Bitcoin Core 28.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
miniscript_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2019-2022 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 <stdint.h>
6#include <string>
7#include <vector>
8
9#include <test/util/random.h>
11#include <boost/test/unit_test.hpp>
12
13#include <addresstype.h>
14#include <core_io.h>
15#include <hash.h>
16#include <pubkey.h>
17#include <uint256.h>
18#include <crypto/ripemd160.h>
19#include <crypto/sha256.h>
20#include <script/interpreter.h>
21#include <script/miniscript.h>
22#include <script/script_error.h>
24
25namespace {
26
28struct TestData {
30 std::vector<CPubKey> pubkeys;
32 std::map<CPubKey, CKeyID> pkhashes;
33 std::map<CKeyID, CPubKey> pkmap;
34 std::map<XOnlyPubKey, CKeyID> xonly_pkhashes;
35 std::map<CPubKey, std::vector<unsigned char>> signatures;
36 std::map<XOnlyPubKey, std::vector<unsigned char>> schnorr_signatures;
37
38 // Various precomputed hashes
39 std::vector<std::vector<unsigned char>> sha256;
40 std::vector<std::vector<unsigned char>> ripemd160;
41 std::vector<std::vector<unsigned char>> hash256;
42 std::vector<std::vector<unsigned char>> hash160;
43 std::map<std::vector<unsigned char>, std::vector<unsigned char>> sha256_preimages;
44 std::map<std::vector<unsigned char>, std::vector<unsigned char>> ripemd160_preimages;
45 std::map<std::vector<unsigned char>, std::vector<unsigned char>> hash256_preimages;
46 std::map<std::vector<unsigned char>, std::vector<unsigned char>> hash160_preimages;
47
48 TestData()
49 {
50 // All our signatures sign (and are required to sign) this constant message.
51 constexpr uint256 MESSAGE_HASH{"0000000000000000f5cd94e18b6fe77dd7aca9e35c2b0c9cbd86356c80a71065"};
52 // We don't pass additional randomness when creating a schnorr signature.
53 const auto EMPTY_AUX{uint256::ZERO};
54
55 // We generate 255 public keys and 255 hashes of each type.
56 for (int i = 1; i <= 255; ++i) {
57 // This 32-byte array functions as both private key data and hash preimage (31 zero bytes plus any nonzero byte).
58 unsigned char keydata[32] = {0};
59 keydata[31] = i;
60
61 // Compute CPubkey and CKeyID
62 CKey key;
63 key.Set(keydata, keydata + 32, true);
64 CPubKey pubkey = key.GetPubKey();
65 CKeyID keyid = pubkey.GetID();
66 pubkeys.push_back(pubkey);
67 pkhashes.emplace(pubkey, keyid);
68 pkmap.emplace(keyid, pubkey);
69 XOnlyPubKey xonly_pubkey{pubkey};
70 uint160 xonly_hash{Hash160(xonly_pubkey)};
71 xonly_pkhashes.emplace(xonly_pubkey, xonly_hash);
72 pkmap.emplace(xonly_hash, pubkey);
73
74 // Compute ECDSA signatures on MESSAGE_HASH with the private keys.
75 std::vector<unsigned char> sig, schnorr_sig(64);
76 BOOST_CHECK(key.Sign(MESSAGE_HASH, sig));
77 sig.push_back(1); // sighash byte
78 signatures.emplace(pubkey, sig);
79 BOOST_CHECK(key.SignSchnorr(MESSAGE_HASH, schnorr_sig, nullptr, EMPTY_AUX));
80 schnorr_sig.push_back(1); // Maximally sized Schnorr sigs have a sighash byte.
81 schnorr_signatures.emplace(XOnlyPubKey{pubkey}, schnorr_sig);
82
83 // Compute various hashes
84 std::vector<unsigned char> hash;
85 hash.resize(32);
86 CSHA256().Write(keydata, 32).Finalize(hash.data());
87 sha256.push_back(hash);
88 sha256_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
89 CHash256().Write(keydata).Finalize(hash);
90 hash256.push_back(hash);
91 hash256_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
92 hash.resize(20);
93 CRIPEMD160().Write(keydata, 32).Finalize(hash.data());
94 ripemd160.push_back(hash);
95 ripemd160_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
96 CHash160().Write(keydata).Finalize(hash);
97 hash160.push_back(hash);
98 hash160_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
99 }
100 }
101};
102
104std::unique_ptr<const TestData> g_testdata;
105
107enum class ChallengeType {
108 SHA256,
109 RIPEMD160,
110 HASH256,
111 HASH160,
112 OLDER,
113 AFTER,
114 PK
115};
116
117/* With each leaf condition we associate a challenge number.
118 * For hashes it's just the first 4 bytes of the hash. For pubkeys, it's the last 4 bytes.
119 */
120uint32_t ChallengeNumber(const CPubKey& pubkey) { return ReadLE32(pubkey.data() + 29); }
121uint32_t ChallengeNumber(const std::vector<unsigned char>& hash) { return ReadLE32(hash.data()); }
122
124typedef std::pair<ChallengeType, uint32_t> Challenge;
125
127struct KeyConverter {
128 typedef CPubKey Key;
129
130 const miniscript::MiniscriptContext m_script_ctx;
131
132 constexpr KeyConverter(miniscript::MiniscriptContext ctx) noexcept : m_script_ctx{ctx} {}
133
134 bool KeyCompare(const Key& a, const Key& b) const {
135 return a < b;
136 }
137
139 std::vector<unsigned char> ToPKBytes(const CPubKey& key) const {
140 if (!miniscript::IsTapscript(m_script_ctx)) {
141 return {key.begin(), key.end()};
142 }
143 const XOnlyPubKey xonly_pubkey{key};
144 return {xonly_pubkey.begin(), xonly_pubkey.end()};
145 }
146
148 std::vector<unsigned char> ToPKHBytes(const CPubKey& key) const {
149 if (!miniscript::IsTapscript(m_script_ctx)) {
150 auto hash = g_testdata->pkhashes.at(key);
151 return {hash.begin(), hash.end()};
152 }
153 const XOnlyPubKey xonly_key{key};
154 auto hash = g_testdata->xonly_pkhashes.at(xonly_key);
155 return {hash.begin(), hash.end()};
156 }
157
159 template<typename I>
160 std::optional<Key> FromString(I first, I last) const {
161 auto bytes = ParseHex(std::string(first, last));
162 Key key{bytes.begin(), bytes.end()};
163 if (key.IsValid()) return key;
164 return {};
165 }
166
167 template<typename I>
168 std::optional<Key> FromPKBytes(I first, I last) const {
169 if (!miniscript::IsTapscript(m_script_ctx)) {
170 Key key{first, last};
171 if (key.IsValid()) return key;
172 return {};
173 }
174 if (last - first != 32) return {};
175 XOnlyPubKey xonly_pubkey;
176 std::copy(first, last, xonly_pubkey.begin());
177 return xonly_pubkey.GetEvenCorrespondingCPubKey();
178 }
179
180 template<typename I>
181 std::optional<Key> FromPKHBytes(I first, I last) const {
182 assert(last - first == 20);
183 CKeyID keyid;
184 std::copy(first, last, keyid.begin());
185 return g_testdata->pkmap.at(keyid);
186 }
187
188 std::optional<std::string> ToString(const Key& key) const {
189 return HexStr(ToPKBytes(key));
190 }
191
192 miniscript::MiniscriptContext MsContext() const {
193 return m_script_ctx;
194 }
195};
196
198struct Satisfier : public KeyConverter {
199
200 Satisfier(miniscript::MiniscriptContext ctx) noexcept : KeyConverter{ctx} {}
201
203 std::set<Challenge> supported;
204
206 bool CheckAfter(uint32_t value) const {
207 return supported.count(Challenge(ChallengeType::AFTER, value));
208 }
209
211 bool CheckOlder(uint32_t value) const {
212 return supported.count(Challenge(ChallengeType::OLDER, value));
213 }
214
216 miniscript::Availability Sign(const CPubKey& key, std::vector<unsigned char>& sig) const {
217 if (supported.count(Challenge(ChallengeType::PK, ChallengeNumber(key)))) {
219 auto it = g_testdata->signatures.find(key);
220 if (it == g_testdata->signatures.end()) return miniscript::Availability::NO;
221 sig = it->second;
222 } else {
223 auto it = g_testdata->schnorr_signatures.find(XOnlyPubKey{key});
224 if (it == g_testdata->schnorr_signatures.end()) return miniscript::Availability::NO;
225 sig = it->second;
226 }
228 }
230 }
231
233 miniscript::Availability SatHash(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage, ChallengeType chtype) const {
234 if (!supported.count(Challenge(chtype, ChallengeNumber(hash)))) return miniscript::Availability::NO;
235 const auto& m =
236 chtype == ChallengeType::SHA256 ? g_testdata->sha256_preimages :
237 chtype == ChallengeType::HASH256 ? g_testdata->hash256_preimages :
238 chtype == ChallengeType::RIPEMD160 ? g_testdata->ripemd160_preimages :
239 g_testdata->hash160_preimages;
240 auto it = m.find(hash);
241 if (it == m.end()) return miniscript::Availability::NO;
242 preimage = it->second;
244 }
245
246 // Functions that produce the preimage for hashes of various types.
247 miniscript::Availability SatSHA256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return SatHash(hash, preimage, ChallengeType::SHA256); }
248 miniscript::Availability SatRIPEMD160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return SatHash(hash, preimage, ChallengeType::RIPEMD160); }
249 miniscript::Availability SatHASH256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return SatHash(hash, preimage, ChallengeType::HASH256); }
250 miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return SatHash(hash, preimage, ChallengeType::HASH160); }
251};
252
257class TestSignatureChecker : public BaseSignatureChecker {
258 const Satisfier& ctx;
259
260public:
261 TestSignatureChecker(const Satisfier& in_ctx LIFETIMEBOUND) : ctx(in_ctx) {}
262
263 bool CheckECDSASignature(const std::vector<unsigned char>& sig, const std::vector<unsigned char>& pubkey, const CScript& scriptcode, SigVersion sigversion) const override {
264 CPubKey pk(pubkey);
265 if (!pk.IsValid()) return false;
266 // Instead of actually running signature validation, check if the signature matches the precomputed one for this key.
267 auto it = g_testdata->signatures.find(pk);
268 if (it == g_testdata->signatures.end()) return false;
269 return sig == it->second;
270 }
271
272 bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion,
273 ScriptExecutionData&, ScriptError*) const override {
274 XOnlyPubKey pk{pubkey};
275 auto it = g_testdata->schnorr_signatures.find(pk);
276 if (it == g_testdata->schnorr_signatures.end()) return false;
277 return sig == it->second;
278 }
279
280 bool CheckLockTime(const CScriptNum& locktime) const override {
281 // Delegate to Satisfier.
282 return ctx.CheckAfter(locktime.GetInt64());
283 }
284
285 bool CheckSequence(const CScriptNum& sequence) const override {
286 // Delegate to Satisfier.
287 return ctx.CheckOlder(sequence.GetInt64());
288 }
289};
290
293using miniscript::operator"" _mst;
294using Node = miniscript::Node<CPubKey>;
295
297// NOLINTNEXTLINE(misc-no-recursion)
298std::set<Challenge> FindChallenges(const NodeRef& ref) {
299 std::set<Challenge> chal;
300 for (const auto& key : ref->keys) {
301 chal.emplace(ChallengeType::PK, ChallengeNumber(key));
302 }
303 if (ref->fragment == miniscript::Fragment::OLDER) {
304 chal.emplace(ChallengeType::OLDER, ref->k);
305 } else if (ref->fragment == miniscript::Fragment::AFTER) {
306 chal.emplace(ChallengeType::AFTER, ref->k);
307 } else if (ref->fragment == miniscript::Fragment::SHA256) {
308 chal.emplace(ChallengeType::SHA256, ChallengeNumber(ref->data));
309 } else if (ref->fragment == miniscript::Fragment::RIPEMD160) {
310 chal.emplace(ChallengeType::RIPEMD160, ChallengeNumber(ref->data));
311 } else if (ref->fragment == miniscript::Fragment::HASH256) {
312 chal.emplace(ChallengeType::HASH256, ChallengeNumber(ref->data));
313 } else if (ref->fragment == miniscript::Fragment::HASH160) {
314 chal.emplace(ChallengeType::HASH160, ChallengeNumber(ref->data));
315 }
316 for (const auto& sub : ref->subs) {
317 auto sub_chal = FindChallenges(sub);
318 chal.insert(sub_chal.begin(), sub_chal.end());
319 }
320 return chal;
321}
322
324CScript ScriptPubKey(miniscript::MiniscriptContext ctx, const CScript& script, TaprootBuilder& builder)
325{
327
328 // For Taproot outputs we always use a tree with a single script and a dummy internal key.
329 builder.Add(0, script, TAPROOT_LEAF_TAPSCRIPT);
331 return GetScriptForDestination(builder.GetOutput());
332}
333
335void SatisfactionToWitness(miniscript::MiniscriptContext ctx, CScriptWitness& witness, const CScript& script, TaprootBuilder& builder) {
336 // For P2WSH, it's only the witness script.
337 witness.stack.emplace_back(script.begin(), script.end());
338 if (!miniscript::IsTapscript(ctx)) return;
339 // For Tapscript we also need the control block.
340 witness.stack.push_back(*builder.GetSpendData().scripts.begin()->second.begin());
341}
342
344void TestSatisfy(const KeyConverter& converter, const std::string& testcase, const NodeRef& node) {
345 auto script = node->ToScript(converter);
346 auto challenges = FindChallenges(node); // Find all challenges in the generated miniscript.
347 std::vector<Challenge> challist(challenges.begin(), challenges.end());
348 for (int iter = 0; iter < 3; ++iter) {
349 std::shuffle(challist.begin(), challist.end(), g_insecure_rand_ctx);
350 Satisfier satisfier(converter.MsContext());
351 TestSignatureChecker checker(satisfier);
352 bool prev_mal_success = false, prev_nonmal_success = false;
353 // Go over all challenges involved in this miniscript in random order.
354 for (int add = -1; add < (int)challist.size(); ++add) {
355 if (add >= 0) satisfier.supported.insert(challist[add]); // The first iteration does not add anything
356
357 // Get the ScriptPubKey for this script, filling spend data if it's Taproot.
358 TaprootBuilder builder;
359 const CScript script_pubkey{ScriptPubKey(converter.MsContext(), script, builder)};
360
361 // Run malleable satisfaction algorithm.
362 CScriptWitness witness_mal;
363 const bool mal_success = node->Satisfy(satisfier, witness_mal.stack, false) == miniscript::Availability::YES;
364 SatisfactionToWitness(converter.MsContext(), witness_mal, script, builder);
365
366 // Run non-malleable satisfaction algorithm.
367 CScriptWitness witness_nonmal;
368 const bool nonmal_success = node->Satisfy(satisfier, witness_nonmal.stack, true) == miniscript::Availability::YES;
369 // Compute witness size (excluding script push, control block, and witness count encoding).
370 const size_t wit_size = GetSerializeSize(witness_nonmal.stack) - GetSizeOfCompactSize(witness_nonmal.stack.size());
371 SatisfactionToWitness(converter.MsContext(), witness_nonmal, script, builder);
372
373 if (nonmal_success) {
374 // Non-malleable satisfactions are bounded by the satisfaction size plus:
375 // - For P2WSH spends, the witness script
376 // - For Tapscript spends, both the witness script and the control block
377 const size_t max_stack_size{*node->GetStackSize() + 1 + miniscript::IsTapscript(converter.MsContext())};
378 BOOST_CHECK(witness_nonmal.stack.size() <= max_stack_size);
379 // If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
380 BOOST_CHECK(mal_success);
381 BOOST_CHECK(witness_nonmal.stack == witness_mal.stack);
382 assert(wit_size <= *node->GetWitnessSize());
383
384 // Test non-malleable satisfaction.
385 ScriptError serror;
386 bool res = VerifyScript(CScript(), script_pubkey, &witness_nonmal, STANDARD_SCRIPT_VERIFY_FLAGS, checker, &serror);
387 // Non-malleable satisfactions are guaranteed to be valid if ValidSatisfactions().
388 if (node->ValidSatisfactions()) BOOST_CHECK(res);
389 // More detailed: non-malleable satisfactions must be valid, or could fail with ops count error (if CheckOpsLimit failed),
390 // or with a stack size error (if CheckStackSize check fails).
391 BOOST_CHECK(res ||
392 (!node->CheckOpsLimit() && serror == ScriptError::SCRIPT_ERR_OP_COUNT) ||
393 (!node->CheckStackSize() && serror == ScriptError::SCRIPT_ERR_STACK_SIZE));
394 }
395
396 if (mal_success && (!nonmal_success || witness_mal.stack != witness_nonmal.stack)) {
397 // Test malleable satisfaction only if it's different from the non-malleable one.
398 ScriptError serror;
399 bool res = VerifyScript(CScript(), script_pubkey, &witness_mal, STANDARD_SCRIPT_VERIFY_FLAGS, checker, &serror);
400 // Malleable satisfactions are not guaranteed to be valid under any conditions, but they can only
401 // fail due to stack or ops limits.
402 BOOST_CHECK(res || serror == ScriptError::SCRIPT_ERR_OP_COUNT || serror == ScriptError::SCRIPT_ERR_STACK_SIZE);
403 }
404
405 if (node->IsSane()) {
406 // For sane nodes, the two algorithms behave identically.
407 BOOST_CHECK_EQUAL(mal_success, nonmal_success);
408 }
409
410 // Adding more satisfied conditions can never remove our ability to produce a satisfaction.
411 BOOST_CHECK(mal_success >= prev_mal_success);
412 // For nonmalleable solutions this is only true if the added condition is PK;
413 // for other conditions, adding one may make an valid satisfaction become malleable. If the script
414 // is sane, this cannot happen however.
415 if (node->IsSane() || add < 0 || challist[add].first == ChallengeType::PK) {
416 BOOST_CHECK(nonmal_success >= prev_nonmal_success);
417 }
418 // Remember results for the next added challenge.
419 prev_mal_success = mal_success;
420 prev_nonmal_success = nonmal_success;
421 }
422
423 bool satisfiable = node->IsSatisfiable([](const Node&) { return true; });
424 // If the miniscript was satisfiable at all, a satisfaction must be found after all conditions are added.
425 BOOST_CHECK_EQUAL(prev_mal_success, satisfiable);
426 // If the miniscript is sane and satisfiable, a nonmalleable satisfaction must eventually be found.
427 if (node->IsSane()) BOOST_CHECK_EQUAL(prev_nonmal_success, satisfiable);
428 }
429}
430
431enum TestMode : int {
433 TESTMODE_INVALID = 0,
435 TESTMODE_VALID = 1,
436 TESTMODE_NONMAL = 2,
437 TESTMODE_NEEDSIG = 4,
438 TESTMODE_TIMELOCKMIX = 8,
440 TESTMODE_P2WSH_INVALID = 16,
442 TESTMODE_TAPSCRIPT_INVALID = 32,
443};
444
445void Test(const std::string& ms, const std::string& hexscript, int mode, const KeyConverter& converter,
446 int opslimit = -1, int stacklimit = -1, std::optional<uint32_t> max_wit_size = std::nullopt,
447 std::optional<uint32_t> stack_exec = {})
448{
449 auto node = miniscript::FromString(ms, converter);
450 const bool is_tapscript{miniscript::IsTapscript(converter.MsContext())};
451 if (mode == TESTMODE_INVALID || ((mode & TESTMODE_P2WSH_INVALID) && !is_tapscript) || ((mode & TESTMODE_TAPSCRIPT_INVALID) && is_tapscript)) {
452 BOOST_CHECK_MESSAGE(!node || !node->IsValid(), "Unexpectedly valid: " + ms);
453 } else {
454 BOOST_CHECK_MESSAGE(node, "Unparseable: " + ms);
455 BOOST_CHECK_MESSAGE(node->IsValid(), "Invalid: " + ms);
456 BOOST_CHECK_MESSAGE(node->IsValidTopLevel(), "Invalid top level: " + ms);
457 auto computed_script = node->ToScript(converter);
458 BOOST_CHECK_MESSAGE(node->ScriptSize() == computed_script.size(), "Script size mismatch: " + ms);
459 if (hexscript != "?") BOOST_CHECK_MESSAGE(HexStr(computed_script) == hexscript, "Script mismatch: " + ms + " (" + HexStr(computed_script) + " vs " + hexscript + ")");
460 BOOST_CHECK_MESSAGE(node->IsNonMalleable() == !!(mode & TESTMODE_NONMAL), "Malleability mismatch: " + ms);
461 BOOST_CHECK_MESSAGE(node->NeedsSignature() == !!(mode & TESTMODE_NEEDSIG), "Signature necessity mismatch: " + ms);
462 BOOST_CHECK_MESSAGE((node->GetType() << "k"_mst) == !(mode & TESTMODE_TIMELOCKMIX), "Timelock mix mismatch: " + ms);
463 auto inferred_miniscript = miniscript::FromScript(computed_script, converter);
464 BOOST_CHECK_MESSAGE(inferred_miniscript, "Cannot infer miniscript from script: " + ms);
465 BOOST_CHECK_MESSAGE(inferred_miniscript->ToScript(converter) == computed_script, "Roundtrip failure: miniscript->script != miniscript->script->miniscript->script: " + ms);
466 if (opslimit != -1) BOOST_CHECK_MESSAGE((int)*node->GetOps() == opslimit, "Ops limit mismatch: " << ms << " (" << *node->GetOps() << " vs " << opslimit << ")");
467 if (stacklimit != -1) BOOST_CHECK_MESSAGE((int)*node->GetStackSize() == stacklimit, "Stack limit mismatch: " << ms << " (" << *node->GetStackSize() << " vs " << stacklimit << ")");
468 if (max_wit_size) BOOST_CHECK_MESSAGE(*node->GetWitnessSize() == *max_wit_size, "Witness size limit mismatch: " << ms << " (" << *node->GetWitnessSize() << " vs " << *max_wit_size << ")");
469 if (stack_exec) BOOST_CHECK_MESSAGE(*node->GetExecStackSize() == *stack_exec, "Stack execution limit mismatch: " << ms << " (" << *node->GetExecStackSize() << " vs " << *stack_exec << ")");
470 TestSatisfy(converter, ms, node);
471 }
472}
473
474void Test(const std::string& ms, const std::string& hexscript, const std::string& hextapscript, int mode,
475 int opslimit, int stacklimit, std::optional<uint32_t> max_wit_size,
476 std::optional<uint32_t> max_tap_wit_size,
477 std::optional<uint32_t> stack_exec)
478{
479 KeyConverter wsh_converter(miniscript::MiniscriptContext::P2WSH);
480 Test(ms, hexscript, mode, wsh_converter, opslimit, stacklimit, max_wit_size, stack_exec);
481 KeyConverter tap_converter(miniscript::MiniscriptContext::TAPSCRIPT);
482 Test(ms, hextapscript == "=" ? hexscript : hextapscript, mode, tap_converter, opslimit, stacklimit, max_tap_wit_size, stack_exec);
483}
484
485void Test(const std::string& ms, const std::string& hexscript, const std::string& hextapscript, int mode)
486{
487 Test(ms, hexscript, hextapscript, mode,
488 /*opslimit=*/-1, /*stacklimit=*/-1,
489 /*max_wit_size=*/std::nullopt, /*max_tap_wit_size=*/std::nullopt, /*stack_exec=*/std::nullopt);
490}
491
492} // namespace
493
494BOOST_FIXTURE_TEST_SUITE(miniscript_tests, BasicTestingSetup)
495
497{
498 g_testdata.reset(new TestData());
499
500 // Validity rules
501 Test("l:older(1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // older(1): valid
502 Test("l:older(0)", "?", "?", TESTMODE_INVALID); // older(0): k must be at least 1
503 Test("l:older(2147483647)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // older(2147483647): valid
504 Test("l:older(2147483648)", "?", "?", TESTMODE_INVALID); // older(2147483648): k must be below 2^31
505 Test("u:after(1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // after(1): valid
506 Test("u:after(0)", "?", "?", TESTMODE_INVALID); // after(0): k must be at least 1
507 Test("u:after(2147483647)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // after(2147483647): valid
508 Test("u:after(2147483648)", "?", "?", TESTMODE_INVALID); // after(2147483648): k must be below 2^31
509 Test("andor(0,1,1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // andor(Bdu,B,B): valid
510 Test("andor(a:0,1,1)", "?", "?", TESTMODE_INVALID); // andor(Wdu,B,B): X must be B
511 Test("andor(0,a:1,a:1)", "?", "?", TESTMODE_INVALID); // andor(Bdu,W,W): Y and Z must be B/V/K
512 Test("andor(1,1,1)", "?", "?", TESTMODE_INVALID); // andor(Bu,B,B): X must be d
513 Test("andor(n:or_i(0,after(1)),1,1)", "?", "?", TESTMODE_VALID); // andor(Bdu,B,B): valid
514 Test("andor(or_i(0,after(1)),1,1)", "?", "?", TESTMODE_INVALID); // andor(Bd,B,B): X must be u
515 Test("c:andor(0,pk_k(03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7),pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // andor(Bdu,K,K): valid
516 Test("t:andor(0,v:1,v:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // andor(Bdu,V,V): valid
517 Test("and_v(v:1,1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_v(V,B): valid
518 Test("t:and_v(v:1,v:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_v(V,V): valid
519 Test("c:and_v(v:1,pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // and_v(V,K): valid
520 Test("and_v(1,1)", "?", "?", TESTMODE_INVALID); // and_v(B,B): X must be V
521 Test("and_v(pk_k(02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),1)", "?", "?", TESTMODE_INVALID); // and_v(K,B): X must be V
522 Test("and_v(v:1,a:1)", "?", "?", TESTMODE_INVALID); // and_v(K,W): Y must be B/V/K
523 Test("and_b(1,a:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_b(B,W): valid
524 Test("and_b(1,1)", "?", "?", TESTMODE_INVALID); // and_b(B,B): Y must W
525 Test("and_b(v:1,a:1)", "?", "?", TESTMODE_INVALID); // and_b(V,W): X must be B
526 Test("and_b(a:1,a:1)", "?", "?", TESTMODE_INVALID); // and_b(W,W): X must be B
527 Test("and_b(pk_k(025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),a:1)", "?", "?", TESTMODE_INVALID); // and_b(K,W): X must be B
528 Test("or_b(0,a:0)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // or_b(Bd,Wd): valid
529 Test("or_b(1,a:0)", "?", "?", TESTMODE_INVALID); // or_b(B,Wd): X must be d
530 Test("or_b(0,a:1)", "?", "?", TESTMODE_INVALID); // or_b(Bd,W): Y must be d
531 Test("or_b(0,0)", "?", "?", TESTMODE_INVALID); // or_b(Bd,Bd): Y must W
532 Test("or_b(v:0,a:0)", "?", "?", TESTMODE_INVALID); // or_b(V,Wd): X must be B
533 Test("or_b(a:0,a:0)", "?", "?", TESTMODE_INVALID); // or_b(Wd,Wd): X must be B
534 Test("or_b(pk_k(025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),a:0)", "?", "?", TESTMODE_INVALID); // or_b(Kd,Wd): X must be B
535 Test("t:or_c(0,v:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // or_c(Bdu,V): valid
536 Test("t:or_c(a:0,v:1)", "?", "?", TESTMODE_INVALID); // or_c(Wdu,V): X must be B
537 Test("t:or_c(1,v:1)", "?", "?", TESTMODE_INVALID); // or_c(Bu,V): X must be d
538 Test("t:or_c(n:or_i(0,after(1)),v:1)", "?", "?", TESTMODE_VALID); // or_c(Bdu,V): valid
539 Test("t:or_c(or_i(0,after(1)),v:1)", "?", "?", TESTMODE_INVALID); // or_c(Bd,V): X must be u
540 Test("t:or_c(0,1)", "?", "?", TESTMODE_INVALID); // or_c(Bdu,B): Y must be V
541 Test("or_d(0,1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // or_d(Bdu,B): valid
542 Test("or_d(a:0,1)", "?", "?", TESTMODE_INVALID); // or_d(Wdu,B): X must be B
543 Test("or_d(1,1)", "?", "?", TESTMODE_INVALID); // or_d(Bu,B): X must be d
544 Test("or_d(n:or_i(0,after(1)),1)", "?", "?", TESTMODE_VALID); // or_d(Bdu,B): valid
545 Test("or_d(or_i(0,after(1)),1)", "?", "?", TESTMODE_INVALID); // or_d(Bd,B): X must be u
546 Test("or_d(0,v:1)", "?", "?", TESTMODE_INVALID); // or_d(Bdu,V): Y must be B
547 Test("or_i(1,1)", "?", "?", TESTMODE_VALID); // or_i(B,B): valid
548 Test("t:or_i(v:1,v:1)", "?", "?", TESTMODE_VALID); // or_i(V,V): valid
549 Test("c:or_i(pk_k(03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7),pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // or_i(K,K): valid
550 Test("or_i(a:1,a:1)", "?", "?", TESTMODE_INVALID); // or_i(W,W): X and Y must be B/V/K
551 Test("or_b(l:after(100),al:after(1000000000))", "?", "?", TESTMODE_VALID); // or_b(timelock, heighlock) valid
552 Test("and_b(after(100),a:after(1000000000))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX); // and_b(timelock, heighlock) invalid
553 Test("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_k
554 Test("pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "76a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac", "76a914fd1690c37fa3b0f04395ddc9415b220ab1ccc59588ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_h
555
556 // Randomly generated test set that covers the majority of type and node type combinations
557 Test("lltvln:after(1231488000)", "6300676300676300670400046749b1926869516868", "=", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 3, 3, 3);
558 Test("uuj:and_v(v:multi(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "6363829263522103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a21025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc52af0400046749b168670068670068", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 14, 5, 2 + 2 + 1 + 2 * 73, 0, 7);
559 Test("or_b(un:multi(2,03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),al:older(16))", "63522103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee872921024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae926700686b63006760b2686c9b", "?", TESTMODE_VALID | TESTMODE_TAPSCRIPT_INVALID, 14, 5, 2 + 1 + 2 * 73 + 2, 0, 8);
560 Test("j:and_v(vdv:after(1567547623),older(2016))", "829263766304e7e06e5db169686902e007b268", "=", TESTMODE_VALID | TESTMODE_NONMAL, 11, 1, 2, 2, 2);
561 Test("t:and_v(vu:hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),v:sha256(ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5))", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", "6382012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876700686982012088a820ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc58851", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 2 + 33 + 33, 2 + 33 + 33, 4);
562 Test("t:andor(multi(3,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),v:older(4194305),v:sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2))", "532102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a14602975562102e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd1353ae6482012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2886703010040b2696851", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TAPSCRIPT_INVALID, 13, 5, 1 + 3 * 73, 0, 10);
563 Test("or_d(multi(1,02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9),or_b(multi(3,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a),su:after(500000)))", "512102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f951ae73645321022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a0121032fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f2103d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a53ae7c630320a107b16700689b68", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TAPSCRIPT_INVALID, 15, 7, 2 + 1 + 3 * 73 + 1, 0, 10);
564 Test("or_d(sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6),and_n(un:after(499999999),older(4194305)))", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", TESTMODE_VALID, 16, 1, 33, 33, 3);
565 Test("and_v(or_i(v:multi(2,02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb),v:multi(2,03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)),sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68))", "63522102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee52103774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb52af67522103e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a21025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc52af6882012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c6887", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 11, 5, 2 + 1 + 2 * 73 + 33, 0, 8);
566 Test("j:and_b(multi(2,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),s:or_i(older(1),older(4252898)))", "82926352210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c9752ae7c6351b26703e2e440b2689a68", "?", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 14, 4, 1 + 2 * 73 + 2, 0, 8);
567 Test("and_b(older(16),s:or_d(sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),n:after(1567547623)))", "60b27c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87736404e7e06e5db192689a", "=", TESTMODE_VALID, 12, 1, 33, 33, 4);
568 Test("j:and_v(v:hash160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))", "82926382012088a91420195b5a3d650c17f0f29f91c33f8f6335193d078882012088a82096de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c4787736460b26868", "=", TESTMODE_VALID, 16, 2, 33 + 33, 33 + 33, 4);
569 Test("and_b(hash256(32ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac),a:and_b(hash256(131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b),a:older(1)))", "82012088aa2032ba476771d01e37807990ead8719f08af494723de1d228f2c2c07cc0aa40bac876b82012088aa20131772552c01444cd81360818376a040b7c3b2b7b0a53550ee3edde216cec61b876b51b26c9a6c9a", "=", TESTMODE_VALID | TESTMODE_NONMAL, 15, 2, 33 + 33, 33 + 33, 4);
570 Test("thresh(2,multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),a:multi(1,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00),ac:pk_k(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))", "522103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c721036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0052ae6b5121036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a0051ae6c936b21022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ac6c935287", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 13, 6, 1 + 2 * 73 + 1 + 73 + 1, 0, 10);
571 Test("and_n(sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68),t:or_i(v:older(4252898),v:older(144)))", "82012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68876400676303e2e440b26967029000b269685168", "=", TESTMODE_VALID, 14, 2, 33 + 2, 33 + 2, 4);
572 Test("or_d(nd:and_v(v:older(4252898),v:older(4252898)),sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6))", "766303e2e440b26903e2e440b2696892736482012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68768", "=", TESTMODE_VALID, 15, 2, 1 + 33, 1 + 33, 3);
573 Test("c:and_v(or_c(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),v:multi(1,02c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db)),pk_k(03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764512102c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db51af682103acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeac", "?", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 8, 2, 33 + 73, 0, 4);
574 Test("c:and_v(or_c(multi(2,036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00,02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),v:ripemd160(1b0f3c404d12075c68c938f9f60ebea4f74941a0)),pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "5221036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a002102352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d552ae6482012088a6141b0f3c404d12075c68c938f9f60ebea4f74941a088682103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TAPSCRIPT_INVALID, 10, 5, 1 + 2 * 73 + 73, 0, 9);
575 Test("and_v(andor(hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),v:hash256(939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735),v:older(50000)),after(499999999))", "82012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b2587640350c300b2696782012088aa20939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735886804ff64cd1db1", "=", TESTMODE_VALID, 14, 2, 33 + 33, 33 + 33, 4);
576 Test("andor(hash256(5f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040),j:and_v(v:hash160(3a2bff0da9d96868e66abc4427bea4691cf61ccd),older(4194305)),ripemd160(44d90e2d3714c8663b632fcf0f9d5f22192cc4c8))", "82012088aa205f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040876482012088a61444d90e2d3714c8663b632fcf0f9d5f22192cc4c8876782926382012088a9143a2bff0da9d96868e66abc4427bea4691cf61ccd8803010040b26868", "=", TESTMODE_VALID, 20, 2, 33 + 33, 33 + 33, 4);
577 Test("or_i(c:and_v(v:after(500000),pk_k(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),sha256(d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f946))", "630320a107b1692102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", "630320a107b16920c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ac6782012088a820d9147961436944f43cd99d28b2bbddbf452ef872b30c8279e255e7daafc7f9468768", TESTMODE_VALID | TESTMODE_NONMAL, 10, 2, 2 + 73, 2 + 66, 3);
578 Test("thresh(2,c:pk_h(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),a:hash160(dd69735817e0e3f6f826a9238dc2e291184f0131))", "76a9145dedfbf9ea599dd4e3ca6a80b333c472fd0b3f6988ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", "76a9141a7ac36cfa8431ab2395d701b0050045ae4a37d188ac7c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87936b82012088a914dd69735817e0e3f6f826a9238dc2e291184f0131876c935287", TESTMODE_VALID, 18, 4, 1 + 34 + 33 + 33, 1 + 33 + 33 + 33, 6);
579 Test("and_n(sha256(9267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed2),uc:and_v(v:older(144),pk_k(03fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ce)))", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b2692103fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", "82012088a8209267d3dbed802941483f1afa2a6bc68de5f653128aca9bf1461c5d0a3ad36ed28764006763029000b26920fe72c435413d33d48ac09c9161ba8b09683215439d62b7940502bda8b202e6ceac67006868", TESTMODE_VALID | TESTMODE_NEEDSIG, 13, 3, 33 + 2 + 73, 33 + 2 + 66, 5);
580 Test("and_n(c:pk_k(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),and_b(l:older(4252898),a:older(16)))", "2103daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", "20daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729ac64006763006703e2e440b2686b60b26c9a68", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_TIMELOCKMIX, 12, 2, 73 + 1, 66 + 1, 3);
581 Test("c:or_i(and_v(v:older(16),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)),pk_h(026a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4))", "6360b26976a9149fc5dbe5efdce10374a4dd4053c93af540211718886776a9142fbd32c8dd59ee7c17e66cb6ebea7e9846c3040f8868ac", "6360b26976a9144d4421361c3289bdad06441ffaee8be8e786f1ad886776a91460d4a7bcbd08f58e58bd208d1069837d7adb16ae8868ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 12, 3, 2 + 34 + 73, 2 + 33 + 66, 4);
582 Test("or_d(c:pk_h(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13),andor(c:pk_k(024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97),older(2016),after(1567547623)))", "76a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88ac736421024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", "76a91421ab1a140d0d305b8ff62bdb887d9fef82c9899e88ac7364204ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ac6404e7e06e5db16702e007b26868", TESTMODE_VALID | TESTMODE_NONMAL, 13, 3, 1 + 34 + 73, 1 + 33 + 66, 5);
583 Test("c:andor(ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e),and_v(v:hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),pk_h(03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a)))", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a914dd100be7d9aea5721158ebde6d6a1fd8fff93bb1886776a9149fc5dbe5efdce10374a4dd4053c93af5402117188868ac", "82012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba876482012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b258876a914a63d1e4d2ed109246c600ec8c19cce546b65b1cc886776a9144d4421361c3289bdad06441ffaee8be8e786f1ad8868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 18, 3, 33 + 34 + 73, 33 + 33 + 66, 5);
584 Test("c:andor(u:ripemd160(6ad07d21fd5dfc646f0b30577045ce201616b9ba),pk_h(03daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729),or_i(pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)))", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a9149652d86bedf43ad264362e6e6eba6eb764508127886776a914751e76e8199196d454941c45d1b3a323f1433bd688686776a91420d637c1a6404d2227f3561fdbaff5a680dba6488868ac", "6382012088a6146ad07d21fd5dfc646f0b30577045ce201616b9ba87670068646376a914ceedcb44b38bdbcb614d872223964fd3dca8a434886776a914f678d9b79045452c8c64e9309d0f0046056e26c588686776a914a2a75e1819afa208f6c89ae0da43021116dfcb0c8868ac", TESTMODE_VALID | TESTMODE_NEEDSIG, 23, 4, 2 + 33 + 34 + 73, 2 + 33 + 33 + 66, 5);
585 Test("c:or_i(andor(c:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk_h(022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01),pk_h(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)),pk_k(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e))", "6376a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac6476a91406afd46bcdfd22ef94ac122aa11f241244a37ecc886776a9149652d86bedf43ad264362e6e6eba6eb7645081278868672102d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e68ac", "6376a914fd1690c37fa3b0f04395ddc9415b220ab1ccc59588ac6476a9149b652a14674a506079f574d20ca7daef6f9a66bb886776a914ceedcb44b38bdbcb614d872223964fd3dca8a43488686720d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e68ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG, 17, 5, 2 + 34 + 73 + 34 + 73, 2 + 33 + 66 + 33 + 66, 6);
586 Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670400ca9a3bb16951686c936b6300670164b16951686c935187", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670400ca9a3bb16951686c936b6300670164b16951686c935187", TESTMODE_VALID, 18, 3, 73 + 2 + 2, 66 + 2 + 2, 4);
587 Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),altv:after(1000000000),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac6c936b6300670400ca9a3bb16951686c936b6300670164b16951686c935287", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac6c936b6300670400ca9a3bb16951686c936b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX, 22, 4, 73 + 73 + 2 + 2, 66 + 66 + 2 + 2, 5);
588
589 // Additional Tapscript-related tests
590 // Edge cases when parsing multi_a from script:
591 // - no pubkey at all
592 // - no pubkey before a CHECKSIGADD
593 // - no pubkey before the CHECKSIG
594 constexpr KeyConverter tap_converter{miniscript::MiniscriptContext::TAPSCRIPT};
595 constexpr KeyConverter wsh_converter{miniscript::MiniscriptContext::P2WSH};
596 const auto no_pubkey{ParseHex("ac519c")};
597 BOOST_CHECK(miniscript::FromScript({no_pubkey.begin(), no_pubkey.end()}, tap_converter) == nullptr);
598 const auto incomplete_multi_a{ParseHex("ba20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba519c")};
599 BOOST_CHECK(miniscript::FromScript({incomplete_multi_a.begin(), incomplete_multi_a.end()}, tap_converter) == nullptr);
600 const auto incomplete_multi_a_2{ParseHex("ac2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba519c")};
601 BOOST_CHECK(miniscript::FromScript({incomplete_multi_a_2.begin(), incomplete_multi_a_2.end()}, tap_converter) == nullptr);
602 // Can use multi_a under Tapscript but not P2WSH.
603 Test("and_v(v:multi_a(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "?", "20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aac205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba529d0400046749b1", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4, 2, {}, {}, 3);
604 // Can use more than 20 keys in a multi_a.
605 std::string ms_str_multi_a{"multi_a(1,"};
606 for (size_t i = 0; i < 21; ++i) {
607 ms_str_multi_a += HexStr(g_testdata->pubkeys[i]);
608 if (i < 20) ms_str_multi_a += ",";
609 }
610 ms_str_multi_a += ")";
611 Test(ms_str_multi_a, "?", "2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba20f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9ba20e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13ba202f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4ba20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ba205cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bcba202f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ba20acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeba20a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7ba20774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cbba20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aba20f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8ba20499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4ba20d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080eba20e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0aba20defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34ba205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba202b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6cba204ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ba20352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5ba519c", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 22, 21, {}, {}, 22);
612 // Since 'd:' is 'u' we can use it directly inside a thresh. But we can't under P2WSH.
613 Test("thresh(2,dv:older(42),s:pk(025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", "?", "7663012ab269687c205cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bcac937c20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac935287", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 12, 3, {}, {}, 4);
614 // We can have a script that has more than 201 ops (n = 99), that needs a stack size > 100 (n = 110), or has a
615 // script that is larger than 3600 bytes (n = 200). All that can't be under P2WSH.
616 for (const auto pk_count: {99, 110, 200}) {
617 std::string ms_str_large;
618 for (auto i = 0; i < pk_count - 1; ++i) {
619 ms_str_large += "and_b(pk(" + HexStr(g_testdata->pubkeys[i]) + "),a:";
620 }
621 ms_str_large += "pk(" + HexStr(g_testdata->pubkeys[pk_count - 1]) + ")";
622 ms_str_large.insert(ms_str_large.end(), pk_count - 1, ')');
623 Test(ms_str_large, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, pk_count + (pk_count - 1) * 3, pk_count, {}, {}, pk_count + 1);
624 }
625 // We can have a script that reaches a stack size of 1000 during execution.
626 std::string ms_stack_limit;
627 auto count{998};
628 for (auto i = 0; i < count; ++i) {
629 ms_stack_limit += "and_b(older(1),a:";
630 }
631 ms_stack_limit += "pk(" + HexStr(g_testdata->pubkeys[0]) + ")";
632 ms_stack_limit.insert(ms_stack_limit.end(), count, ')');
633 const auto ms_stack_ok{miniscript::FromString(ms_stack_limit, tap_converter)};
634 BOOST_CHECK(ms_stack_ok && ms_stack_ok->CheckStackSize());
635 Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, {}, 1 + count + 1);
636 // But one more element on the stack during execution will make it fail. And we'd detect that.
637 count++;
638 ms_stack_limit = "and_b(older(1),a:" + ms_stack_limit + ")";
639 const auto ms_stack_nok{miniscript::FromString(ms_stack_limit, tap_converter)};
640 BOOST_CHECK(ms_stack_nok && !ms_stack_nok->CheckStackSize());
641 Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, {}, 1 + count + 1);
642
643 // Misc unit tests
644 // A Script with a non minimal push is invalid
645 std::vector<unsigned char> nonminpush = ParseHex("0000210232780000feff00ffffffffffff21ff005f00ae21ae00000000060602060406564c2102320000060900fe00005f00ae21ae00100000060606060606000000000000000000000000000000000000000000000000000000000000000000");
646 const CScript nonminpush_script(nonminpush.begin(), nonminpush.end());
647 BOOST_CHECK(miniscript::FromScript(nonminpush_script, wsh_converter) == nullptr);
648 BOOST_CHECK(miniscript::FromScript(nonminpush_script, tap_converter) == nullptr);
649 // A non-minimal VERIFY (<key> CHECKSIG VERIFY 1)
650 std::vector<unsigned char> nonminverify = ParseHex("2103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7ac6951");
651 const CScript nonminverify_script(nonminverify.begin(), nonminverify.end());
652 BOOST_CHECK(miniscript::FromScript(nonminverify_script, wsh_converter) == nullptr);
653 BOOST_CHECK(miniscript::FromScript(nonminverify_script, tap_converter) == nullptr);
654 // A threshold as large as the number of subs is valid.
655 Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670164b16951686c935287", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_NONMAL);
656 // A threshold of 1 is valid.
657 Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_NONMAL);
658 // A threshold with a k larger than the number of subs is invalid
659 Test("thresh(3,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "=", TESTMODE_INVALID);
660 // A threshold with a k null is invalid
661 Test("thresh(0,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "=", TESTMODE_INVALID);
662 // For CHECKMULTISIG the OP cost is the number of keys, but the stack size is the number of sigs (+1)
663 const auto ms_multi = miniscript::FromString("multi(1,03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)", wsh_converter);
664 BOOST_CHECK(ms_multi);
665 BOOST_CHECK_EQUAL(*ms_multi->GetOps(), 4); // 3 pubkeys + CMS
666 BOOST_CHECK_EQUAL(*ms_multi->GetStackSize(), 2); // 1 sig + dummy elem
667 // The 'd:' wrapper leaves on the stack what was DUP'ed at the beginning of its execution.
668 // Since it contains an OP_IF just after on the same element, we can make sure that the element
669 // in question must be OP_1 if OP_IF enforces that its argument must only be OP_1 or the empty
670 // vector (since otherwise the execution would immediately fail). This is the MINIMALIF rule.
671 // Unfortunately, this rule is consensus for Taproot but only policy for P2WSH. Therefore we can't
672 // (for now) have 'd:' be 'u'. This tests we can't use a 'd:' wrapper for a thresh, which requires
673 // its subs to all be 'u' (taken from https://github.com/rust-bitcoin/rust-miniscript/discussions/341).
674 const auto ms_minimalif = miniscript::FromString("thresh(3,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),sc:pk_k(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798),sdv:older(32))", wsh_converter);
675 BOOST_CHECK(ms_minimalif && !ms_minimalif->IsValid());
676 // A Miniscript with duplicate keys is not sane
677 const auto ms_dup1 = miniscript::FromString("and_v(v:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", wsh_converter);
678 BOOST_CHECK(ms_dup1);
679 BOOST_CHECK(!ms_dup1->IsSane() && !ms_dup1->CheckDuplicateKey());
680 // Same with a disjunction, and different key nodes (pk and pkh)
681 const auto ms_dup2 = miniscript::FromString("or_b(c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", wsh_converter);
682 BOOST_CHECK(ms_dup2 && !ms_dup2->IsSane() && !ms_dup2->CheckDuplicateKey());
683 // Same when the duplicates are leaves or a larger tree
684 const auto ms_dup3 = miniscript::FromString("or_i(and_b(pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556)),and_b(older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", wsh_converter);
685 BOOST_CHECK(ms_dup3 && !ms_dup3->IsSane() && !ms_dup3->CheckDuplicateKey());
686 // Same when the duplicates are on different levels in the tree
687 const auto ms_dup4 = miniscript::FromString("thresh(2,pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),a:and_b(dv:older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", wsh_converter);
688 BOOST_CHECK(ms_dup4 && !ms_dup4->IsSane() && !ms_dup4->CheckDuplicateKey());
689 // Sanity check the opposite is true, too. An otherwise sane Miniscript with no duplicate keys is sane.
690 const auto ms_nondup = miniscript::FromString("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", wsh_converter);
691 BOOST_CHECK(ms_nondup && ms_nondup->CheckDuplicateKey() && ms_nondup->IsSane());
692 // Test we find the first insane sub closer to be a leaf node. This fragment is insane for two reasons:
693 // 1. It can be spent without a signature
694 // 2. It contains timelock mixes
695 // We'll report the timelock mix error, as it's "deeper" (closer to be a leaf node) than the "no 's' property"
696 // error is.
697 const auto ms_ins = miniscript::FromString("or_i(and_b(after(1),a:after(1000000000)),pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204))", wsh_converter);
698 BOOST_CHECK(ms_ins && ms_ins->IsValid() && !ms_ins->IsSane());
699 const auto insane_sub = ms_ins->FindInsaneSub();
700 BOOST_CHECK(insane_sub && *insane_sub->ToString(wsh_converter) == "and_b(after(1),a:after(1000000000))");
701
702 // Numbers can't be prefixed by a sign.
703 BOOST_CHECK(!miniscript::FromString("after(-1)", wsh_converter));
704 BOOST_CHECK(!miniscript::FromString("after(+1)", wsh_converter));
705 BOOST_CHECK(!miniscript::FromString("thresh(-1,pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204))", wsh_converter));
706 BOOST_CHECK(!miniscript::FromString("multi(+1,03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)", wsh_converter));
707
708 // Timelock tests
709 Test("after(100)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only heightlock
710 Test("after(1000000000)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only timelock
711 Test("or_b(l:after(100),al:after(1000000000))", "?", "?", TESTMODE_VALID); // or_b(timelock, heighlock) valid
712 Test("and_b(after(100),a:after(1000000000))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX); // and_b(timelock, heighlock) invalid
713 /* This is correctly detected as non-malleable but for the wrong reason. The type system assumes that branches 1 and 2
714 can be spent together to create a non-malleble witness, but because of mixing of timelocks they cannot be spent together.
715 But since exactly one of the two after's can be satisfied, the witness involving the key cannot be malleated.
716 */
717 Test("thresh(2,ltv:after(1000000000),altv:after(100),a:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", "?", "?", TESTMODE_VALID | TESTMODE_TIMELOCKMIX | TESTMODE_NONMAL); // thresh with k = 2
718 // This is actually non-malleable in practice, but we cannot detect it in type system. See above rationale
719 Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(1000000000),altv:after(100))", "?", "?", TESTMODE_VALID); // thresh with k = 1
720
721 g_testdata.reset();
722}
723
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
#define LIFETIMEBOUND
Definition attributes.h:16
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
A hasher class for Bitcoin's 256-bit hash (double SHA-256).
Definition hash.h:24
void Finalize(Span< unsigned char > output)
Definition hash.h:30
CHash256 & Write(Span< const unsigned char > input)
Definition hash.h:37
An encapsulated private key.
Definition key.h:35
bool SignSchnorr(const uint256 &hash, Span< unsigned char > sig, const uint256 *merkle_root, const uint256 &aux) const
Create a BIP-340 Schnorr signature, for the xonly-pubkey corresponding to *this, optionally tweaked b...
Definition key.cpp:272
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:208
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition key.cpp:182
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition key.h:103
A reference to a CKey: the Hash160 of its serialized public key.
Definition pubkey.h:24
An encapsulated public key.
Definition pubkey.h:34
const unsigned char * data() const
Definition pubkey.h:113
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition pubkey.h:164
bool IsValid() const
Definition pubkey.h:189
const unsigned char * end() const
Definition pubkey.h:115
const unsigned char * begin() const
Definition pubkey.h:114
A hasher class for RIPEMD-160.
Definition ripemd160.h:13
CRIPEMD160 & Write(const unsigned char *data, size_t len)
void Finalize(unsigned char hash[OUTPUT_SIZE])
A hasher class for SHA-256.
Definition sha256.h:14
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition sha256.cpp:727
CSHA256 & Write(const unsigned char *data, size_t len)
Definition sha256.cpp:701
Serialized script, used inside transaction inputs and outputs.
Definition script.h:414
int64_t GetInt64() const
Definition script.h:341
A Span is an object that can refer to a contiguous sequence of objects.
Definition span.h:98
Utility class to construct Taproot outputs from internal key and script tree.
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
TaprootSpendData GetSpendData() const
Compute spending data (after Finalize()).
TaprootBuilder & Add(int depth, Span< const unsigned char > script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
TaprootBuilder & Finalize(const XOnlyPubKey &internal_key)
Finalize the construction.
const unsigned char * begin() const
Definition pubkey.h:295
CPubKey GetEvenCorrespondingCPubKey() const
Definition pubkey.cpp:219
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:194
constexpr unsigned char * begin()
Definition uint256.h:102
160-bit opaque blob.
Definition uint256.h:166
256-bit opaque blob.
Definition uint256.h:178
static const uint256 ZERO
Definition uint256.h:185
static uint32_t ReadLE32(const unsigned char *ptr)
Definition common.h:20
BOOST_AUTO_TEST_SUITE_END()
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
Definition hash.h:92
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
Definition hash.h:222
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition hex_base.cpp:29
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
SigVersion
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
uint64_t sequence
BOOST_AUTO_TEST_CASE(fixed_tests)
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
Definition miniscript.h:240
std::shared_ptr< const Node< Key > > NodeRef
Definition miniscript.h:187
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
Fragment
The different node types in miniscript.
Definition miniscript.h:194
@ RIPEMD160
OP_SIZE 32 OP_EQUALVERIFY OP_RIPEMD160 [hash] OP_EQUAL.
@ HASH160
OP_SIZE 32 OP_EQUALVERIFY OP_HASH160 [hash] OP_EQUAL.
@ HASH256
OP_SIZE 32 OP_EQUALVERIFY OP_HASH256 [hash] OP_EQUAL.
@ OLDER
[n] OP_CHECKSEQUENCEVERIFY
@ SHA256
OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 [hash] OP_EQUAL.
@ AFTER
[n] OP_CHECKLOCKTIMEVERIFY
Internal RIPEMD-160 implementation.
Definition ripemd160.cpp:16
Internal SHA-256 implementation.
Definition sha256.cpp:70
#define BOOST_CHECK_EQUAL(v1, v2)
Definition object.cpp:18
#define BOOST_CHECK(expr)
Definition object.cpp:17
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS
Standard script verification flags that standard transactions will comply with.
Definition policy.h:103
@ OP_0
Definition script.h:75
enum ScriptError_t ScriptError
size_t GetSerializeSize(const T &t)
Definition serialize.h:1101
constexpr unsigned int GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 byt...
Definition serialize.h:295
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
Basic testing setup.
std::vector< std::vector< unsigned char > > stack
Definition script.h:577
Context for solving a Miniscript.
Definition sign.cpp:195
miniscript::Availability SatRIPEMD160(const std::vector< unsigned char > &hash, std::vector< unsigned char > &preimage) const
Definition sign.cpp:241
bool CheckAfter(uint32_t value) const
Time lock satisfactions.
Definition sign.cpp:234
const miniscript::MiniscriptContext m_script_ctx
The context of the script we are satisfying (either P2WSH or Tapscript).
Definition sign.cpp:203
miniscript::Availability SatSHA256(const std::vector< unsigned char > &hash, std::vector< unsigned char > &preimage) const
Hash preimage satisfactions.
Definition sign.cpp:238
miniscript::Availability SatHASH256(const std::vector< unsigned char > &hash, std::vector< unsigned char > &preimage) const
Definition sign.cpp:244
Satisfier(const SigningProvider &provider LIFETIMEBOUND, SignatureData &sig_data LIFETIMEBOUND, const BaseSignatureCreator &creator LIFETIMEBOUND, const CScript &witscript LIFETIMEBOUND, miniscript::MiniscriptContext script_ctx)
Definition sign.cpp:205
miniscript::Availability SatHASH160(const std::vector< unsigned char > &hash, std::vector< unsigned char > &preimage) const
Definition sign.cpp:247
bool CheckOlder(uint32_t value) const
Definition sign.cpp:235
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.
A node in a miniscript expression.
Definition miniscript.h:499
FastRandomContext g_insecure_rand_ctx
This global and the helpers that use it are not thread-safe.
Definition random.cpp:14
static int count
assert(!tx.IsCoinBase())