Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
bip352_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2026-present 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#include <chainparams.h>
7#include <coins.h>
8#include <span.h>
9#include <addresstype.h>
10#include <policy/policy.h>
11#include <script/interpreter.h>
12#include <script/script.h>
13#include <script/script_error.h>
14#include <script/solver.h>
15#include <test/data/bip352_send_and_receive_vectors.json.h>
16
18
19#include <boost/test/unit_test.hpp>
20#include <test/util/json.h>
21#include <vector>
22#include <util/chaintype.h>
23#include <util/strencodings.h>
24#include <streams.h>
25
26namespace bip352 {
28
30 CKey output;
31 std::vector<unsigned char> hex_data = ParseHex(hex);
32 output.Set(hex_data.begin(), hex_data.end(), true);
33 return output;
34};
35
37{
39 BOOST_REQUIRE(tests.read(json_tests::bip352_send_and_receive_vectors));
40
41 for (const auto& vec : tests.getValues()) {
42 // run sending tests
43 BOOST_TEST_MESSAGE(vec["comment"].get_str());
44
45 for (const auto& sender : vec["sending"].getValues()) {
46 const UniValue& given = sender["given"];
47 const UniValue& expected = sender["expected"];
48
49 std::vector<COutPoint> outpoints;
50 std::vector<CKey> keys;
51 std::vector<KeyPair> taproot_keys;
52 for (const auto& input : given["vin"].getValues()) {
53 COutPoint outpoint{Txid::FromHex(input["txid"].get_str()).value(), input["vout"].getInt<uint32_t>()};
54 outpoints.push_back(outpoint);
55 const auto& spk_bytes = ParseHex(input["prevout"]["scriptPubKey"]["hex"].get_str());
56 CScript spk = CScript(spk_bytes.begin(), spk_bytes.end());
57 const auto& script_sig_bytes = ParseHex(input["scriptSig"].get_str());
59 CTxIn txin{outpoint, script_sig};
60 // read the field txWitness as a stream and write txWitness >> witness.stack;
61 const auto witness_str = ParseHex(input["txinwitness"].get_str());
62 if (!witness_str.empty()) {
63 SpanReader(witness_str) >> txin.scriptWitness.stack;
64 }
65
66 // check if this is a silent payments input by trying to extract the public key
67 const auto& pubkey = GetPubKeyFromInput(txin, spk);
68 if (pubkey.has_value()) {
69 std::vector<std::vector<unsigned char>> solutions;
72 taproot_keys.emplace_back(ParseHexToCKey(input["private_key"].get_str()).ComputeKeyPair(nullptr));
73 } else {
74 keys.emplace_back(ParseHexToCKey(input["private_key"].get_str()));
75 }
76 }
77 }
78 if (taproot_keys.empty() && keys.empty()) {
79 BOOST_CHECK(expected["outputs"].getValues()[0].empty());
80 continue;
81 }
82 // silent payments logic
83 auto smallest_outpoint = std::min_element(outpoints.begin(), outpoints.end(), BIP352Comparator());
84 std::map<size_t, SilentPaymentsDestination> sp_dests;
85 const std::vector<UniValue>& silent_payments_addresses = given["recipients"].getValues();
86 size_t sp_index = 0;
87 for (size_t i = 0; i < silent_payments_addresses.size(); ++i) {
88 auto sp = DecodeSilentPaymentsAddress(silent_payments_addresses[i]["address"].get_str(), Params());
89 BOOST_REQUIRE(sp.has_value());
90 if (!silent_payments_addresses[i]["scan_pub_key"].isNull()) {
91 BOOST_CHECK_EQUAL(HexStr(sp->GetScanPubKey()), silent_payments_addresses[i]["scan_pub_key"].get_str());
92 BOOST_CHECK_EQUAL(HexStr(sp->GetSpendPubKey()), silent_payments_addresses[i]["spend_pub_key"].get_str());
93 }
94 size_t count = silent_payments_addresses[i]["count"].isNull() ? 1 : (size_t)silent_payments_addresses[i]["count"].getInt<int>();
95 for (size_t j = 0; j < count; ++j) {
96 sp_dests.emplace(sp_index++, *sp);
97 }
98 }
100 // This means the inputs summed to zero, which realistically would only happen maliciously. In this case, just move on
101 if (!sp_tr_dests.has_value()) {
102 // Check that we actually expect zero outputs to be generated for this test
103 BOOST_CHECK(expected["outputs"].getValues()[0].empty());
104 continue;
105 }
106 bool match = false;
107 for (const auto& candidate_set : expected["outputs"].getValues()) {
108 BOOST_CHECK(sp_tr_dests->size() == candidate_set.size());
109 std::vector<WitnessV1Taproot> expected_spks;
110 for (const auto& output : candidate_set.getValues()) {
111 const WitnessV1Taproot tap{XOnlyPubKey(ParseHex(output.get_str()))};
112 expected_spks.push_back(tap);
113 }
114 match = std::all_of(sp_tr_dests->begin(), sp_tr_dests->end(), [&](const auto& entry) {
115 return std::find(expected_spks.begin(), expected_spks.end(), entry.second) != expected_spks.end();
116 });
117 if (match) break;
118 }
120 }
121
122 // Test receiving
123 for (const auto& recipient : vec["receiving"].getValues()) {
124
125 const UniValue& given = recipient["given"];
126 const UniValue& expected = recipient["expected"];
127
128 std::vector<CTxIn> vin;
129 std::map<COutPoint, Coin> coins;
130 for (const auto& input : given["vin"].getValues()) {
131 COutPoint outpoint{Txid::FromHex(input["txid"].get_str()).value(), input["vout"].getInt<uint32_t>()};
132 const auto& spk_bytes = ParseHex(input["prevout"]["scriptPubKey"]["hex"].get_str());
133 CScript spk = CScript(spk_bytes.begin(), spk_bytes.end());
134 const auto& script_sig_bytes = ParseHex(input["scriptSig"].get_str());
136 CTxIn txin{outpoint, script_sig};
137 // read the field txWitness as a stream and write txWitness >> witness.stack;
138 const auto witness_str = ParseHex(input["txinwitness"].get_str());
139 if (!witness_str.empty()) {
140 SpanReader(witness_str) >> txin.scriptWitness.stack;
141 }
142 vin.push_back(txin);
143 coins[outpoint] = Coin{CTxOut{{}, spk}, 0, false};
144 }
146 // If we don't get any tweak data from the transaction inputs, it is not a silent payment
147 // transaction, so we skip it.
148 if (!pub_tweak_data.has_value()) {
149 // Make sure this is expected and not just a failure of the GetSilentPaymentsPrevoutsSummary func
150 BOOST_CHECK(expected["outputs"].empty());
151 continue;
152 }
153 std::vector<XOnlyPubKey> output_pub_keys;
154 for (const auto& pubkey : given["outputs"].getValues()) {
155 output_pub_keys.emplace_back(ParseHex(pubkey.get_str()));
156 }
157
158 CKey scan_priv_key = ParseHexToCKey(given["key_material"]["scan_priv_key"].get_str());
159 CKey spend_priv_key = ParseHexToCKey(given["key_material"]["spend_priv_key"].get_str());
161 auto expected_address = DecodeSilentPaymentsAddress(expected["addresses"][0].get_str(), Params());
162 BOOST_REQUIRE(expected_address.has_value());
164
165 // The change label is registered automatically; only non-change labels need registering.
166 SilentPaymentsReceiver receiver{scan_priv_key, sp_address.GetSpendPubKey()};
167 auto given_labels{given["labels"].getValues()};
168 for (size_t i = 0; i < given_labels.size(); i++) {
169 const uint32_t m = given_labels[i].getInt<uint32_t>();
170 const SilentPaymentsDestination labeled_addr = (m == 0) ? receiver.GetChangeDestination() : receiver.GenerateLabeledAddress(m);
171 // expected["addresses"] contains the base silent payments address (at index 0)
172 // followed by the labeled addresses
173 auto sp = DecodeSilentPaymentsAddress(expected["addresses"][i+1].get_str(), Params());
174 BOOST_REQUIRE(sp.has_value());
176 }
177
178 // Scanning
179 const auto& found_outputs = receiver.Scan(*pub_tweak_data, output_pub_keys);
180 BOOST_REQUIRE(found_outputs.has_value());
181 // The transaction may be a silent payments transaction, but it does not contain any outputs for us,
182 // so we continue to the next transaction.
183 if (found_outputs->empty()) {
184 BOOST_CHECK(expected["outputs"].empty());
185 continue;
186 }
187 if (!expected["n_outputs"].isNull()) {
188 BOOST_CHECK_EQUAL(found_outputs->size(), (size_t)expected["n_outputs"].getInt<int>());
189 } else {
190 std::map<XOnlyPubKey, uint256> expected_outputs;
191 for (const auto& output : expected["outputs"].getValues()) {
192 expected_outputs.emplace(
193 XOnlyPubKey{ParseHex(output["pub_key"].get_str())},
194 uint256{ParseHex(output["priv_key_tweak"].get_str())});
195 }
196 BOOST_TEST_MESSAGE(found_outputs->size());
197 BOOST_REQUIRE_EQUAL(found_outputs->size(), expected_outputs.size());
198 for (const auto& output : *found_outputs) {
199 const auto expected_output = expected_outputs.find(output.output);
200 BOOST_REQUIRE(expected_output != expected_outputs.end());
201 BOOST_CHECK(output.tweak == expected_output->second);
202 }
203 }
204 }
205 }
206}
207
209{
210 CKey sender_key = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000001");
211 CKey scan_key = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000002");
212 CKey spend_key = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000003");
214 std::map<size_t, SilentPaymentsDestination> sp_dests{{2, sp_dest}, {5, sp_dest}};
215 COutPoint smallest_outpoint{Txid::FromHex("0000000000000000000000000000000000000000000000000000000000000001").value(), 0};
216
218
219 BOOST_REQUIRE(generated.has_value());
220 BOOST_CHECK_EQUAL(generated->size(), sp_dests.size());
221 BOOST_CHECK_EQUAL(generated->count(0), 0);
222 BOOST_CHECK_EQUAL(generated->count(1), 0);
223 BOOST_CHECK_EQUAL(generated->count(2), 1);
224 BOOST_CHECK_EQUAL(generated->count(5), 1);
225}
226
228{
229 CKey key = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000001");
230 CPubKey pubkey = key.GetPubKey();
231 COutPoint eligible_outpoint{Txid::FromHex("0000000000000000000000000000000000000000000000000000000000000001").value(), 0};
232 COutPoint unknown_segwit_outpoint{Txid::FromHex("0000000000000000000000000000000000000000000000000000000000000002").value(), 0};
233
235 eligible_input.scriptWitness.stack.emplace_back(64, 0);
236 eligible_input.scriptWitness.stack.emplace_back(pubkey.begin(), pubkey.end());
237
238 std::map<COutPoint, Coin> coins;
239 coins[eligible_outpoint] = Coin{CTxOut{{}, GetScriptForDestination(WitnessV0KeyHash{pubkey})}, 0, false};
240 coins[unknown_segwit_outpoint] = Coin{CTxOut{{}, GetScriptForDestination(WitnessUnknown{2, std::vector<unsigned char>(32, 1)})}, 0, false};
241
244}
245
247{
248 CKey sender_key = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000001");
249 CKey scan_key = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000002");
250 CKey spend_key = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000003");
251 const COutPoint outpoint{Txid::FromHex("0000000000000000000000000000000000000000000000000000000000000001").value(), 0};
252
253 std::map<size_t, SilentPaymentsDestination> sp_dests;
254 sp_dests.emplace(0, SilentPaymentsDestination::From(scan_key.GetPubKey(), spend_key.GetPubKey()).value());
256 BOOST_REQUIRE(sp_tr_dests.has_value());
257 const XOnlyPubKey expected_output{sp_tr_dests->begin()->second};
258
259 CTxIn txin{outpoint};
260 const CPubKey sender_pubkey{sender_key.GetPubKey()};
261 txin.scriptWitness.stack.emplace_back();
262 txin.scriptWitness.stack.emplace_back(sender_pubkey.begin(), sender_pubkey.end());
263
264 std::map<COutPoint, Coin> coins;
265 coins[outpoint] = Coin{CTxOut{{}, GetScriptForDestination(WitnessV0KeyHash{sender_pubkey})}, 0, false};
267 BOOST_REQUIRE(prevouts_summary.has_value());
268
269 std::vector<XOnlyPubKey> output_pub_keys;
270 output_pub_keys.emplace_back(ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
271 output_pub_keys.push_back(expected_output);
272
273 SilentPaymentsReceiver receiver{scan_key, spend_key.GetPubKey()};
274 const auto found_outputs = receiver.Scan(*prevouts_summary, output_pub_keys);
275 BOOST_REQUIRE(found_outputs.has_value());
276 BOOST_REQUIRE_EQUAL(found_outputs->size(), 1);
277 BOOST_CHECK(found_outputs->front().output == expected_output);
278}
279
281{
282 // P2PKH scriptSigs are third-party malleable. Construct one that contains an OP_CHECKSIG with a
283 // bogus (but strictly DER-encoded) signature, followed by a conditional push of a wrong pubkey:
284 //
285 // <sig> <pubkey> <bogus_sig> OP_OVER OP_CHECKSIG OP_IF <wrong_pubkey> OP_ENDIF
286 //
287 // In real validation the OP_CHECKSIG fails, the OP_IF branch is skipped and the final stack is
288 // <sig> <pubkey>, i.e. the spend is still valid and the pubkey must be extracted from it.
289 const CKey key = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000001");
290 const CPubKey pubkey = key.GetPubKey();
291 const CPubKey wrong_pubkey = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000002").GetPubKey();
293
295 tx.vin.emplace_back(COutPoint{Txid::FromHex("0000000000000000000000000000000000000000000000000000000000000001").value(), 0});
296 std::vector<unsigned char> sig;
297 BOOST_REQUIRE(key.Sign(SignatureHash(spk, tx, 0, SIGHASH_ALL, /*amount=*/0, SigVersion::BASE), sig));
298 sig.push_back(SIGHASH_ALL);
299 const std::vector<unsigned char> bogus_sig{ParseHex("300602010102010101")}; // r=1, s=1, SIGHASH_ALL
300 tx.vin[0].scriptSig = CScript() << sig << ToByteVector(pubkey) << bogus_sig << OP_OVER << OP_CHECKSIG
302 const CTxIn& txin{tx.vin[0]};
303
304 // Verify that the malleated spend is consensus-valid
309
311 BOOST_REQUIRE(extracted_pubkey.has_value());
312 BOOST_CHECK(std::get<CPubKey>(*extracted_pubkey) == pubkey);
313}
314
316{
317 CKey scan_key = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000002");
318 CPubKey spend_pubkey = ParseHexToCKey("0000000000000000000000000000000000000000000000000000000000000003").GetPubKey();
319 SilentPaymentsReceiver receiver{scan_key, spend_pubkey};
320
321 BOOST_REQUIRE_EQUAL(receiver.GetLabels().size(), 1);
322 const SilentPaymentsLabel& label = receiver.GetLabels().begin()->first;
323
325 label.Serialize(stream);
327 BOOST_REQUIRE(roundtripped.has_value());
328 BOOST_CHECK(*roundtripped == label);
329 BOOST_CHECK(stream.empty());
330}
331
333{
334 struct ValidVector {
335 ChainType chain;
336 std::string address;
337 std::string scan_pubkey;
338 std::string spend_pubkey;
339 std::string extension_data;
340 uint8_t version;
341 };
344 "sp1qq22l5s6l9460ww6t4tkzsy2a7zejurcmzz35pt0ffrzk5erlaykdcqugecjjnjqf7ggq39vl6wexjlm00n66z94v675n7wcux6d2krr68gdjvfn2",
345 "0295fa435f2d74f73b4baaec28115df0b32e0f1b10a340ade948c56a647fe92cdc",
346 "0388ce2529c809f21008959fd3b2697f6f7cf5a116acd7a93f3b1c369aab0c7a3a",
347 "", 0},
349 "sp1pq22l5s6l9460ww6t4tkzsy2a7zejurcmzz35pt0ffrzk5erlaykdcqugecjjnjqf7ggq39vl6wexjlm00n66z94v675n7wcux6d2krr68t02m0h0s8cwhy",
350 "0295fa435f2d74f73b4baaec28115df0b32e0f1b10a340ade948c56a647fe92cdc",
351 "0388ce2529c809f21008959fd3b2697f6f7cf5a116acd7a93f3b1c369aab0c7a3a",
352 "deadbeef", 1},
354 "tsp1qqthpye3hdcnydp9temp7yduy6uw5h2nw8u9fz677ccrna280qwj3uq60zeqs3zfpj3age62h4ljq2lyawwdecmk8a545yysk4x3tu3skjqm2thu6",
355 "02ee1266376e264684abcec3e23784d71d4baa6e3f0a916bdec6073ea8ef03a51e",
356 "034f1641088921947a8ce957afe4057c9d739b9c6ec7ed2b421216a9a2be461690",
357 "", 0},
359 "tsp1qqvrl2accqtatgtkllv5fdsfapq6vqnrr0uf2whhmjyas4teg7ljfqqlpec0ze90m97t3stv92p5ekzkcwzmpx0x8p7ljj9xqcjjpvnfurc00tjn9",
360 "0307f5771802fab42edffb2896c13d0834c04c637f12a75efb913b0aaf28f7e490",
361 "03e1ce1e2c95fb2f97182d8550699b0ad870b6133cc70fbf2914c0c4a4164d3c1e",
362 "", 0},
364 "sprt1qq04xgllnqqfdlxjkr355rmsahfn9t8l6sd0k20t4uka4c73nvvpnwqu4kvg0nm62d5jtmqp54lkc7tul0dzt25ejtn4f80505z3u0h5jag59rdg4",
365 "03ea647ff30012df9a561c6941ee1dba66559ffa835f653d75e5bb5c7a33630337",
366 "0395b310f9ef4a6d24bd8034afed8f2f9f7b44b553325cea93be8fa0a3c7de92ea",
367 "", 0},
368 };
369
370 for (const auto& vec : valid_vectors) {
371 SelectParams(vec.chain);
372
373 auto sp = DecodeSilentPaymentsAddress(vec.address, Params());
374 BOOST_REQUIRE_MESSAGE(sp.has_value(), vec.address);
375 BOOST_CHECK_EQUAL(sp->GetVersion(), vec.version);
376 BOOST_CHECK_EQUAL(HexStr(sp->GetScanPubKey()), vec.scan_pubkey);
377 BOOST_CHECK_EQUAL(HexStr(sp->GetSpendPubKey()), vec.spend_pubkey);
378 BOOST_CHECK_EQUAL(HexStr(sp->GetExtensionData()), vec.extension_data);
379
380 // Bech32(m) is case-insensitive as a whole; an all-uppercase address must decode identically.
381 std::string flipped = ToUpper(vec.address);
385 }
386
387 // `chain` is the one chain (if any) whose HRP matches the address, where `expected_error`
388 // applies; on every other chain the HRP check itself is expected to fail first.
389 // `chain_independent` addresses fail bech32m checksum verification before the HRP is even
390 // compared, so `expected_error` applies on every chain instead.
391 struct InvalidVector {
392 std::string address;
393 std::string expected_error;
394 std::optional<ChainType> chain = std::nullopt;
395 bool chain_independent = false;
396 };
398 {"spx1qq22l5s6l9460ww6t4tkzsy2a7zejurcmzz35pt0ffrzk5erlaykdcqugecjjnjqf7ggq39vl6wexjlm00n66z94v675n7wcux6d2krr68g37pn04",
399 "Invalid or unsupported prefix for Silent Payments address (expected sp, got spx)."}, // wrong HRP; never matches any chain
400 {"sp1qq22l5s6l9460ww6t4tkzsy2a7zejurcmzz35pt0ffrzk5erlaykdcqugecjjnjqf7ggq39vl6wexjlm00n66z94v675n7wcux6d2krr68gcwu9kg",
401 "Silent Payments address must use Bech32m checksum", std::nullopt, /*chain_independent=*/true}, // bad checksum
402 {"sp1qqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq2qugecjjnjqf7ggq39vl6wexjlm00n66z94v675n7wcux6d2krr68g25havg",
403 "Invalid Silent payments address", ChainType::MAIN}, // invalid scan pubkey
404 {"sp1qq22l5s6l9460ww6t4tkzsy2a7zejurcmzz35pt0ffrzk5erlaykdcqsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq57qc9nf",
405 "Invalid Silent payments address", ChainType::MAIN}, // invalid spend pubkey
406 {"sp1lq22l5s6l9460ww6t4tkzsy2a7zejurcmzz35pt0ffrzk5erlaykdcqugecjjnjqf7ggq39vl6wexjlm00n66z94v675n7wcux6d2krr68gaafydt",
407 "This implementation only supports Silent payments addresses v0 through v30 (got 31).", ChainType::MAIN}, // reserved version 31
408 {"sp1qq22l5s6l9460ww6t4tkzsy2a7zejurcmzz35pt0ffrzk5erlaykdcznsxsn",
409 "Silent payments data payload is too small (expected at least 66, got 33).", ChainType::MAIN}, // payload too small
410 {"tsp1qqthpye3hdcnydp9temp7yduy6uw5h2nw8u9fz677ccrna280qwj3uq60zeqs3zfpj3age62h4ljq2lyawwdecmk8a545yysk4x3tu3skjqm2thum",
411 "Silent Payments address must use Bech32m checksum", std::nullopt, /*chain_independent=*/true}, // bad checksum
412 {"sp1qqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqf26rn7",
413 "Silent Payments address must use Bech32m checksum", std::nullopt, /*chain_independent=*/true}, // bad checksum
414 {"sprt1qqgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq2qu4kvg0nm62d5jtmqp54lkc7tul0dzt25ejtn4f80505z3u0h5jagf9zkp5",
415 "Invalid Silent payments address", ChainType::REGTEST}, // invalid scan pubkey
416 };
417
418 for (const auto& vec : invalid_vectors) {
420 SelectParams(chain);
421 auto sp = DecodeSilentPaymentsAddress(vec.address, Params());
422 BOOST_REQUIRE_MESSAGE(!sp.has_value(), vec.address);
423 if (vec.chain_independent || chain == vec.chain) {
424 BOOST_CHECK_EQUAL(sp.error(), vec.expected_error);
425 } else {
426 BOOST_CHECK_MESSAGE(sp.error().starts_with("Invalid or unsupported prefix for Silent Payments address"), sp.error());
427 }
428 }
429 }
430
432}
433
435} // namespace bip352
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
void SelectParams(const ChainType chain)
Sets the params returned by Params() to those for the given chain type.
const CChainParams & Params()
Return the currently selected parameters.
ChainType
Definition chaintype.h:12
An encapsulated private key.
Definition key.h:46
bool Sign(const uint256 &hash, std::vector< unsigned char > &vchSig, bool grind=true, uint32_t test_case=0) const
Create a DER-serialized signature.
Definition key.cpp:210
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition key.cpp:184
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition key.h:114
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 * end() const
Definition pubkey.h:124
const unsigned char * begin() const
Definition pubkey.h:123
Serialized script, used inside transaction inputs and outputs.
Definition script.h:406
An input of a transaction.
Definition transaction.h:63
CScriptWitness scriptWitness
Only serialized through CTransaction.
Definition transaction.h:68
An output of a transaction.
A UTXO entry.
Definition coins.h:46
Double ended buffer combining vector and stream-like interfaces.
Definition streams.h:165
Minimal stream for reading from an existing byte array by std::span.
Definition streams.h:83
const std::vector< UniValue > & getValues() const
Int getInt() const
Definition univalue.h:143
const unsigned char * begin() const
Definition pubkey.h:304
static std::optional< SilentPaymentsLabel > Unserialize(Stream &s)
Definition bip352.h:150
void Serialize(Stream &s) const
Definition bip352.h:144
A silent payments recipient's scanning identity.
Definition bip352.h:239
static std::optional< transaction_identifier > FromHex(std::string_view hex)
256-bit opaque blob.
Definition uint256.h:196
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition hex_base.cpp:30
uint256 SignatureHash(const CScript &scriptCode, const T &txTo, unsigned int nIn, int32_t nHashType, const CAmount &amount, SigVersion sigversion, const PrecomputedTransactionData *cache, SigHashCache *sighash_cache)
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, script_verify_flags flags, const BaseSignatureChecker &checker, ScriptError *serror)
@ BASE
Bare scripts and BIP16 P2SH-wrapped redeemscripts.
@ SIGHASH_ALL
Definition interpreter.h:32
@ ASSERT_FAIL
Abort execution through assertion failure (for consensus code)
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
CKey ParseHexToCKey(std::string_view hex)
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
BOOST_AUTO_TEST_CASE(bip352_send_and_receive_test_vectors)
#define BOOST_CHECK_EQUAL(v1, v2)
Definition object.cpp:17
#define BOOST_CHECK(expr)
Definition object.cpp:16
constexpr script_verify_flags MANDATORY_SCRIPT_VERIFY_FLAGS
Mandatory script verification flags that all new transactions must comply with for them to be valid.
Definition policy.h:98
@ OP_IF
Definition script.h:105
@ OP_CHECKSIG
Definition script.h:191
@ OP_ENDIF
Definition script.h:110
@ OP_OVER
Definition script.h:128
std::vector< unsigned char > ToByteVector(const T &in)
Definition script.h:68
std::string ScriptErrorString(const ScriptError serror)
enum ScriptError_t ScriptError
@ SCRIPT_ERR_OK
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
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
Basic testing setup.
A mutable version of CTransaction.
std::vector< CTxIn > vin
std::vector< std::vector< unsigned char > > stack
Definition script.h:581
CTxDestination subtype to encode any future Witness version.
Definition addresstype.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
std::vector< uint16_t > keys
static int count
constexpr std::array tests
std::string ToUpper(std::string_view str)
Returns the uppercase equivalent of the given string.
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82