Bitcoin Core  27.99.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 <stdint.h>
6 #include <string>
7 #include <vector>
8 
9 #include <test/util/random.h>
10 #include <test/util/setup_common.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>
23 #include <script/signingprovider.h>
24 
25 namespace {
26 
28 struct 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  auto const MESSAGE_HASH = uint256S("f5cd94e18b6fe77dd7aca9e35c2b0c9cbd86356c80a71065");
52  // We don't pass additional randomness when creating a schnorr signature.
53  auto const EMPTY_AUX{uint256S("")};
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 
104 std::unique_ptr<const TestData> g_testdata;
105 
107 enum 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  */
120 uint32_t ChallengeNumber(const CPubKey& pubkey) { return ReadLE32(pubkey.data() + 29); }
121 uint32_t ChallengeNumber(const std::vector<unsigned char>& hash) { return ReadLE32(hash.data()); }
122 
124 typedef std::pair<ChallengeType, uint32_t> Challenge;
125 
127 struct 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 
198 struct 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 
257 class TestSignatureChecker : public BaseSignatureChecker {
258  const Satisfier& ctx;
259 
260 public:
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 
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 
292 const std::vector<unsigned char> NUMS_PK{ParseHex("50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0")};
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 {
329  if (!miniscript::IsTapscript(ctx)) return CScript() << OP_0 << WitnessV0ScriptHash(script);
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_PK});
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 
347 void TestSatisfy(const KeyConverter& converter, const std::string& testcase, const NodeRef& node) {
348  auto script = node->ToScript(converter);
349  auto challenges = FindChallenges(node); // Find all challenges in the generated miniscript.
350  std::vector<Challenge> challist(challenges.begin(), challenges.end());
351  for (int iter = 0; iter < 3; ++iter) {
352  Shuffle(challist.begin(), challist.end(), g_insecure_rand_ctx);
353  Satisfier satisfier(converter.MsContext());
354  TestSignatureChecker checker(satisfier);
355  bool prev_mal_success = false, prev_nonmal_success = false;
356  // Go over all challenges involved in this miniscript in random order.
357  for (int add = -1; add < (int)challist.size(); ++add) {
358  if (add >= 0) satisfier.supported.insert(challist[add]); // The first iteration does not add anything
359 
360  // Get the ScriptPubKey for this script, filling spend data if it's Taproot.
361  TaprootBuilder builder;
362  const CScript script_pubkey{ScriptPubKey(converter.MsContext(), script, builder)};
363 
364  // Run malleable satisfaction algorithm.
365  CScriptWitness witness_mal;
366  const bool mal_success = node->Satisfy(satisfier, witness_mal.stack, false) == miniscript::Availability::YES;
367  SatisfactionToWitness(converter.MsContext(), witness_mal, script, builder);
368 
369  // Run non-malleable satisfaction algorithm.
370  CScriptWitness witness_nonmal;
371  const bool nonmal_success = node->Satisfy(satisfier, witness_nonmal.stack, true) == miniscript::Availability::YES;
372  // Compute witness size (excluding script push, control block, and witness count encoding).
373  const size_t wit_size = GetSerializeSize(witness_nonmal.stack) - GetSizeOfCompactSize(witness_nonmal.stack.size());
374  SatisfactionToWitness(converter.MsContext(), witness_nonmal, script, builder);
375 
376  if (nonmal_success) {
377  // Non-malleable satisfactions are bounded by the satisfaction size plus:
378  // - For P2WSH spends, the witness script
379  // - For Tapscript spends, both the witness script and the control block
380  const size_t max_stack_size{*node->GetStackSize() + 1 + miniscript::IsTapscript(converter.MsContext())};
381  BOOST_CHECK(witness_nonmal.stack.size() <= max_stack_size);
382  // If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
383  BOOST_CHECK(mal_success);
384  BOOST_CHECK(witness_nonmal.stack == witness_mal.stack);
385  assert(wit_size <= *node->GetWitnessSize());
386 
387  // Test non-malleable satisfaction.
388  ScriptError serror;
389  bool res = VerifyScript(CScript(), script_pubkey, &witness_nonmal, STANDARD_SCRIPT_VERIFY_FLAGS, checker, &serror);
390  // Non-malleable satisfactions are guaranteed to be valid if ValidSatisfactions().
391  if (node->ValidSatisfactions()) BOOST_CHECK(res);
392  // More detailed: non-malleable satisfactions must be valid, or could fail with ops count error (if CheckOpsLimit failed),
393  // or with a stack size error (if CheckStackSize check fails).
394  BOOST_CHECK(res ||
395  (!node->CheckOpsLimit() && serror == ScriptError::SCRIPT_ERR_OP_COUNT) ||
396  (!node->CheckStackSize() && serror == ScriptError::SCRIPT_ERR_STACK_SIZE));
397  }
398 
399  if (mal_success && (!nonmal_success || witness_mal.stack != witness_nonmal.stack)) {
400  // Test malleable satisfaction only if it's different from the non-malleable one.
401  ScriptError serror;
402  bool res = VerifyScript(CScript(), script_pubkey, &witness_mal, STANDARD_SCRIPT_VERIFY_FLAGS, checker, &serror);
403  // Malleable satisfactions are not guaranteed to be valid under any conditions, but they can only
404  // fail due to stack or ops limits.
406  }
407 
408  if (node->IsSane()) {
409  // For sane nodes, the two algorithms behave identically.
410  BOOST_CHECK_EQUAL(mal_success, nonmal_success);
411  }
412 
413  // Adding more satisfied conditions can never remove our ability to produce a satisfaction.
414  BOOST_CHECK(mal_success >= prev_mal_success);
415  // For nonmalleable solutions this is only true if the added condition is PK;
416  // for other conditions, adding one may make an valid satisfaction become malleable. If the script
417  // is sane, this cannot happen however.
418  if (node->IsSane() || add < 0 || challist[add].first == ChallengeType::PK) {
419  BOOST_CHECK(nonmal_success >= prev_nonmal_success);
420  }
421  // Remember results for the next added challenge.
422  prev_mal_success = mal_success;
423  prev_nonmal_success = nonmal_success;
424  }
425 
426  bool satisfiable = node->IsSatisfiable([](const Node&) { return true; });
427  // If the miniscript was satisfiable at all, a satisfaction must be found after all conditions are added.
428  BOOST_CHECK_EQUAL(prev_mal_success, satisfiable);
429  // If the miniscript is sane and satisfiable, a nonmalleable satisfaction must eventually be found.
430  if (node->IsSane()) BOOST_CHECK_EQUAL(prev_nonmal_success, satisfiable);
431  }
432 }
433 
434 enum TestMode : int {
436  TESTMODE_INVALID = 0,
438  TESTMODE_VALID = 1,
439  TESTMODE_NONMAL = 2,
440  TESTMODE_NEEDSIG = 4,
441  TESTMODE_TIMELOCKMIX = 8,
443  TESTMODE_P2WSH_INVALID = 16,
445  TESTMODE_TAPSCRIPT_INVALID = 32,
446 };
447 
448 void Test(const std::string& ms, const std::string& hexscript, int mode, const KeyConverter& converter,
449  int opslimit = -1, int stacklimit = -1, std::optional<uint32_t> max_wit_size = std::nullopt,
450  std::optional<uint32_t> stack_exec = {})
451 {
452  auto node = miniscript::FromString(ms, converter);
453  const bool is_tapscript{miniscript::IsTapscript(converter.MsContext())};
454  if (mode == TESTMODE_INVALID || ((mode & TESTMODE_P2WSH_INVALID) && !is_tapscript) || ((mode & TESTMODE_TAPSCRIPT_INVALID) && is_tapscript)) {
455  BOOST_CHECK_MESSAGE(!node || !node->IsValid(), "Unexpectedly valid: " + ms);
456  } else {
457  BOOST_CHECK_MESSAGE(node, "Unparseable: " + ms);
458  BOOST_CHECK_MESSAGE(node->IsValid(), "Invalid: " + ms);
459  BOOST_CHECK_MESSAGE(node->IsValidTopLevel(), "Invalid top level: " + ms);
460  auto computed_script = node->ToScript(converter);
461  BOOST_CHECK_MESSAGE(node->ScriptSize() == computed_script.size(), "Script size mismatch: " + ms);
462  if (hexscript != "?") BOOST_CHECK_MESSAGE(HexStr(computed_script) == hexscript, "Script mismatch: " + ms + " (" + HexStr(computed_script) + " vs " + hexscript + ")");
463  BOOST_CHECK_MESSAGE(node->IsNonMalleable() == !!(mode & TESTMODE_NONMAL), "Malleability mismatch: " + ms);
464  BOOST_CHECK_MESSAGE(node->NeedsSignature() == !!(mode & TESTMODE_NEEDSIG), "Signature necessity mismatch: " + ms);
465  BOOST_CHECK_MESSAGE((node->GetType() << "k"_mst) == !(mode & TESTMODE_TIMELOCKMIX), "Timelock mix mismatch: " + ms);
466  auto inferred_miniscript = miniscript::FromScript(computed_script, converter);
467  BOOST_CHECK_MESSAGE(inferred_miniscript, "Cannot infer miniscript from script: " + ms);
468  BOOST_CHECK_MESSAGE(inferred_miniscript->ToScript(converter) == computed_script, "Roundtrip failure: miniscript->script != miniscript->script->miniscript->script: " + ms);
469  if (opslimit != -1) BOOST_CHECK_MESSAGE((int)*node->GetOps() == opslimit, "Ops limit mismatch: " << ms << " (" << *node->GetOps() << " vs " << opslimit << ")");
470  if (stacklimit != -1) BOOST_CHECK_MESSAGE((int)*node->GetStackSize() == stacklimit, "Stack limit mismatch: " << ms << " (" << *node->GetStackSize() << " vs " << stacklimit << ")");
471  if (max_wit_size) BOOST_CHECK_MESSAGE(*node->GetWitnessSize() == *max_wit_size, "Witness size limit mismatch: " << ms << " (" << *node->GetWitnessSize() << " vs " << *max_wit_size << ")");
472  if (stack_exec) BOOST_CHECK_MESSAGE(*node->GetExecStackSize() == *stack_exec, "Stack execution limit mismatch: " << ms << " (" << *node->GetExecStackSize() << " vs " << *stack_exec << ")");
473  TestSatisfy(converter, ms, node);
474  }
475 }
476 
477 void Test(const std::string& ms, const std::string& hexscript, const std::string& hextapscript, int mode,
478  int opslimit, int stacklimit, std::optional<uint32_t> max_wit_size,
479  std::optional<uint32_t> max_tap_wit_size,
480  std::optional<uint32_t> stack_exec)
481 {
482  KeyConverter wsh_converter(miniscript::MiniscriptContext::P2WSH);
483  Test(ms, hexscript, mode, wsh_converter, opslimit, stacklimit, max_wit_size, stack_exec);
484  KeyConverter tap_converter(miniscript::MiniscriptContext::TAPSCRIPT);
485  Test(ms, hextapscript == "=" ? hexscript : hextapscript, mode, tap_converter, opslimit, stacklimit, max_tap_wit_size, stack_exec);
486 }
487 
488 void Test(const std::string& ms, const std::string& hexscript, const std::string& hextapscript, int mode)
489 {
490  Test(ms, hexscript, hextapscript, mode,
491  /*opslimit=*/-1, /*stacklimit=*/-1,
492  /*max_wit_size=*/std::nullopt, /*max_tap_wit_size=*/std::nullopt, /*stack_exec=*/std::nullopt);
493 }
494 
495 } // namespace
496 
497 BOOST_FIXTURE_TEST_SUITE(miniscript_tests, BasicTestingSetup)
498 
500 {
501  g_testdata.reset(new TestData());
502 
503  // Validity rules
504  Test("l:older(1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // older(1): valid
505  Test("l:older(0)", "?", "?", TESTMODE_INVALID); // older(0): k must be at least 1
506  Test("l:older(2147483647)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // older(2147483647): valid
507  Test("l:older(2147483648)", "?", "?", TESTMODE_INVALID); // older(2147483648): k must be below 2^31
508  Test("u:after(1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // after(1): valid
509  Test("u:after(0)", "?", "?", TESTMODE_INVALID); // after(0): k must be at least 1
510  Test("u:after(2147483647)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // after(2147483647): valid
511  Test("u:after(2147483648)", "?", "?", TESTMODE_INVALID); // after(2147483648): k must be below 2^31
512  Test("andor(0,1,1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // andor(Bdu,B,B): valid
513  Test("andor(a:0,1,1)", "?", "?", TESTMODE_INVALID); // andor(Wdu,B,B): X must be B
514  Test("andor(0,a:1,a:1)", "?", "?", TESTMODE_INVALID); // andor(Bdu,W,W): Y and Z must be B/V/K
515  Test("andor(1,1,1)", "?", "?", TESTMODE_INVALID); // andor(Bu,B,B): X must be d
516  Test("andor(n:or_i(0,after(1)),1,1)", "?", "?", TESTMODE_VALID); // andor(Bdu,B,B): valid
517  Test("andor(or_i(0,after(1)),1,1)", "?", "?", TESTMODE_INVALID); // andor(Bd,B,B): X must be u
518  Test("c:andor(0,pk_k(03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7),pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // andor(Bdu,K,K): valid
519  Test("t:andor(0,v:1,v:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // andor(Bdu,V,V): valid
520  Test("and_v(v:1,1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_v(V,B): valid
521  Test("t:and_v(v:1,v:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_v(V,V): valid
522  Test("c:and_v(v:1,pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // and_v(V,K): valid
523  Test("and_v(1,1)", "?", "?", TESTMODE_INVALID); // and_v(B,B): X must be V
524  Test("and_v(pk_k(02352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5),1)", "?", "?", TESTMODE_INVALID); // and_v(K,B): X must be V
525  Test("and_v(v:1,a:1)", "?", "?", TESTMODE_INVALID); // and_v(K,W): Y must be B/V/K
526  Test("and_b(1,a:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // and_b(B,W): valid
527  Test("and_b(1,1)", "?", "?", TESTMODE_INVALID); // and_b(B,B): Y must W
528  Test("and_b(v:1,a:1)", "?", "?", TESTMODE_INVALID); // and_b(V,W): X must be B
529  Test("and_b(a:1,a:1)", "?", "?", TESTMODE_INVALID); // and_b(W,W): X must be B
530  Test("and_b(pk_k(025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),a:1)", "?", "?", TESTMODE_INVALID); // and_b(K,W): X must be B
531  Test("or_b(0,a:0)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // or_b(Bd,Wd): valid
532  Test("or_b(1,a:0)", "?", "?", TESTMODE_INVALID); // or_b(B,Wd): X must be d
533  Test("or_b(0,a:1)", "?", "?", TESTMODE_INVALID); // or_b(Bd,W): Y must be d
534  Test("or_b(0,0)", "?", "?", TESTMODE_INVALID); // or_b(Bd,Bd): Y must W
535  Test("or_b(v:0,a:0)", "?", "?", TESTMODE_INVALID); // or_b(V,Wd): X must be B
536  Test("or_b(a:0,a:0)", "?", "?", TESTMODE_INVALID); // or_b(Wd,Wd): X must be B
537  Test("or_b(pk_k(025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),a:0)", "?", "?", TESTMODE_INVALID); // or_b(Kd,Wd): X must be B
538  Test("t:or_c(0,v:1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // or_c(Bdu,V): valid
539  Test("t:or_c(a:0,v:1)", "?", "?", TESTMODE_INVALID); // or_c(Wdu,V): X must be B
540  Test("t:or_c(1,v:1)", "?", "?", TESTMODE_INVALID); // or_c(Bu,V): X must be d
541  Test("t:or_c(n:or_i(0,after(1)),v:1)", "?", "?", TESTMODE_VALID); // or_c(Bdu,V): valid
542  Test("t:or_c(or_i(0,after(1)),v:1)", "?", "?", TESTMODE_INVALID); // or_c(Bd,V): X must be u
543  Test("t:or_c(0,1)", "?", "?", TESTMODE_INVALID); // or_c(Bdu,B): Y must be V
544  Test("or_d(0,1)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // or_d(Bdu,B): valid
545  Test("or_d(a:0,1)", "?", "?", TESTMODE_INVALID); // or_d(Wdu,B): X must be B
546  Test("or_d(1,1)", "?", "?", TESTMODE_INVALID); // or_d(Bu,B): X must be d
547  Test("or_d(n:or_i(0,after(1)),1)", "?", "?", TESTMODE_VALID); // or_d(Bdu,B): valid
548  Test("or_d(or_i(0,after(1)),1)", "?", "?", TESTMODE_INVALID); // or_d(Bd,B): X must be u
549  Test("or_d(0,v:1)", "?", "?", TESTMODE_INVALID); // or_d(Bdu,V): Y must be B
550  Test("or_i(1,1)", "?", "?", TESTMODE_VALID); // or_i(B,B): valid
551  Test("t:or_i(v:1,v:1)", "?", "?", TESTMODE_VALID); // or_i(V,V): valid
552  Test("c:or_i(pk_k(03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7),pk_k(036d2b085e9e382ed10b69fc311a03f8641ccfff21574de0927513a49d9a688a00))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // or_i(K,K): valid
553  Test("or_i(a:1,a:1)", "?", "?", TESTMODE_INVALID); // or_i(W,W): X and Y must be B/V/K
554  Test("or_b(l:after(100),al:after(1000000000))", "?", "?", TESTMODE_VALID); // or_b(timelock, heighlock) valid
555  Test("and_b(after(100),a:after(1000000000))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX); // and_b(timelock, heighlock) invalid
556  Test("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_k
557  Test("pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", "76a914fcd35ddacad9f2d5be5e464639441c6065e6955d88ac", "76a914fd1690c37fa3b0f04395ddc9415b220ab1ccc59588ac", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG); // alias to c:pk_h
558 
559  // Randomly generated test set that covers the majority of type and node type combinations
560  Test("lltvln:after(1231488000)", "6300676300676300670400046749b1926869516868", "=", TESTMODE_VALID | TESTMODE_NONMAL, 12, 3, 3, 3, 3);
561  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);
562  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);
563  Test("j:and_v(vdv:after(1567547623),older(2016))", "829263766304e7e06e5db169686902e007b268", "=", TESTMODE_VALID | TESTMODE_NONMAL, 11, 1, 2, 2, 2);
564  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);
565  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);
566  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);
567  Test("or_d(sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6),and_n(un:after(499999999),older(4194305)))", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", "82012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68773646304ff64cd1db19267006864006703010040b26868", TESTMODE_VALID, 16, 1, 33, 33, 3);
568  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);
569  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);
570  Test("and_b(older(16),s:or_d(sha256(e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f),n:after(1567547623)))", "60b27c82012088a820e38990d0c7fc009880a9c07c23842e886c6bbdc964ce6bdd5817ad357335ee6f87736404e7e06e5db192689a", "=", TESTMODE_VALID, 12, 1, 33, 33, 4);
571  Test("j:and_v(v:hash160(20195b5a3d650c17f0f29f91c33f8f6335193d07),or_d(sha256(96de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c47),older(16)))", "82926382012088a91420195b5a3d650c17f0f29f91c33f8f6335193d078882012088a82096de8fc8c256fa1e1556d41af431cace7dca68707c78dd88c3acab8b17164c4787736460b26868", "=", TESTMODE_VALID, 16, 2, 33 + 33, 33 + 33, 4);
572  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);
573  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);
574  Test("and_n(sha256(d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68),t:or_i(v:older(4252898),v:older(144)))", "82012088a820d1ec675902ef1633427ca360b290b0b3045a0d9058ddb5e648b4c3c3224c5c68876400676303e2e440b26967029000b269685168", "=", TESTMODE_VALID, 14, 2, 33 + 2, 33 + 2, 4);
575  Test("or_d(nd:and_v(v:older(4252898),v:older(4252898)),sha256(38df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b6))", "766303e2e440b26903e2e440b2696892736482012088a82038df1c1f64a24a77b23393bca50dff872e31edc4f3b5aa3b90ad0b82f4f089b68768", "=", TESTMODE_VALID, 15, 2, 1 + 33, 1 + 33, 3);
576  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);
577  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);
578  Test("and_v(andor(hash256(8a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b25),v:hash256(939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735),v:older(50000)),after(499999999))", "82012088aa208a35d9ca92a48eaade6f53a64985e9e2afeb74dcf8acb4c3721e0dc7e4294b2587640350c300b2696782012088aa20939894f70e6c3a25da75da0cc2071b4076d9b006563cf635986ada2e93c0d735886804ff64cd1db1", "=", TESTMODE_VALID, 14, 2, 33 + 33, 33 + 33, 4);
579  Test("andor(hash256(5f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040),j:and_v(v:hash160(3a2bff0da9d96868e66abc4427bea4691cf61ccd),older(4194305)),ripemd160(44d90e2d3714c8663b632fcf0f9d5f22192cc4c8))", "82012088aa205f8d30e655a7ba0d7596bb3ddfb1d2d20390d23b1845000e1e118b3be1b3f040876482012088a61444d90e2d3714c8663b632fcf0f9d5f22192cc4c8876782926382012088a9143a2bff0da9d96868e66abc4427bea4691cf61ccd8803010040b26868", "=", TESTMODE_VALID, 20, 2, 33 + 33, 33 + 33, 4);
580  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);
581  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);
582  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);
583  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);
584  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);
585  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);
586  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);
587  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);
588  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);
589  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);
590  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);
591 
592  // Additional Tapscript-related tests
593  // Edge cases when parsing multi_a from script:
594  // - no pubkey at all
595  // - no pubkey before a CHECKSIGADD
596  // - no pubkey before the CHECKSIG
597  constexpr KeyConverter tap_converter{miniscript::MiniscriptContext::TAPSCRIPT};
598  constexpr KeyConverter wsh_converter{miniscript::MiniscriptContext::P2WSH};
599  const auto no_pubkey{ParseHex("ac519c")};
600  BOOST_CHECK(miniscript::FromScript({no_pubkey.begin(), no_pubkey.end()}, tap_converter) == nullptr);
601  const auto incomplete_multi_a{ParseHex("ba20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba519c")};
602  BOOST_CHECK(miniscript::FromScript({incomplete_multi_a.begin(), incomplete_multi_a.end()}, tap_converter) == nullptr);
603  const auto incomplete_multi_a_2{ParseHex("ac2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba519c")};
604  BOOST_CHECK(miniscript::FromScript({incomplete_multi_a_2.begin(), incomplete_multi_a_2.end()}, tap_converter) == nullptr);
605  // Can use multi_a under Tapscript but not P2WSH.
606  Test("and_v(v:multi_a(2,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a,025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc),after(1231488000))", "?", "20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aac205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba529d0400046749b1", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4, 2, {}, {}, 3);
607  // Can use more than 20 keys in a multi_a.
608  std::string ms_str_multi_a{"multi_a(1,"};
609  for (size_t i = 0; i < 21; ++i) {
610  ms_str_multi_a += HexStr(g_testdata->pubkeys[i]);
611  if (i < 20) ms_str_multi_a += ",";
612  }
613  ms_str_multi_a += ")";
614  Test(ms_str_multi_a, "?", "2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba20f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9ba20e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13ba202f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4ba20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ba205cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bcba202f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01ba20acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbeba20a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7ba20774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cbba20d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85aba20f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8ba20499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4ba20d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080eba20e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0aba20defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34ba205601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7ccba202b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6cba204ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97ba20352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5ba519c", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 22, 21, {}, {}, 22);
615  // Since 'd:' is 'u' we can use it directly inside a thresh. But we can't under P2WSH.
616  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);
617  // We can have a script that has more than 201 ops (n = 99), that needs a stack size > 100 (n = 110), or has a
618  // script that is larger than 3600 bytes (n = 200). All that can't be under P2WSH.
619  for (const auto pk_count: {99, 110, 200}) {
620  std::string ms_str_large;
621  for (auto i = 0; i < pk_count - 1; ++i) {
622  ms_str_large += "and_b(pk(" + HexStr(g_testdata->pubkeys[i]) + "),a:";
623  }
624  ms_str_large += "pk(" + HexStr(g_testdata->pubkeys[pk_count - 1]) + ")";
625  ms_str_large.insert(ms_str_large.end(), pk_count - 1, ')');
626  Test(ms_str_large, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, pk_count + (pk_count - 1) * 3, pk_count, {}, {}, pk_count + 1);
627  }
628  // We can have a script that reaches a stack size of 1000 during execution.
629  std::string ms_stack_limit;
630  auto count{998};
631  for (auto i = 0; i < count; ++i) {
632  ms_stack_limit += "and_b(older(1),a:";
633  }
634  ms_stack_limit += "pk(" + HexStr(g_testdata->pubkeys[0]) + ")";
635  ms_stack_limit.insert(ms_stack_limit.end(), count, ')');
636  const auto ms_stack_ok{miniscript::FromString(ms_stack_limit, tap_converter)};
637  BOOST_CHECK(ms_stack_ok && ms_stack_ok->CheckStackSize());
638  Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, {}, 1 + count + 1);
639  // But one more element on the stack during execution will make it fail. And we'd detect that.
640  count++;
641  ms_stack_limit = "and_b(older(1),a:" + ms_stack_limit + ")";
642  const auto ms_stack_nok{miniscript::FromString(ms_stack_limit, tap_converter)};
643  BOOST_CHECK(ms_stack_nok && !ms_stack_nok->CheckStackSize());
644  Test(ms_stack_limit, "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_NEEDSIG | TESTMODE_P2WSH_INVALID, 4 * count + 1, 1, {}, {}, 1 + count + 1);
645 
646  // Misc unit tests
647  // A Script with a non minimal push is invalid
648  std::vector<unsigned char> nonminpush = ParseHex("0000210232780000feff00ffffffffffff21ff005f00ae21ae00000000060602060406564c2102320000060900fe00005f00ae21ae00100000060606060606000000000000000000000000000000000000000000000000000000000000000000");
649  const CScript nonminpush_script(nonminpush.begin(), nonminpush.end());
650  BOOST_CHECK(miniscript::FromScript(nonminpush_script, wsh_converter) == nullptr);
651  BOOST_CHECK(miniscript::FromScript(nonminpush_script, tap_converter) == nullptr);
652  // A non-minimal VERIFY (<key> CHECKSIG VERIFY 1)
653  std::vector<unsigned char> nonminverify = ParseHex("2103a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7ac6951");
654  const CScript nonminverify_script(nonminverify.begin(), nonminverify.end());
655  BOOST_CHECK(miniscript::FromScript(nonminverify_script, wsh_converter) == nullptr);
656  BOOST_CHECK(miniscript::FromScript(nonminverify_script, tap_converter) == nullptr);
657  // A threshold as large as the number of subs is valid.
658  Test("thresh(2,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(100))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670164b16951686c935287", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac6b6300670164b16951686c935287", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_NONMAL);
659  // A threshold of 1 is valid.
660  Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "20d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c20fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", TESTMODE_VALID | TESTMODE_NEEDSIG | TESTMODE_NONMAL);
661  // A threshold with a k larger than the number of subs is invalid
662  Test("thresh(3,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "=", TESTMODE_INVALID);
663  // A threshold with a k null is invalid
664  Test("thresh(0,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),sc:pk_k(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))", "2103d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65ac7c2103fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556ac935187", "=", TESTMODE_INVALID);
665  // For CHECKMULTISIG the OP cost is the number of keys, but the stack size is the number of sigs (+1)
666  const auto ms_multi = miniscript::FromString("multi(1,03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)", wsh_converter);
667  BOOST_CHECK(ms_multi);
668  BOOST_CHECK_EQUAL(*ms_multi->GetOps(), 4); // 3 pubkeys + CMS
669  BOOST_CHECK_EQUAL(*ms_multi->GetStackSize(), 2); // 1 sig + dummy elem
670  // The 'd:' wrapper leaves on the stack what was DUP'ed at the beginning of its execution.
671  // Since it contains an OP_IF just after on the same element, we can make sure that the element
672  // in question must be OP_1 if OP_IF enforces that its argument must only be OP_1 or the empty
673  // vector (since otherwise the execution would immediately fail). This is the MINIMALIF rule.
674  // Unfortunately, this rule is consensus for Taproot but only policy for P2WSH. Therefore we can't
675  // (for now) have 'd:' be 'u'. This tests we can't use a 'd:' wrapper for a thresh, which requires
676  // its subs to all be 'u' (taken from https://github.com/rust-bitcoin/rust-miniscript/discussions/341).
677  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);
678  BOOST_CHECK(ms_minimalif && !ms_minimalif->IsValid());
679  // A Miniscript with duplicate keys is not sane
680  const auto ms_dup1 = miniscript::FromString("and_v(v:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", wsh_converter);
681  BOOST_CHECK(ms_dup1);
682  BOOST_CHECK(!ms_dup1->IsSane() && !ms_dup1->CheckDuplicateKey());
683  // Same with a disjunction, and different key nodes (pk and pkh)
684  const auto ms_dup2 = miniscript::FromString("or_b(c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),ac:pk_h(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", wsh_converter);
685  BOOST_CHECK(ms_dup2 && !ms_dup2->IsSane() && !ms_dup2->CheckDuplicateKey());
686  // Same when the duplicates are leaves or a larger tree
687  const auto ms_dup3 = miniscript::FromString("or_i(and_b(pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556)),and_b(older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", wsh_converter);
688  BOOST_CHECK(ms_dup3 && !ms_dup3->IsSane() && !ms_dup3->CheckDuplicateKey());
689  // Same when the duplicates are on different levels in the tree
690  const auto ms_dup4 = miniscript::FromString("thresh(2,pkh(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),s:pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),a:and_b(dv:older(1),s:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)))", wsh_converter);
691  BOOST_CHECK(ms_dup4 && !ms_dup4->IsSane() && !ms_dup4->CheckDuplicateKey());
692  // Sanity check the opposite is true, too. An otherwise sane Miniscript with no duplicate keys is sane.
693  const auto ms_nondup = miniscript::FromString("pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65)", wsh_converter);
694  BOOST_CHECK(ms_nondup && ms_nondup->CheckDuplicateKey() && ms_nondup->IsSane());
695  // Test we find the first insane sub closer to be a leaf node. This fragment is insane for two reasons:
696  // 1. It can be spent without a signature
697  // 2. It contains timelock mixes
698  // We'll report the timelock mix error, as it's "deeper" (closer to be a leaf node) than the "no 's' property"
699  // error is.
700  const auto ms_ins = miniscript::FromString("or_i(and_b(after(1),a:after(1000000000)),pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204))", wsh_converter);
701  BOOST_CHECK(ms_ins && ms_ins->IsValid() && !ms_ins->IsSane());
702  const auto insane_sub = ms_ins->FindInsaneSub();
703  BOOST_CHECK(insane_sub && *insane_sub->ToString(wsh_converter) == "and_b(after(1),a:after(1000000000))");
704 
705  // Timelock tests
706  Test("after(100)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only heightlock
707  Test("after(1000000000)", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only timelock
708  Test("or_b(l:after(100),al:after(1000000000))", "?", "?", TESTMODE_VALID); // or_b(timelock, heighlock) valid
709  Test("and_b(after(100),a:after(1000000000))", "?", "?", TESTMODE_VALID | TESTMODE_NONMAL | TESTMODE_TIMELOCKMIX); // and_b(timelock, heighlock) invalid
710  /* This is correctly detected as non-malleable but for the wrong reason. The type system assumes that branches 1 and 2
711  can be spent together to create a non-malleble witness, but because of mixing of timelocks they cannot be spent together.
712  But since exactly one of the two after's can be satisfied, the witness involving the key cannot be malleated.
713  */
714  Test("thresh(2,ltv:after(1000000000),altv:after(100),a:pk(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65))", "?", "?", TESTMODE_VALID | TESTMODE_TIMELOCKMIX | TESTMODE_NONMAL); // thresh with k = 2
715  // This is actually non-malleable in practice, but we cannot detect it in type system. See above rationale
716  Test("thresh(1,c:pk_k(03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65),altv:after(1000000000),altv:after(100))", "?", "?", TESTMODE_VALID); // thresh with k = 1
717 
718  g_testdata.reset();
719 }
720 
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
#define LIFETIMEBOUND
Definition: attributes.h:16
virtual bool CheckLockTime(const CScriptNum &nLockTime) const
Definition: interpreter.h:258
virtual bool CheckSchnorrSignature(Span< const unsigned char > sig, Span< const unsigned char > pubkey, SigVersion sigversion, ScriptExecutionData &execdata, ScriptError *serror=nullptr) const
Definition: interpreter.h:253
virtual bool CheckSequence(const CScriptNum &nSequence) const
Definition: interpreter.h:263
virtual bool CheckECDSASignature(const std::vector< unsigned char > &scriptSig, const std::vector< unsigned char > &vchPubKey, const CScript &scriptCode, SigVersion sigversion) const
Definition: interpreter.h:248
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
CHash256 & Write(Span< const unsigned char > input)
Definition: hash.h:37
void Finalize(Span< unsigned char > output)
Definition: hash.h:30
An encapsulated private key.
Definition: key.h:33
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:278
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:214
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:188
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:99
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 * end() const
Definition: pubkey.h:115
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 * begin() const
Definition: pubkey.h:114
const unsigned char * data() const
Definition: pubkey.h:113
A hasher class for RIPEMD-160.
Definition: ripemd160.h:13
CRIPEMD160 & Write(const unsigned char *data, size_t len)
Definition: ripemd160.cpp:247
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: ripemd160.cpp:273
A hasher class for SHA-256.
Definition: sha256.h:14
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha256.cpp:728
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:702
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:414
int64_t GetInt64() const
Definition: script.h:341
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:290
CPubKey GetEvenCorrespondingCPubKey() const
Definition: pubkey.cpp:207
constexpr unsigned char * begin()
Definition: uint256.h:68
iterator begin()
Definition: prevector.h:304
iterator end()
Definition: prevector.h:306
160-bit opaque blob.
Definition: uint256.h:95
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
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
SigVersion
Definition: interpreter.h:191
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
Definition: interpreter.h:232
uint64_t sequence
BOOST_AUTO_TEST_CASE(fixed_tests)
std::shared_ptr< const Node< Key > > NodeRef
Definition: miniscript.h:187
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
Definition: miniscript.h:240
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
Definition: miniscript.h:2618
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
Definition: miniscript.h:2613
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
Definition: init.h:25
Internal RIPEMD-160 implementation.
Definition: ripemd160.cpp:16
Internal SHA-256 implementation.
Definition: sha256.cpp:71
#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
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
Definition: random.h:265
@ OP_0
Definition: script.h:75
enum ScriptError_t ScriptError
@ SCRIPT_ERR_OP_COUNT
Definition: script_error.h:21
@ SCRIPT_ERR_STACK_SIZE
Definition: script_error.h:22
size_t GetSerializeSize(const T &t)
Definition: serialize.h:1116
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:310
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
Definition: strencodings.h:65
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:110
Basic testing setup.
Definition: setup_common.h:52
std::vector< std::vector< unsigned char > > stack
Definition: script.h:569
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
uint256 uint256S(const char *str)
Definition: uint256.h:119
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
assert(!tx.IsCoinBase())