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