Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
script_standard_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2017-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 <addresstype.h>
6#include <key.h>
7#include <key_io.h>
8#include <script/script.h>
10#include <script/solver.h>
11#include <test/data/bip341_wallet_vectors.json.h>
12#include <test/util/common.h>
14#include <univalue.h>
15#include <util/check.h>
16#include <util/strencodings.h>
17
18#include <boost/test/unit_test.hpp>
19
20using namespace util::hex_literals;
21
23
29
31{
32 CKey keys[3];
33 CPubKey pubkeys[3];
34 for (int i = 0; i < 3; i++) {
35 keys[i].MakeNewKey(true);
36 pubkeys[i] = keys[i].GetPubKey();
37 }
38
39 CScript s;
40 std::vector<std::vector<unsigned char> > solutions;
41
42 // TxoutType::PUBKEY
43 s.clear();
44 s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
46 BOOST_CHECK_EQUAL(solutions.size(), 1U);
47 BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
48
49 // TxoutType::PUBKEYHASH
50 s.clear();
51 s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
53 BOOST_CHECK_EQUAL(solutions.size(), 1U);
54 BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
55
56 // TxoutType::SCRIPTHASH
57 CScript redeemScript(s); // initialize with leftover P2PKH script
58 s.clear();
61 BOOST_CHECK_EQUAL(solutions.size(), 1U);
63
64 // TxoutType::MULTISIG
65 s.clear();
66 s << OP_1 <<
67 ToByteVector(pubkeys[0]) <<
68 ToByteVector(pubkeys[1]) <<
71 BOOST_CHECK_EQUAL(solutions.size(), 4U);
72 BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1}));
73 BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
74 BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
75 BOOST_CHECK(solutions[3] == std::vector<unsigned char>({2}));
76
77 s.clear();
78 s << OP_2 <<
79 ToByteVector(pubkeys[0]) <<
80 ToByteVector(pubkeys[1]) <<
81 ToByteVector(pubkeys[2]) <<
84 BOOST_CHECK_EQUAL(solutions.size(), 5U);
85 BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2}));
86 BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
87 BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
88 BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2]));
89 BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3}));
90
91 // TxoutType::NULL_DATA
92 s.clear();
93 s << OP_RETURN <<
94 std::vector<unsigned char>({0}) <<
95 std::vector<unsigned char>({75}) <<
96 std::vector<unsigned char>({255});
99
100 // TxoutType::WITNESS_V0_KEYHASH
101 s.clear();
102 s << OP_0 << ToByteVector(pubkeys[0].GetID());
104 BOOST_CHECK_EQUAL(solutions.size(), 1U);
105 BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
106
107 // TxoutType::WITNESS_V0_SCRIPTHASH
109 CSHA256().Write(redeemScript.data(), redeemScript.size())
110 .Finalize(scriptHash.begin());
111
112 s.clear();
115 BOOST_CHECK_EQUAL(solutions.size(), 1U);
117
118 // TxoutType::WITNESS_V1_TAPROOT
119 s.clear();
122 BOOST_CHECK_EQUAL(solutions.size(), 1U);
124
125 // TxoutType::WITNESS_UNKNOWN
126 s.clear();
129 BOOST_CHECK_EQUAL(solutions.size(), 2U);
130 BOOST_CHECK(solutions[0] == std::vector<unsigned char>{16});
132
133 // TxoutType::ANCHOR
134 s.clear();
135 s << OP_1 << ANCHOR_BYTES;
137 BOOST_CHECK(solutions.empty());
138
139 // Sanity-check IsPayToAnchor
140 int version{-1};
141 std::vector<unsigned char> witness_program;
142 BOOST_CHECK(s.IsPayToAnchor());
143 BOOST_CHECK(s.IsWitnessProgram(version, witness_program));
145
146 // TxoutType::NONSTANDARD
147 s.clear();
148 s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
150}
151
153{
154 CKey key = GenerateRandomKey();
155 CPubKey pubkey = key.GetPubKey();
156
157 CScript s;
158 std::vector<std::vector<unsigned char> > solutions;
159
160 // TxoutType::PUBKEY with incorrectly sized pubkey
161 s.clear();
164
165 // TxoutType::PUBKEYHASH with incorrectly sized key hash
166 s.clear();
169
170 // TxoutType::SCRIPTHASH with incorrectly sized script hash
171 s.clear();
174
175 // TxoutType::MULTISIG 0/2
176 s.clear();
177 s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
179
180 // TxoutType::MULTISIG 2/1
181 s.clear();
182 s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
184
185 // TxoutType::MULTISIG n = 2 with 1 pubkey
186 s.clear();
187 s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
189
190 // TxoutType::MULTISIG n = 1 with 0 pubkeys
191 s.clear();
192 s << OP_1 << OP_1 << OP_CHECKMULTISIG;
194
195 // TxoutType::NULL_DATA with other opcodes
196 s.clear();
199
200 // TxoutType::WITNESS_V0_{KEY,SCRIPT}HASH with incorrect program size (-> consensus-invalid, i.e. non-standard)
201 s.clear();
204
205 // TxoutType::WITNESS_V1_TAPROOT with incorrect program size (-> undefined, but still policy-valid)
206 s.clear();
209 s.clear();
212
213 // TxoutType::ANCHOR but wrong witness version
214 s.clear();
215 s << OP_2 << ANCHOR_BYTES;
216 BOOST_CHECK(!s.IsPayToAnchor());
218
219 // TxoutType::ANCHOR but wrong 2-byte data push
220 s.clear();
222 BOOST_CHECK(!s.IsPayToAnchor());
224}
225
227{
228 CKey key = GenerateRandomKey();
229 CPubKey pubkey = key.GetPubKey();
230
231 CScript s;
232 CTxDestination address;
233
234 // TxoutType::PUBKEY
235 s.clear();
236 s << ToByteVector(pubkey) << OP_CHECKSIG;
237 BOOST_CHECK(!ExtractDestination(s, address));
238 BOOST_CHECK(std::get<PubKeyDestination>(address) == PubKeyDestination(pubkey));
239
240 // TxoutType::PUBKEYHASH
241 s.clear();
243 BOOST_CHECK(ExtractDestination(s, address));
244 BOOST_CHECK(std::get<PKHash>(address) == PKHash(pubkey));
245
246 // TxoutType::SCRIPTHASH
247 CScript redeemScript(s); // initialize with leftover P2PKH script
248 s.clear();
250 BOOST_CHECK(ExtractDestination(s, address));
251 BOOST_CHECK(std::get<ScriptHash>(address) == ScriptHash(redeemScript));
252
253 // TxoutType::MULTISIG
254 s.clear();
255 s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
256 BOOST_CHECK(!ExtractDestination(s, address));
257
258 // TxoutType::NULL_DATA
259 s.clear();
261 BOOST_CHECK(!ExtractDestination(s, address));
262
263 // TxoutType::WITNESS_V0_KEYHASH
264 s.clear();
265 s << OP_0 << ToByteVector(pubkey.GetID());
266 BOOST_CHECK(ExtractDestination(s, address));
268 CHash160().Write(pubkey).Finalize(keyhash);
269 BOOST_CHECK(std::get<WitnessV0KeyHash>(address) == keyhash);
270
271 // TxoutType::WITNESS_V0_SCRIPTHASH
272 s.clear();
274 CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(scripthash.begin());
276 BOOST_CHECK(ExtractDestination(s, address));
277 BOOST_CHECK(std::get<WitnessV0ScriptHash>(address) == scripthash);
278
279 // TxoutType::WITNESS_V1_TAPROOT
280 s.clear();
281 auto xpk = XOnlyPubKey(pubkey);
282 s << OP_1 << ToByteVector(xpk);
283 BOOST_CHECK(ExtractDestination(s, address));
284 BOOST_CHECK(std::get<WitnessV1Taproot>(address) == WitnessV1Taproot(xpk));
285
286 // TxoutType::ANCHOR
287 s.clear();
288 s << OP_1 << ANCHOR_BYTES;
289 BOOST_CHECK(ExtractDestination(s, address));
290 BOOST_CHECK(std::get<PayToAnchor>(address) == PayToAnchor());
291
292 // TxoutType::WITNESS_UNKNOWN with unknown version
293 // -> segwit version 1 with an undefined program size (33 bytes in this test case)
294 s.clear();
295 s << OP_1 << ToByteVector(pubkey);
296 BOOST_CHECK(ExtractDestination(s, address));
298 BOOST_CHECK(std::get<WitnessUnknown>(address) == unk_v1);
299 s.clear();
300 // -> segwit versions 2+ are not specified yet
301 s << OP_2 << ToByteVector(xpk);
302 BOOST_CHECK(ExtractDestination(s, address));
304 BOOST_CHECK(std::get<WitnessUnknown>(address) == unk_v2);
305}
306
308{
309 CKey keys[3];
310 CPubKey pubkeys[3];
311 for (int i = 0; i < 3; i++) {
312 keys[i].MakeNewKey(true);
313 pubkeys[i] = keys[i].GetPubKey();
314 }
315
316 CScript expected, result;
317
318 // PKHash
319 expected.clear();
320 expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
321 result = GetScriptForDestination(PKHash(pubkeys[0]));
322 BOOST_CHECK(result == expected);
323
324 // CScriptID
325 CScript redeemScript(result);
326 expected.clear();
329 BOOST_CHECK(result == expected);
330
331 // CNoDestination
332 expected.clear();
334 BOOST_CHECK(result == expected);
335
336 // GetScriptForRawPubKey
337 expected.clear();
338 expected << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
339 result = GetScriptForRawPubKey(pubkeys[0]);
340 BOOST_CHECK(result == expected);
341
342 // GetScriptForMultisig
343 expected.clear();
344 expected << OP_2 <<
345 ToByteVector(pubkeys[0]) <<
346 ToByteVector(pubkeys[1]) <<
347 ToByteVector(pubkeys[2]) <<
349 result = GetScriptForMultisig(2, std::vector<CPubKey>(pubkeys, pubkeys + 3));
350 BOOST_CHECK(result == expected);
351
352 // WitnessV0KeyHash
353 expected.clear();
354 expected << OP_0 << ToByteVector(pubkeys[0].GetID());
356 BOOST_CHECK(result == expected);
357 result = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
358 BOOST_CHECK(result == expected);
359
360 // WitnessV0ScriptHash (multisig)
362 witnessScript << OP_1 << ToByteVector(pubkeys[0]) << OP_1 << OP_CHECKMULTISIG;
363
365 CSHA256().Write(witnessScript.data(), witnessScript.size())
366 .Finalize(scriptHash.begin());
367
368 expected.clear();
369 expected << OP_0 << ToByteVector(scriptHash);
371 BOOST_CHECK(result == expected);
372
373 // WitnessV1Taproot
374 auto xpk = XOnlyPubKey(pubkeys[0]);
375 expected.clear();
376 expected << OP_1 << ToByteVector(xpk);
378 BOOST_CHECK(result == expected);
379
380 // PayToAnchor
381 expected.clear();
382 expected << OP_1 << ANCHOR_BYTES;
384 BOOST_CHECK(result == expected);
385}
386
388{
429 BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({2,2,2,3,4,5,6,7,8,9,10,11,12,14,14,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,31,31,31,31,31,31,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,128}), true);
430 BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({128,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1}), true);
431 BOOST_CHECK_EQUAL(TaprootBuilder::ValidDepths({129,129,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1}), false);
432
433 XOnlyPubKey key_inner{"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"_hex_u8};
434 XOnlyPubKey key_1{"c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5"_hex_u8};
435 XOnlyPubKey key_2{"f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9"_hex_u8};
438 constexpr uint256 hash_3{"31fe7061656bea2a36aa60a2f7ef940578049273746935d296426dc0afd86b68"};
439
441 BOOST_CHECK(builder.IsValid());
442 BOOST_CHECK(builder.IsComplete());
443 builder.Add(2, script_2, 0xc0);
444 BOOST_CHECK(builder.IsValid());
445 BOOST_CHECK(!builder.IsComplete());
446 builder.AddOmitted(2, hash_3);
447 BOOST_CHECK(builder.IsValid());
448 BOOST_CHECK(!builder.IsComplete());
449 builder.Add(1, script_1, 0xc0);
450 BOOST_CHECK(builder.IsValid());
451 BOOST_CHECK(builder.IsComplete());
452 builder.Finalize(key_inner);
453 BOOST_CHECK(builder.IsValid());
454 BOOST_CHECK(builder.IsComplete());
455 BOOST_CHECK_EQUAL(EncodeDestination(builder.GetOutput()), "bc1pj6gaw944fy0xpmzzu45ugqde4rz7mqj5kj0tg8kmr5f0pjq8vnaqgynnge");
456}
457
459{
461
463 Assert(tests.read(json_tests::bip341_wallet_vectors));
464
465 const auto& vectors = tests["scriptPubKey"];
466
467 for (const auto& vec : vectors.getValues()) {
469 std::map<std::pair<std::vector<unsigned char>, int>, int> scriptposes;
470 std::function<void (const UniValue&, int)> parse_tree = [&](const UniValue& node, int depth) {
471 if (node.isNull()) return;
472 if (node.isObject()) {
473 auto script = ParseHex(node["script"].get_str());
474 int idx = node["id"].getInt<int>();
475 int leaf_version = node["leafVersion"].getInt<int>();
476 scriptposes[{script, leaf_version}] = idx;
477 spktest.Add(depth, script, leaf_version);
478 } else {
479 parse_tree(node[0], depth + 1);
480 parse_tree(node[1], depth + 1);
481 }
482 };
483 parse_tree(vec["given"]["scriptTree"], 0);
484 spktest.Finalize(XOnlyPubKey(ParseHex(vec["given"]["internalPubkey"].get_str())));
485 BOOST_CHECK_EQUAL(HexStr(GetScriptForDestination(spktest.GetOutput())), vec["expected"]["scriptPubKey"].get_str());
486 BOOST_CHECK_EQUAL(EncodeDestination(spktest.GetOutput()), vec["expected"]["bip350Address"].get_str());
487 auto spend_data = spktest.GetSpendData();
488 BOOST_CHECK_EQUAL(vec["intermediary"]["merkleRoot"].isNull(), spend_data.merkle_root.IsNull());
489 if (!spend_data.merkle_root.IsNull()) {
490 BOOST_CHECK_EQUAL(vec["intermediary"]["merkleRoot"].get_str(), HexStr(spend_data.merkle_root));
491 }
492 BOOST_CHECK_EQUAL(spend_data.scripts.size(), scriptposes.size());
493 for (const auto& scriptpos : scriptposes) {
494 BOOST_CHECK(spend_data.scripts[scriptpos.first] == control_set{ParseHex(vec["expected"]["scriptPathControlBlocks"][scriptpos.second].get_str())});
495 }
496 }
497}
498
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a scriptPubKey for the destination.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
const std::vector< unsigned char > ANCHOR_BYTES
Witness program for Pay-to-Anchor output script type.
#define Assert(val)
Identity function.
Definition check.h:119
A hasher class for Bitcoin's 160-bit hash (SHA-256 + RIPEMD-160).
Definition hash.h:57
CHash160 & Write(std::span< const unsigned char > input)
Definition hash.h:70
void Finalize(std::span< unsigned char > output)
Definition hash.h:63
An encapsulated private key.
Definition key.h:46
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition key.cpp:184
An encapsulated public key.
Definition pubkey.h:43
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition pubkey.h:169
A hasher class for SHA-256.
Definition sha256.h:14
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition sha256.cpp:725
CSHA256 & Write(const unsigned char *data, size_t len)
Definition sha256.cpp:699
Serialized script, used inside transaction inputs and outputs.
Definition script.h:406
void clear()
Definition script.h:569
bool IsPayToAnchor() const
Definition script.cpp:207
A reference to a CScript: the Hash160 of its serialization.
Definition script.h:597
Utility class to construct Taproot outputs from internal key and script tree.
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
256-bit opaque blob.
Definition uint256.h:196
static const uint256 ONE
Definition uint256.h:205
static const uint256 ZERO
Definition uint256.h:204
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
Definition hash.h:100
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
CKey GenerateRandomKey(bool compressed) noexcept
Definition key.cpp:354
std::string EncodeDestination(const CTxDestination &dest)
Definition key_io.cpp:292
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
#define BOOST_CHECK_EQUAL(v1, v2)
Definition object.cpp:17
#define BOOST_CHECK(expr)
Definition object.cpp:16
@ OP_2
Definition script.h:86
@ OP_CHECKMULTISIG
Definition script.h:193
@ OP_CHECKSIG
Definition script.h:191
@ OP_16
Definition script.h:100
@ OP_EQUAL
Definition script.h:147
@ OP_DUP
Definition script.h:126
@ OP_HASH160
Definition script.h:188
@ OP_1
Definition script.h:84
@ OP_ADD
Definition script.h:162
@ OP_9
Definition script.h:93
@ OP_3
Definition script.h:87
@ OP_11
Definition script.h:95
@ OP_0
Definition script.h:77
@ OP_RETURN
Definition script.h:112
@ OP_EQUALVERIFY
Definition script.h:148
std::vector< unsigned char > ToByteVector(const T &in)
Definition script.h:68
BOOST_AUTO_TEST_CASE(dest_default_is_no_dest)
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
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition solver.cpp:218
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition solver.cpp:213
@ WITNESS_V1_TAPROOT
@ WITNESS_UNKNOWN
Only for Witness versions not already defined above.
@ ANCHOR
anyone can spend script
@ WITNESS_V0_SCRIPTHASH
@ NULL_DATA
unspendable OP_RETURN script that carries data
@ WITNESS_V0_KEYHASH
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
Basic testing setup.
std::map< std::pair< std::vector< unsigned char >, int >, std::set< std::vector< unsigned char >, ShortestVectorFirstComparator > > scripts
Map from (script, leaf_version) to (sets of) control blocks.
CTxDestination subtype to encode any future Witness version.
Definition addresstype.h:95
std::vector< uint16_t > keys
constexpr std::array tests
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82