Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
bip352.cpp
Go to the documentation of this file.
1// Copyright (c) 2023 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <common/bip352.h>
6
7#include <addresstype.h>
8#include <bech32.h>
9#include <chainparams.h>
10#include <coins.h>
11#include <hash.h>
12#include <key.h>
14#include <pubkey.h>
15#include <script/interpreter.h>
16#include <script/script.h>
17#include <script/sign.h>
18#include <script/solver.h>
19#include <script/verify_flags.h>
20#include <secp256k1.h>
21#include <secp256k1_extrakeys.h>
23#include <span.h>
24#include <streams.h>
25#include <tinyformat.h>
26#include <uint256.h>
27#include <util/strencodings.h>
28
29#include <algorithm>
30#include <cassert>
31#include <cstddef>
32#include <optional>
33#include <span>
34#include <type_traits>
35#include <utility>
36
37namespace bip352 {
38
41
44
46
48{
49 return m_prevouts_summary.get();
50}
51
52std::optional<SilentPaymentsDestination> SilentPaymentsDestination::From(
53 const CPubKey& scan_pubkey,
54 const CPubKey& spend_pubkey,
55 uint8_t version,
56 std::span<const unsigned char> extension_data
57) {
58 if (version >= 31) return std::nullopt;
59 if (version == 0 && !extension_data.empty()) {
60 // V0 address has no extension data
61 return std::nullopt;
62 }
63 if (!scan_pubkey.IsFullyValid() || !scan_pubkey.IsCompressed()) return std::nullopt;
64 if (!spend_pubkey.IsFullyValid() || !spend_pubkey.IsCompressed()) return std::nullopt;
65 return SilentPaymentsDestination(version, scan_pubkey, spend_pubkey, extension_data);
66}
67
69 const std::string& str, const CChainParams& params)
70{
71 static constexpr size_t SILENT_PAYMENTS_V0_DATA_SIZE = 66;
72 static constexpr size_t SP_PUBKEYS_SIZE = 2 * CPubKey::COMPRESSED_SIZE;
73
75 if (dec.encoding != bech32::Encoding::BECH32M) {
76 return util::Unexpected{"Silent Payments address must use Bech32m checksum"};
77 }
78 if (dec.hrp != params.SilentPaymentsHRP()) {
79 return util::Unexpected{strprintf("Invalid or unsupported prefix for Silent Payments address (expected %s, got %s).", params.SilentPaymentsHRP(), dec.hrp)};
80 }
81 if (dec.data.empty()) {
82 return util::Unexpected{"Empty Bech32 data section"};
83 }
84 std::vector<unsigned char> data;
85 if (!ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, dec.data.begin() + 1, dec.data.end())) {
86 return util::Unexpected{"Invalid padding in Silent payments address (Bech32m data section)"};
87 }
89 return util::Unexpected{strprintf("Silent payments data payload is too small (expected at least %d, got %d).", SILENT_PAYMENTS_V0_DATA_SIZE, data.size())};
90 }
91 const uint8_t version = dec.data[0];
92 if (version >= 31) {
93 return util::Unexpected{strprintf("This implementation only supports Silent payments addresses v0 through v30 (got %d).", version)};
94 }
95 if (version == 0 && data.size() != SILENT_PAYMENTS_V0_DATA_SIZE) {
96 return util::Unexpected{strprintf("Silent payments version is v0 but data is not the correct size (expected %d, got %d).", SILENT_PAYMENTS_V0_DATA_SIZE, data.size())};
97 }
98 CPubKey scan_pubkey{data.begin(), data.begin() + CPubKey::COMPRESSED_SIZE};
100 std::span<unsigned char> extension_data{data.data() + SP_PUBKEYS_SIZE, data.size() - SP_PUBKEYS_SIZE};
101 auto sp_dest = SilentPaymentsDestination::From(scan_pubkey, spend_pubkey, version, extension_data);
102 if (!sp_dest) {
103 return util::Unexpected{"Invalid Silent payments address"};
104 }
105 return *sp_dest;
106}
107
109 m_label = std::make_unique<secp256k1_silentpayments_label>(label);
111 assert(ret);
112}
113
114std::optional<SilentPaymentsLabel> SilentPaymentsLabel::FromBytes(std::span<const unsigned char, CPubKey::COMPRESSED_SIZE> vch)
115{
118 return std::nullopt;
119 }
121}
122
126
128 : m_label{std::make_unique<secp256k1_silentpayments_label>(*label.m_label)}
129{
130 memcpy(m_vch, label.m_vch, CPubKey::COMPRESSED_SIZE);
131}
133 if (this != &label) {
134 m_label = std::make_unique<secp256k1_silentpayments_label>(*label.m_label);
136 }
137 return *this;
138}
139
143
144std::optional<PubKey> GetPubKeyFromInput(const CTxIn& txin, const CScript& spk)
145{
146 std::vector<std::vector<unsigned char>> solutions;
147 const TxoutType type = Solver(spk, solutions);
148
149 if (type == TxoutType::WITNESS_V1_TAPROOT) {
150 const auto& stack = txin.scriptWitness.stack;
151 if (stack.empty()) return std::nullopt;
152 const bool has_annex = !stack.back().empty() && stack.back()[0] == ANNEX_TAG;
153 const size_t effective_size = stack.size() - (has_annex ? 1 : 0);
154
155 if (effective_size > 1) {
156 // BIP-352: skip script-path spends using NUMS-H internal key.
157 // Validate control block size before checking internal key.
158 const auto& control = stack[effective_size - 1];
159 if (control.size() < TAPROOT_CONTROL_BASE_SIZE ||
162 return std::nullopt;
163 }
164 if (std::equal(WitnessV1Taproot::NUMS_H.begin(), WitnessV1Taproot::NUMS_H.end(), control.begin() + 1)) {
165 return std::nullopt;
166 }
167 }
168
169 XOnlyPubKey key{solutions[0]};
170 if (!key.IsFullyValid()) return std::nullopt;
171 return PubKey{key};
172 }
173
174 if (type == TxoutType::WITNESS_V0_KEYHASH) {
175 const auto& stack = txin.scriptWitness.stack;
176 if (stack.empty()) return std::nullopt;
177 CPubKey key{stack.back()};
178 if (!key.IsCompressed() || !key.IsFullyValid()) return std::nullopt;
179 return PubKey{key};
180 }
181
182 if (type == TxoutType::PUBKEYHASH) {
183 // For P2PKH public key extraction, BIP-352 states: "The receiver MUST parse the scriptSig
184 // for the public key, even if the scriptSig does not match the template specified. This is
185 // to address the third-party malleability of P2PKH scriptSigs."
186 //
187 // Find the preimage of the pubkey hash by iterating through the scriptSig data pushes and
188 // comparing the Hash160 of each 33-byte (compressed) push against the output script. In
189 // standard spends the pubkey is the last push, but due to malleability we can't rely on
190 // that (e.g. `<dummy> OP_DROP` inserted anywhere). Evaluating the scriptSig with a dummy
191 // signature checker isn't safe either, as a malleated scriptSig could then leave a
192 // different pubkey on top of the stack than real validation would.
193 const uint160 pubkey_hash{solutions[0]};
194 auto pc = txin.scriptSig.begin();
195 while (pc < txin.scriptSig.end()) {
197 std::vector<unsigned char> pubkey_candidate;
198 if (!txin.scriptSig.GetOp(pc, opcode, pubkey_candidate)) {
199 return std::nullopt;
200 }
201 if (pubkey_candidate.size() == 33 && Hash160(pubkey_candidate) == pubkey_hash) {
203 if (key.IsFullyValid()) return PubKey{key};
204 }
205 }
206 return std::nullopt;
207 }
208
209 if (type == TxoutType::SCRIPTHASH) {
210 // P2SH-P2WPKH only: eval scriptSig, verify redeem script is P2WPKH. Unlike P2PKH above,
211 // evaluating is safe here, as consensus (BIP-141) requires the scriptSig to be a single
212 // push of the redeem script.
213 std::vector<std::vector<unsigned char>> stack;
215 return std::nullopt;
216 }
217 if (stack.empty()) return std::nullopt;
218 CScript redeem{stack.back().begin(), stack.back().end()};
219 if (Solver(redeem, solutions) != TxoutType::WITNESS_V0_KEYHASH) return std::nullopt;
220 if (txin.scriptWitness.stack.empty()) return std::nullopt;
221 CPubKey key{txin.scriptWitness.stack.back()};
222 if (!key.IsCompressed() || !key.IsFullyValid()) return std::nullopt;
223 return PubKey{key};
224 }
225
226 return std::nullopt;
227}
228
229static std::optional<PrevoutsSummary> CreateInputPubkeysTweak(
230 const std::vector<CPubKey>& plain_pubkeys,
231 const std::vector<XOnlyPubKey>& taproot_pubkeys,
233{
235 std::vector<secp256k1_pubkey> plain_pubkey_objs;
236 std::vector<secp256k1_pubkey*> plain_pubkey_ptrs;
237 plain_pubkey_objs.reserve(plain_pubkeys.size());
238 plain_pubkey_ptrs.reserve(plain_pubkeys.size());
239 for (const CPubKey& pubkey : plain_pubkeys) {
241 &plain_pubkey_objs.emplace_back(), pubkey.data(), pubkey.size());
242 // This pubkey is expected to be valid because GetPubKeyFromInput()
243 // already called IsFullyValid() before including it here
244 assert(ret);
245 plain_pubkey_ptrs.push_back(&plain_pubkey_objs.back());
246 }
247
248 std::vector<secp256k1_xonly_pubkey> taproot_pubkey_objs;
249 std::vector<secp256k1_xonly_pubkey*> taproot_pubkey_ptrs;
250 taproot_pubkey_objs.reserve(taproot_pubkeys.size());
251 taproot_pubkey_ptrs.reserve(taproot_pubkeys.size());
252 for (const XOnlyPubKey& pubkey : taproot_pubkeys) {
254 &taproot_pubkey_objs.emplace_back(), pubkey.data());
255 // This xonlypubkey is expected to be valid because
256 // GetPubKeyFromInput() already called IsFullyValid()
257 // before including it here
258 assert(ret);
259 taproot_pubkey_ptrs.push_back(&taproot_pubkey_objs.back());
260 }
261
262 std::array<std::byte, 36> smallest_outpoint_ser;
269 );
270 if (!ret) return std::nullopt;
272}
273
274util::Expected<PrevoutsSummary, PrevoutsSummaryError> GetSilentPaymentsPrevoutsSummary(const std::vector<CTxIn>& vin, const std::map<COutPoint, Coin>& coins)
275{
276 // Extract the keys from the inputs
277 // or skip if no valid inputs
278 std::vector<CPubKey> pubkeys;
279 std::vector<XOnlyPubKey> xonly_pubkeys;
280 std::vector<COutPoint> tx_outpoints;
281 for (const CTxIn& txin : vin) {
282 const auto coin_it = coins.find(txin.prevout);
284 const Coin& coin = coin_it->second;
285 int witness_version{0};
286 std::vector<unsigned char> witness_program;
287 // BIP352 v0 skips transactions spending future witness versions.
290 }
291 tx_outpoints.emplace_back(txin.prevout);
292 auto pubkey = GetPubKeyFromInput(txin, coin.out.scriptPubKey);
293 if (pubkey.has_value()) {
294 std::visit([&pubkeys, &xonly_pubkeys](auto&& pubkey) {
295 using T = std::decay_t<decltype(pubkey)>;
296 if constexpr (std::is_same_v<T, CPubKey>) {
297 pubkeys.push_back(pubkey);
298 } else if constexpr (std::is_same_v<T, XOnlyPubKey>) {
299 xonly_pubkeys.push_back(pubkey);
300 }
301 }, *pubkey);
302 }
303 }
304 if (pubkeys.size() + xonly_pubkeys.size() == 0) return util::Unexpected(PrevoutsSummaryError::NOT_ELIGIBLE);
305 auto smallest_outpoint = std::min_element(tx_outpoints.begin(), tx_outpoints.end(), BIP352Comparator());
306 auto tweak = CreateInputPubkeysTweak(pubkeys, xonly_pubkeys, *smallest_outpoint);
308 return std::move(*tweak);
309}
310
311static std::optional<std::vector<secp256k1_xonly_pubkey>> CreateOutputs(
312 const std::vector<SilentPaymentsDestination>& recipients,
313 const std::vector<CKey>& plain_keys,
314 const std::vector<KeyPair>& taproot_keypairs,
316) {
317 bool ret;
318 std::vector<const secp256k1_keypair *> taproot_keypair_ptrs;
319 std::vector<const unsigned char *> plain_key_ptrs;
321 plain_key_ptrs.reserve(plain_keys.size());
322
323 std::vector<secp256k1_silentpayments_recipient> recipient_objs;
324 std::vector<const secp256k1_silentpayments_recipient *> recipient_ptrs;
325 recipient_objs.reserve(recipients.size());
326 recipient_ptrs.reserve(recipients.size());
327
328 std::vector<secp256k1_xonly_pubkey> generated_outputs;
329 std::vector<secp256k1_xonly_pubkey *> generated_output_ptrs;
330 generated_outputs.reserve(recipients.size());
331 generated_output_ptrs.reserve(recipients.size());
332
333 for (size_t i = 0; i < recipients.size(); i++) {
335 ret = secp256k1_ec_pubkey_parse(secp256k1_context_static, &recipient_obj.scan_pubkey, recipients[i].GetScanPubKey().data(), recipients[i].GetScanPubKey().size());
336 assert(ret);
337 ret = secp256k1_ec_pubkey_parse(secp256k1_context_static, &recipient_obj.spend_pubkey, recipients[i].GetSpendPubKey().data(), recipients[i].GetSpendPubKey().size());
338 assert(ret);
339 recipient_obj.index = i;
340 recipient_objs.push_back(recipient_obj);
341 recipient_ptrs.push_back(&recipient_objs[i]);
342
346 }
347
348 for (const auto& key : plain_keys) {
349 if (!key.IsValid()) return std::nullopt;
350 plain_key_ptrs.push_back(UCharCast(key.begin()));
351 }
352 for (const auto& keypair : taproot_keypairs) {
353 if (!keypair.IsValid()) return std::nullopt;
354 taproot_keypair_ptrs.push_back(keypair.GetSecpKeypair());
355 }
356
357 // Serialize the outpoint
358 std::array<std::byte, 36> smallest_outpoint_ser;
360
363 recipient_ptrs.data(), recipient_ptrs.size(),
366 plain_key_ptrs.data(), plain_key_ptrs.size()
367 );
368 if (!ret) return std::nullopt;
369 return generated_outputs;
370}
371
372std::optional<std::map<size_t, WitnessV1Taproot>> GenerateSilentPaymentsTaprootDestinations(const std::map<size_t, SilentPaymentsDestination>& sp_dests, const std::vector<CKey>& plain_keys, const std::vector<KeyPair>& taproot_keys, const COutPoint& smallest_outpoint)
373{
374 if (sp_dests.empty()) return std::map<size_t, WitnessV1Taproot>();
375
376 assert(!smallest_outpoint.IsNull());
377 assert(!plain_keys.empty() || !taproot_keys.empty());
378
379 bool ret;
380 std::map<size_t, WitnessV1Taproot> tr_dests;
381 std::vector<SilentPaymentsDestination> recipients;
382 recipients.reserve(sp_dests.size());
383 for (const auto& [_, addr] : sp_dests) {
384 recipients.push_back(addr);
385 }
386 auto outputs = CreateOutputs(recipients, plain_keys, taproot_keys, smallest_outpoint);
387 // This will fail if any input pubkey is null or
388 // inputs were maliciously crafted to sum to zero
389 if (!outputs) return std::nullopt;
390 assert(sp_dests.size() == outputs->size());
391 size_t output_i{0};
392 for (const auto& [i, _] : sp_dests) {
393 unsigned char xonly_pubkey_bytes[32];
395 assert(ret);
397 output_i++;
398 }
399 return tr_dests;
400}
401
402static const unsigned char* LabelLookupCallback(const unsigned char* key, const void* context) {
403 auto label_context = static_cast<const LabelTweakMap*>(context);
404 auto it = label_context->find(std::span<const unsigned char, CPubKey::COMPRESSED_SIZE>{key, CPubKey::COMPRESSED_SIZE});
405 if (it != label_context->end()) {
406 return it->second.begin();
407 }
408 return nullptr;
409}
410
411static std::pair<SilentPaymentsLabel, uint256> CreateLabel(const CKey& scan_key, const uint32_t m) {
413 unsigned char label_tweak[32];
415 assert(ret);
416 return {SilentPaymentsLabel(label_obj), uint256{label_tweak}};
417}
418
431
433 const LabelTweakMap& labels) : m_scan_key(scan_key), m_spend_pubkey(spend_pubkey), m_labels(labels)
434{
435 m_change_it = m_labels.emplace(CreateLabel(scan_key, 0)).first;
436 m_spend_pubkey_obj = std::make_unique<secp256k1_pubkey>();
438 assert(ret);
439}
440
442
446
453
459
463
464std::optional<std::vector<SilentPaymentsOutput>> SilentPaymentsReceiver::Scan(
466 const std::vector<XOnlyPubKey>& tx_outputs
467) const {
468 bool ret;
469 std::vector<secp256k1_silentpayments_found_output> found_output_objs;
470 std::vector<secp256k1_silentpayments_found_output *> found_output_ptrs;
471 std::vector<secp256k1_xonly_pubkey> tx_output_objs;
472 std::vector<const secp256k1_xonly_pubkey *> tx_output_ptrs;
473 found_output_objs.reserve(tx_outputs.size());
474 found_output_ptrs.reserve(tx_outputs.size());
475 tx_output_objs.reserve(tx_outputs.size());
476 tx_output_ptrs.reserve(tx_outputs.size());
477
480
481 for (const XOnlyPubKey& tx_output : tx_outputs) {
484 if (!ret) {
485 // It is possible that a P2TR output encodes an invalid x-only pubkey.
486 continue;
487 }
488 tx_output_objs.push_back(tx_output_obj);
489 tx_output_ptrs.push_back(&tx_output_objs.back());
490 found_output_objs.emplace_back();
491 found_output_ptrs.push_back(&found_output_objs.back());
492 }
493 if (tx_output_ptrs.empty()) return std::vector<SilentPaymentsOutput>{};
494
495 // Scan the outputs!
499 tx_output_ptrs.data(), tx_output_ptrs.size(),
501 prevouts_summary.Get(),
502 m_spend_pubkey_obj.get(),
504 &m_labels
505 );
506 if (!ret) return std::nullopt;
507
508 std::vector<SilentPaymentsOutput> outputs;
509 for (size_t i = 0; i < n_found_outputs; i++) {
512 assert(ret);
513 sp_output.tweak = uint256{found_output_objs[i].tweak};
514 if (found_output_objs[i].found_with_label) {
516 }
517 outputs.emplace_back(std::move(sp_output));
518 }
519 return outputs;
520}
521}; // namespace bip352
int ret
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition chainparams.h:77
const std::string & SilentPaymentsHRP() const
An encapsulated private key.
Definition key.h:46
bool IsValid() const
Check whether this private key is valid.
Definition key.h:134
const std::byte * begin() const
Definition key.h:130
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition key.cpp:184
const std::byte * data() const
Definition key.h:129
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition transaction.h:30
An encapsulated public key.
Definition pubkey.h:43
const unsigned char * data() const
Definition pubkey.h:122
bool IsCompressed() const
Check whether this is a compressed public key.
Definition pubkey.h:209
static constexpr unsigned int COMPRESSED_SIZE
Definition pubkey.h:49
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition pubkey.cpp:320
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition pubkey.h:121
const unsigned char * begin() const
Definition pubkey.h:123
Serialized script, used inside transaction inputs and outputs.
Definition script.h:406
bool IsWitnessProgram(int &version, std::vector< unsigned char > &program) const
Definition script.cpp:250
An input of a transaction.
Definition transaction.h:63
CScript scriptPubKey
A UTXO entry.
Definition coins.h:46
CTxOut out
unspent transaction output
Definition coins.h:49
Minimal stream for writing to an existing span of bytes.
Definition streams.h:130
const unsigned char * end() const
Definition pubkey.h:305
const unsigned char * begin() const
Definition pubkey.h:304
static const XOnlyPubKey NUMS_H
Nothing Up My Sleeve point H Used as an internal key for provably disabling the key path spend see BI...
Definition pubkey.h:195
constexpr unsigned char * begin()
Definition uint256.h:101
PrevoutsSummary(const secp256k1_silentpayments_prevouts_summary &prevouts_summary)
Definition bip352.cpp:39
std::unique_ptr< secp256k1_silentpayments_label > m_label
Definition bip352.h:107
SilentPaymentsLabel & operator=(SilentPaymentsLabel &&) noexcept
unsigned char m_vch[CPubKey::COMPRESSED_SIZE]
Definition bip352.h:108
const secp256k1_silentpayments_label * Get() const LIFETIMEBOUND
Definition bip352.cpp:140
SilentPaymentsLabel(const secp256k1_silentpayments_label &label)
Definition bip352.cpp:108
static std::optional< SilentPaymentsLabel > FromBytes(std::span< const unsigned char, CPubKey::COMPRESSED_SIZE > vch)
Parses raw bytes into a fully valid label returns std::nullopt if vch is not a validly-encoded label.
Definition bip352.cpp:114
SilentPaymentsDestination GetChangeDestination() const
Get this recipient's silent payments change destination.
Definition bip352.cpp:460
SilentPaymentsDestination BuildLabeledDestination(const SilentPaymentsLabel &label) const
Definition bip352.cpp:447
SilentPaymentsReceiver(const CKey &scan_key, const CPubKey &spend_pubkey, const LabelTweakMap &labels={})
Definition bip352.cpp:432
const LabelTweakMap & GetLabels() const
Get this recipient's registered labels, including the change label.
Definition bip352.cpp:443
LabelTweakMap::const_iterator m_change_it
Definition bip352.h:245
SilentPaymentsDestination GenerateLabeledAddress(uint32_t m)
Register label m (e.g.
Definition bip352.cpp:454
std::optional< std::vector< SilentPaymentsOutput > > Scan(const PrevoutsSummary &prevouts_summary, const std::vector< XOnlyPubKey > &tx_outputs) const
Scan a transaction for silent payments outputs.
Definition bip352.cpp:464
std::unique_ptr< secp256k1_pubkey > m_spend_pubkey_obj
Definition bip352.h:243
T & back()
Definition prevector.h:408
160-bit opaque blob.
Definition uint256.h:184
256-bit opaque blob.
Definition uint256.h:196
The util::Expected class provides a standard way for low-level functions to return either error value...
Definition expected.h:44
The util::Unexpected class represents an unexpected value stored in util::Expected.
Definition expected.h:21
static const PrecomputedData data
Precomputed COutPoint and CCoins values.
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
Definition hash.h:100
#define T(expected, seed, data)
bool EvalScript(std::vector< std::vector< unsigned char > > &stack, const CScript &script, script_verify_flags flags, const BaseSignatureChecker &checker, SigVersion sigversion, ScriptExecutionData &execdata, ScriptError *serror)
@ BASE
Bare scripts and BIP16 P2SH-wrapped redeemscripts.
constexpr size_t TAPROOT_CONTROL_NODE_SIZE
constexpr size_t TAPROOT_CONTROL_MAX_SIZE
constexpr script_verify_flags SCRIPT_VERIFY_NONE
Script verification flags.
Definition interpreter.h:48
constexpr size_t TAPROOT_CONTROL_BASE_SIZE
secp256k1_context * GetSecp256k1SignContext()
Access the secp256k1 context used for signing and MuSig2 nonce generation.
Definition key.cpp:443
static int tweak(const secp256k1_context *ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache)
Definition musig.c:64
@ BECH32M
Bech32m encoding as defined in BIP350.
@ SILENT_PAYMENTS
BIP352 imposed 1023 character limit on Bech32m encoded silent payment addresses. This guarantees find...
Definition bech32.h:42
DecodeResult Decode(const std::string &str, CharLimit limit)
Decode a Bech32 or Bech32m string.
Definition bech32.cpp:373
util::Expected< PrevoutsSummary, PrevoutsSummaryError > GetSilentPaymentsPrevoutsSummary(const std::vector< CTxIn > &vin, const std::map< COutPoint, Coin > &coins)
Get silent payments public data from transaction inputs.
Definition bip352.cpp:274
std::optional< PubKey > GetPubKeyFromInput(const CTxIn &txin, const CScript &spk)
Get the public key from an input.
Definition bip352.cpp:144
std::optional< std::map< size_t, WitnessV1Taproot > > GenerateSilentPaymentsTaprootDestinations(const std::map< size_t, SilentPaymentsDestination > &sp_dests, const std::vector< CKey > &plain_keys, const std::vector< KeyPair > &taproot_keys, const COutPoint &smallest_outpoint)
Generate silent payments taproot destinations.
Definition bip352.cpp:372
@ NOT_ELIGIBLE
This transaction is not eligible to be scanned for silent payments outputs: either none of its inputs...
@ MISSING_COIN
A prevout referenced by an input in vin has no corresponding entry in coins.
static const unsigned char * LabelLookupCallback(const unsigned char *key, const void *context)
Definition bip352.cpp:402
static std::pair< SilentPaymentsLabel, uint256 > CreateLabel(const CKey &scan_key, const uint32_t m)
Definition bip352.cpp:411
util::Expected< SilentPaymentsDestination, std::string > DecodeSilentPaymentsAddress(const std::string &str, const CChainParams &params)
Decode a BIP352 "sp1..." address. Returns the destination, or an error message on failure.
Definition bip352.cpp:68
static std::optional< std::vector< secp256k1_xonly_pubkey > > CreateOutputs(const std::vector< SilentPaymentsDestination > &recipients, const std::vector< CKey > &plain_keys, const std::vector< KeyPair > &taproot_keypairs, const COutPoint &smallest_outpoint)
Definition bip352.cpp:311
std::map< SilentPaymentsLabel, uint256, std::less<> > LabelTweakMap
Definition bip352.h:227
std::variant< CPubKey, XOnlyPubKey > PubKey
Definition bip352.h:39
static CPubKey CreateLabeledSpendPubKey(const CPubKey &spend_pubkey, const SilentPaymentsLabel &label)
Definition bip352.cpp:419
static std::optional< PrevoutsSummary > CreateInputPubkeysTweak(const std::vector< CPubKey > &plain_pubkeys, const std::vector< XOnlyPubKey > &taproot_pubkeys, const COutPoint &smallest_outpoint)
Definition bip352.cpp:229
opcodetype
Script opcodes.
Definition script.h:75
constexpr unsigned int ANNEX_TAG
Definition script.h:59
SECP256K1_API int secp256k1_ec_pubkey_serialize(const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey *pubkey, unsigned int flags) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Serialize a pubkey object into a serialized byte sequence.
Definition secp256k1.c:282
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a variable-length public key into the pubkey object.
Definition secp256k1.c:264
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition secp256k1.h:216
SECP256K1_API const secp256k1_context *const secp256k1_context_static
A built-in constant secp256k1 context object with static storage duration, to be used in conjunction ...
Definition secp256k1.h:237
SECP256K1_API int secp256k1_xonly_pubkey_serialize(const secp256k1_context *ctx, unsigned char *output32, const secp256k1_xonly_pubkey *pubkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Serialize an xonly_pubkey object into a 32-byte sequence.
Definition main_impl.h:51
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse(const secp256k1_context *ctx, secp256k1_xonly_pubkey *pubkey, const unsigned char *input32) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a 32-byte sequence into a xonly_pubkey object.
Definition main_impl.h:29
SECP256K1_API int secp256k1_silentpayments_recipient_label_serialize(const secp256k1_context *ctx, unsigned char *out33, const secp256k1_silentpayments_label *label) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Serialize a Silent Payments label.
Definition main_impl.h:374
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_prevouts_summary_create(const secp256k1_context *ctx, secp256k1_silentpayments_prevouts_summary *prevouts_summary, const unsigned char *outpoint_smallest36, const secp256k1_xonly_pubkey *const *xonly_pubkeys, size_t n_xonly_pubkeys, const secp256k1_pubkey *const *pubkeys, size_t n_pubkeys) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Compute Silent Payments prevouts summary from prevout public keys and transaction inputs.
Definition main_impl.h:484
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_label_parse(const secp256k1_context *ctx, secp256k1_silentpayments_label *label, const unsigned char *in33) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a Silent Payments label.
Definition main_impl.h:358
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_sender_create_outputs(const secp256k1_context *ctx, secp256k1_xonly_pubkey **generated_outputs, const secp256k1_silentpayments_recipient **recipients, size_t n_recipients, const unsigned char *outpoint_smallest36, const secp256k1_keypair *const *keypairs, size_t n_keypairs, const unsigned char *const *seckeys, size_t n_seckeys) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5)
Create Silent Payments outputs for recipient(s).
Definition main_impl.h:187
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_create_labeled_spend_pubkey(const secp256k1_context *ctx, secp256k1_pubkey *labeled_spend_pubkey, const secp256k1_pubkey *unlabeled_spend_pubkey, const secp256k1_silentpayments_label *label) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Create Silent Payments labeled spend public key.
Definition main_impl.h:426
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_scan_outputs(const secp256k1_context *ctx, secp256k1_silentpayments_found_output **found_outputs, uint32_t *n_found_outputs, const secp256k1_xonly_pubkey *const *tx_outputs, size_t n_tx_outputs, const unsigned char *scan_key32, const secp256k1_silentpayments_prevouts_summary *prevouts_summary, const secp256k1_pubkey *unlabeled_spend_pubkey, secp256k1_silentpayments_label_lookup label_lookup, const void *label_context) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8)
Scan for Silent Payments transaction outputs.
Definition main_impl.h:598
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_silentpayments_recipient_label_create(const secp256k1_context *ctx, secp256k1_silentpayments_label *label, unsigned char *label_tweak32, const unsigned char *scan_key32, uint32_t m) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Create Silent Payments label tweak and label.
Definition main_impl.h:389
const BaseSignatureChecker & DUMMY_CHECKER
A signature checker that accepts all signatures.
Definition sign.cpp:958
static unsigned char smallest_outpoint[36]
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition solver.cpp:141
TxoutType
Definition solver.h:22
@ WITNESS_V1_TAPROOT
@ WITNESS_V0_KEYHASH
unsigned char * UCharCast(char *c)
Definition span.h:95
static std::optional< SilentPaymentsDestination > From(const CPubKey &scan_pubkey, const CPubKey &spend_pubkey, uint8_t version=0, std::span< const unsigned char > extension_data={})
Definition bip352.cpp:52
Opaque data structure that holds a parsed and valid public key.
Definition secp256k1.h:62
Opaque data structure that holds a Silent Payments label.
Opaque data structure that holds Silent Payments prevouts summary data.
The data from a single recipient address.
Opaque data structure that holds a parsed and valid "x-only" public key.
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
consteval auto _(util::TranslatedLiteral str)
Definition translation.h:79
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82
assert(!tx.IsCoinBase())
WalletContext context