Bitcoin Core 22.99.0
P2P Digital Currency
script_standard_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2017-2020 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 <key.h>
6#include <key_io.h>
7#include <script/script.h>
9#include <script/standard.h>
11#include <util/strencodings.h>
12
13#include <boost/test/unit_test.hpp>
14
15
16BOOST_FIXTURE_TEST_SUITE(script_standard_tests, BasicTestingSetup)
17
18BOOST_AUTO_TEST_CASE(dest_default_is_no_dest)
19{
20 CTxDestination dest;
22}
23
24BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
25{
26 CKey keys[3];
27 CPubKey pubkeys[3];
28 for (int i = 0; i < 3; i++) {
29 keys[i].MakeNewKey(true);
30 pubkeys[i] = keys[i].GetPubKey();
31 }
32
33 CScript s;
34 std::vector<std::vector<unsigned char> > solutions;
35
36 // TxoutType::PUBKEY
37 s.clear();
38 s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
40 BOOST_CHECK_EQUAL(solutions.size(), 1U);
41 BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
42
43 // TxoutType::PUBKEYHASH
44 s.clear();
45 s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
47 BOOST_CHECK_EQUAL(solutions.size(), 1U);
48 BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
49
50 // TxoutType::SCRIPTHASH
51 CScript redeemScript(s); // initialize with leftover P2PKH script
52 s.clear();
53 s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
55 BOOST_CHECK_EQUAL(solutions.size(), 1U);
56 BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript)));
57
58 // TxoutType::MULTISIG
59 s.clear();
60 s << OP_1 <<
61 ToByteVector(pubkeys[0]) <<
62 ToByteVector(pubkeys[1]) <<
65 BOOST_CHECK_EQUAL(solutions.size(), 4U);
66 BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1}));
67 BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
68 BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
69 BOOST_CHECK(solutions[3] == std::vector<unsigned char>({2}));
70
71 s.clear();
72 s << OP_2 <<
73 ToByteVector(pubkeys[0]) <<
74 ToByteVector(pubkeys[1]) <<
75 ToByteVector(pubkeys[2]) <<
78 BOOST_CHECK_EQUAL(solutions.size(), 5U);
79 BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2}));
80 BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
81 BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
82 BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2]));
83 BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3}));
84
85 // TxoutType::NULL_DATA
86 s.clear();
87 s << OP_RETURN <<
88 std::vector<unsigned char>({0}) <<
89 std::vector<unsigned char>({75}) <<
90 std::vector<unsigned char>({255});
92 BOOST_CHECK_EQUAL(solutions.size(), 0U);
93
94 // TxoutType::WITNESS_V0_KEYHASH
95 s.clear();
96 s << OP_0 << ToByteVector(pubkeys[0].GetID());
98 BOOST_CHECK_EQUAL(solutions.size(), 1U);
99 BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
100
101 // TxoutType::WITNESS_V0_SCRIPTHASH
102 uint256 scriptHash;
103 CSHA256().Write(redeemScript.data(), redeemScript.size())
104 .Finalize(scriptHash.begin());
105
106 s.clear();
107 s << OP_0 << ToByteVector(scriptHash);
109 BOOST_CHECK_EQUAL(solutions.size(), 1U);
110 BOOST_CHECK(solutions[0] == ToByteVector(scriptHash));
111
112 // TxoutType::WITNESS_V1_TAPROOT
113 s.clear();
116 BOOST_CHECK_EQUAL(solutions.size(), 1U);
117 BOOST_CHECK(solutions[0] == ToByteVector(uint256::ZERO));
118
119 // TxoutType::WITNESS_UNKNOWN
120 s.clear();
123 BOOST_CHECK_EQUAL(solutions.size(), 2U);
124 BOOST_CHECK(solutions[0] == std::vector<unsigned char>{16});
125 BOOST_CHECK(solutions[1] == ToByteVector(uint256::ONE));
126
127 // TxoutType::NONSTANDARD
128 s.clear();
129 s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
131}
132
133BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
134{
135 CKey key;
136 CPubKey pubkey;
137 key.MakeNewKey(true);
138 pubkey = key.GetPubKey();
139
140 CScript s;
141 std::vector<std::vector<unsigned char> > solutions;
142
143 // TxoutType::PUBKEY with incorrectly sized pubkey
144 s.clear();
145 s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG;
147
148 // TxoutType::PUBKEYHASH with incorrectly sized key hash
149 s.clear();
152
153 // TxoutType::SCRIPTHASH with incorrectly sized script hash
154 s.clear();
155 s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL;
157
158 // TxoutType::MULTISIG 0/2
159 s.clear();
160 s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
162
163 // TxoutType::MULTISIG 2/1
164 s.clear();
165 s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
167
168 // TxoutType::MULTISIG n = 2 with 1 pubkey
169 s.clear();
170 s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
172
173 // TxoutType::MULTISIG n = 1 with 0 pubkeys
174 s.clear();
175 s << OP_1 << OP_1 << OP_CHECKMULTISIG;
177
178 // TxoutType::NULL_DATA with other opcodes
179 s.clear();
180 s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD;
182
183 // TxoutType::WITNESS_UNKNOWN with incorrect program size
184 s.clear();
185 s << OP_0 << std::vector<unsigned char>(19, 0x01);
187}
188
189BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
190{
191 CKey key;
192 CPubKey pubkey;
193 key.MakeNewKey(true);
194 pubkey = key.GetPubKey();
195
196 CScript s;
197 CTxDestination address;
198
199 // TxoutType::PUBKEY
200 s.clear();
201 s << ToByteVector(pubkey) << OP_CHECKSIG;
202 BOOST_CHECK(ExtractDestination(s, address));
203 BOOST_CHECK(std::get<PKHash>(address) == PKHash(pubkey));
204
205 // TxoutType::PUBKEYHASH
206 s.clear();
208 BOOST_CHECK(ExtractDestination(s, address));
209 BOOST_CHECK(std::get<PKHash>(address) == PKHash(pubkey));
210
211 // TxoutType::SCRIPTHASH
212 CScript redeemScript(s); // initialize with leftover P2PKH script
213 s.clear();
214 s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
215 BOOST_CHECK(ExtractDestination(s, address));
216 BOOST_CHECK(std::get<ScriptHash>(address) == ScriptHash(redeemScript));
217
218 // TxoutType::MULTISIG
219 s.clear();
220 s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
221 BOOST_CHECK(!ExtractDestination(s, address));
222
223 // TxoutType::NULL_DATA
224 s.clear();
225 s << OP_RETURN << std::vector<unsigned char>({75});
226 BOOST_CHECK(!ExtractDestination(s, address));
227
228 // TxoutType::WITNESS_V0_KEYHASH
229 s.clear();
230 s << OP_0 << ToByteVector(pubkey.GetID());
231 BOOST_CHECK(ExtractDestination(s, address));
232 WitnessV0KeyHash keyhash;
233 CHash160().Write(pubkey).Finalize(keyhash);
234 BOOST_CHECK(std::get<WitnessV0KeyHash>(address) == keyhash);
235
236 // TxoutType::WITNESS_V0_SCRIPTHASH
237 s.clear();
238 WitnessV0ScriptHash scripthash;
239 CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(scripthash.begin());
240 s << OP_0 << ToByteVector(scripthash);
241 BOOST_CHECK(ExtractDestination(s, address));
242 BOOST_CHECK(std::get<WitnessV0ScriptHash>(address) == scripthash);
243
244 // TxoutType::WITNESS_UNKNOWN with unknown version
245 s.clear();
246 s << OP_1 << ToByteVector(pubkey);
247 BOOST_CHECK(ExtractDestination(s, address));
248 WitnessUnknown unk;
249 unk.length = 33;
250 unk.version = 1;
251 std::copy(pubkey.begin(), pubkey.end(), unk.program);
252 BOOST_CHECK(std::get<WitnessUnknown>(address) == unk);
253}
254
255BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_)
256{
257 CKey keys[3];
258 CPubKey pubkeys[3];
259 for (int i = 0; i < 3; i++) {
260 keys[i].MakeNewKey(true);
261 pubkeys[i] = keys[i].GetPubKey();
262 }
263
264 CScript expected, result;
265
266 // PKHash
267 expected.clear();
268 expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
269 result = GetScriptForDestination(PKHash(pubkeys[0]));
270 BOOST_CHECK(result == expected);
271
272 // CScriptID
273 CScript redeemScript(result);
274 expected.clear();
275 expected << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
276 result = GetScriptForDestination(ScriptHash(redeemScript));
277 BOOST_CHECK(result == expected);
278
279 // CNoDestination
280 expected.clear();
282 BOOST_CHECK(result == expected);
283
284 // GetScriptForRawPubKey
285 expected.clear();
286 expected << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
287 result = GetScriptForRawPubKey(pubkeys[0]);
288 BOOST_CHECK(result == expected);
289
290 // GetScriptForMultisig
291 expected.clear();
292 expected << OP_2 <<
293 ToByteVector(pubkeys[0]) <<
294 ToByteVector(pubkeys[1]) <<
295 ToByteVector(pubkeys[2]) <<
297 result = GetScriptForMultisig(2, std::vector<CPubKey>(pubkeys, pubkeys + 3));
298 BOOST_CHECK(result == expected);
299
300 // WitnessV0KeyHash
301 expected.clear();
302 expected << OP_0 << ToByteVector(pubkeys[0].GetID());
304 BOOST_CHECK(result == expected);
305 result = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
306 BOOST_CHECK(result == expected);
307
308 // WitnessV0ScriptHash (multisig)
309 CScript witnessScript;
310 witnessScript << OP_1 << ToByteVector(pubkeys[0]) << OP_1 << OP_CHECKMULTISIG;
311
312 uint256 scriptHash;
313 CSHA256().Write(witnessScript.data(), witnessScript.size())
314 .Finalize(scriptHash.begin());
315
316 expected.clear();
317 expected << OP_0 << ToByteVector(scriptHash);
318 result = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
319 BOOST_CHECK(result == expected);
320}
321
322BOOST_AUTO_TEST_CASE(script_standard_taproot_builder)
323{
364 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);
365 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);
366 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);
367
368 XOnlyPubKey key_inner{ParseHex("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")};
369 XOnlyPubKey key_1{ParseHex("c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5")};
370 XOnlyPubKey key_2{ParseHex("f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9")};
371 CScript script_1 = CScript() << ToByteVector(key_1) << OP_CHECKSIG;
372 CScript script_2 = CScript() << ToByteVector(key_2) << OP_CHECKSIG;
373 uint256 hash_3 = uint256S("31fe7061656bea2a36aa60a2f7ef940578049273746935d296426dc0afd86b68");
374
375 TaprootBuilder builder;
376 BOOST_CHECK(builder.IsValid() && builder.IsComplete());
377 builder.Add(2, script_2, 0xc0);
378 BOOST_CHECK(builder.IsValid() && !builder.IsComplete());
379 builder.AddOmitted(2, hash_3);
380 BOOST_CHECK(builder.IsValid() && !builder.IsComplete());
381 builder.Add(1, script_1, 0xc0);
382 BOOST_CHECK(builder.IsValid() && builder.IsComplete());
383 builder.Finalize(key_inner);
384 BOOST_CHECK(builder.IsValid() && builder.IsComplete());
385 BOOST_CHECK_EQUAL(EncodeDestination(builder.GetOutput()), "bc1pj6gaw944fy0xpmzzu45ugqde4rz7mqj5kj0tg8kmr5f0pjq8vnaqgynnge");
386}
387
unsigned char * begin()
Definition: hash_type.h:18
A hasher class for Bitcoin's 160-bit hash (SHA-256 + RIPEMD-160).
Definition: hash.h:49
void Finalize(Span< unsigned char > output)
Definition: hash.h:55
CHash160 & Write(Span< const unsigned char > input)
Definition: hash.h:62
An encapsulated private key.
Definition: key.h:27
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:160
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:187
An encapsulated public key.
Definition: pubkey.h:33
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:160
const unsigned char * end() const
Definition: pubkey.h:114
const unsigned char * begin() const
Definition: pubkey.h:113
A hasher class for SHA-256.
Definition: sha256.h:14
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha256.cpp:663
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:637
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:406
void clear()
Definition: script.h:549
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:26
Utility class to construct Taproot outputs from internal key and script tree.
Definition: standard.h:226
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
Definition: standard.cpp:462
TaprootBuilder & Add(int depth, const CScript &script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
Definition: standard.cpp:428
bool IsComplete() const
Return whether there were either no leaves, or the leaves form a Huffman tree.
Definition: standard.h:308
static bool ValidDepths(const std::vector< int > &depths)
Check if a list of depths is legal (will lead to IsComplete()).
Definition: standard.cpp:405
bool IsValid() const
Return true if so far all input was valid.
Definition: standard.h:306
TaprootBuilder & AddOmitted(int depth, const uint256 &hash)
Like Add(), but for a Merkle node with a given hash to the tree.
Definition: standard.cpp:441
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
Definition: standard.cpp:451
unsigned char * begin()
Definition: uint256.h:58
size_type size() const
Definition: prevector.h:282
value_type * data()
Definition: prevector.h:528
256-bit opaque blob.
Definition: uint256.h:124
static const uint256 ONE
Definition: uint256.h:130
static const uint256 ZERO
Definition: uint256.h:129
BOOST_AUTO_TEST_SUITE_END()
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
Definition: hash.h:92
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:256
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
@ OP_2
Definition: script.h:78
@ OP_CHECKMULTISIG
Definition: script.h:185
@ OP_CHECKSIG
Definition: script.h:183
@ OP_16
Definition: script.h:92
@ OP_EQUAL
Definition: script.h:139
@ OP_DUP
Definition: script.h:118
@ OP_HASH160
Definition: script.h:180
@ OP_1
Definition: script.h:76
@ OP_ADD
Definition: script.h:154
@ OP_9
Definition: script.h:85
@ OP_3
Definition: script.h:79
@ OP_11
Definition: script.h:87
@ OP_0
Definition: script.h:69
@ OP_RETURN
Definition: script.h:104
@ OP_EQUALVERIFY
Definition: script.h:140
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:60
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: standard.cpp:144
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:320
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:213
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:315
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:332
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:310
@ WITNESS_V1_TAPROOT
@ WITNESS_UNKNOWN
Only for Witness versions not already defined above.
@ WITNESS_V0_SCRIPTHASH
@ NULL_DATA
unspendable OP_RETURN script that carries data
@ WITNESS_V0_KEYHASH
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:157
std::vector< unsigned char > ParseHex(const char *psz)
Basic testing setup.
Definition: setup_common.h:76
CTxDestination subtype to encode any future Witness version.
Definition: standard.h:126
unsigned char program[40]
Definition: standard.h:129
unsigned int length
Definition: standard.h:128
unsigned int version
Definition: standard.h:127
uint256 uint256S(const char *str)
Definition: uint256.h:137