Bitcoin Core  31.0.0
P2P Digital Currency
miniscript_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019-present The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <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  std::optional<Key> FromString(std::span<const char>& in) const {
163  auto bytes = ParseHex(std::string(in.begin(), in.end()));
164  Key key{bytes.begin(), bytes.end()};
165  if (key.IsValid()) return key;
166  return {};
167  }
168 
169  template<typename I>
170  std::optional<Key> FromPKBytes(I first, I last) const {
171  if (!miniscript::IsTapscript(m_script_ctx)) {
172  Key key{first, last};
173  if (key.IsValid()) return key;
174  return {};
175  }
176  if (last - first != 32) return {};
177  XOnlyPubKey xonly_pubkey;
178  std::copy(first, last, xonly_pubkey.begin());
179  return xonly_pubkey.GetEvenCorrespondingCPubKey();
180  }
181 
182  template<typename I>
183  std::optional<Key> FromPKHBytes(I first, I last) const {
184  assert(last - first == 20);
185  CKeyID keyid;
186  std::copy(first, last, keyid.begin());
187  return g_testdata->pkmap.at(keyid);
188  }
189 
190  std::optional<std::string> ToString(const Key& key, bool&) const {
191  return HexStr(ToPKBytes(key));
192  }
193 
194  miniscript::MiniscriptContext MsContext() const {
195  return m_script_ctx;
196  }
197 };
198 
200 struct Satisfier : public KeyConverter {
201 
202  Satisfier(miniscript::MiniscriptContext ctx) noexcept : KeyConverter{ctx} {}
203 
205  std::set<Challenge> supported;
206 
208  bool CheckAfter(uint32_t value) const {
209  return supported.contains(Challenge(ChallengeType::AFTER, value));
210  }
211 
213  bool CheckOlder(uint32_t value) const {
214  return supported.contains(Challenge(ChallengeType::OLDER, value));
215  }
216 
218  miniscript::Availability Sign(const CPubKey& key, std::vector<unsigned char>& sig) const {
219  if (supported.contains(Challenge(ChallengeType::PK, ChallengeNumber(key)))) {
220  if (!miniscript::IsTapscript(m_script_ctx)) {
221  auto it = g_testdata->signatures.find(key);
222  if (it == g_testdata->signatures.end()) return miniscript::Availability::NO;
223  sig = it->second;
224  } else {
225  auto it = g_testdata->schnorr_signatures.find(XOnlyPubKey{key});
226  if (it == g_testdata->schnorr_signatures.end()) return miniscript::Availability::NO;
227  sig = it->second;
228  }
230  }
232  }
233 
235  miniscript::Availability SatHash(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage, ChallengeType chtype) const {
236  if (!supported.contains(Challenge(chtype, ChallengeNumber(hash)))) return miniscript::Availability::NO;
237  const auto& m =
238  chtype == ChallengeType::SHA256 ? g_testdata->sha256_preimages :
239  chtype == ChallengeType::HASH256 ? g_testdata->hash256_preimages :
240  chtype == ChallengeType::RIPEMD160 ? g_testdata->ripemd160_preimages :
241  g_testdata->hash160_preimages;
242  auto it = m.find(hash);
243  if (it == m.end()) return miniscript::Availability::NO;
244  preimage = it->second;
246  }
247 
248  // Functions that produce the preimage for hashes of various types.
249  miniscript::Availability SatSHA256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return SatHash(hash, preimage, ChallengeType::SHA256); }
250  miniscript::Availability SatRIPEMD160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return SatHash(hash, preimage, ChallengeType::RIPEMD160); }
251  miniscript::Availability SatHASH256(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return SatHash(hash, preimage, ChallengeType::HASH256); }
252  miniscript::Availability SatHASH160(const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage) const { return SatHash(hash, preimage, ChallengeType::HASH160); }
253 };
254 
259 class TestSignatureChecker : public BaseSignatureChecker {
260  const Satisfier& ctx;
261 
262 public:
263  TestSignatureChecker(const Satisfier& in_ctx LIFETIMEBOUND) : ctx(in_ctx) {}
264 
265  bool CheckECDSASignature(const std::vector<unsigned char>& sig, const std::vector<unsigned char>& pubkey, const CScript& scriptcode, SigVersion sigversion) const override {
266  CPubKey pk(pubkey);
267  if (!pk.IsValid()) return false;
268  // Instead of actually running signature validation, check if the signature matches the precomputed one for this key.
269  auto it = g_testdata->signatures.find(pk);
270  if (it == g_testdata->signatures.end()) return false;
271  return sig == it->second;
272  }
273 
274  bool CheckSchnorrSignature(std::span<const unsigned char> sig, std::span<const unsigned char> pubkey, SigVersion,
275  ScriptExecutionData&, ScriptError*) const override {
276  XOnlyPubKey pk{pubkey};
277  auto it = g_testdata->schnorr_signatures.find(pk);
278  if (it == g_testdata->schnorr_signatures.end()) return false;
279  return std::ranges::equal(sig, it->second);
280  }
281 
282  bool CheckLockTime(const CScriptNum& locktime) const override {
283  // Delegate to Satisfier.
284  return ctx.CheckAfter(locktime.GetInt64());
285  }
286 
287  bool CheckSequence(const CScriptNum& sequence) const override {
288  // Delegate to Satisfier.
289  return ctx.CheckOlder(sequence.GetInt64());
290  }
291 };
292 
294 using miniscript::operator""_mst;
295 using Node = miniscript::Node<CPubKey>;
296 
298 std::set<Challenge> FindChallenges(const Node& root)
299 {
300  std::set<Challenge> chal;
301 
302  for (std::vector stack{&root}; !stack.empty();) {
303  const auto* ref{stack.back()};
304  stack.pop_back();
305 
306  for (const auto& key : ref->Keys()) {
307  chal.emplace(ChallengeType::PK, ChallengeNumber(key));
308  }
309  switch (ref->Fragment()) {
310  case Fragment::OLDER: chal.emplace(ChallengeType::OLDER, ref->K()); break;
311  case Fragment::AFTER: chal.emplace(ChallengeType::AFTER, ref->K()); break;
312  case Fragment::SHA256: chal.emplace(ChallengeType::SHA256, ChallengeNumber(ref->Data())); break;
313  case Fragment::RIPEMD160: chal.emplace(ChallengeType::RIPEMD160, ChallengeNumber(ref->Data())); break;
314  case Fragment::HASH256: chal.emplace(ChallengeType::HASH256, ChallengeNumber(ref->Data())); break;
315  case Fragment::HASH160: chal.emplace(ChallengeType::HASH160, ChallengeNumber(ref->Data())); break;
316  default: break;
317  }
318  for (const auto& sub : ref->Subs()) {
319  stack.push_back(&sub);
320  }
321  }
322  return chal;
323 }
324 
326 CScript ScriptPubKey(miniscript::MiniscriptContext ctx, const CScript& script, TaprootBuilder& builder)
327 {
329 
330  // For Taproot outputs we always use a tree with a single script and a dummy internal key.
331  builder.Add(0, script, TAPROOT_LEAF_TAPSCRIPT);
332  builder.Finalize(XOnlyPubKey::NUMS_H);
333  return GetScriptForDestination(builder.GetOutput());
334 }
335 
337 void SatisfactionToWitness(miniscript::MiniscriptContext ctx, CScriptWitness& witness, const CScript& script, TaprootBuilder& builder) {
338  // For P2WSH, it's only the witness script.
339  witness.stack.emplace_back(script.begin(), script.end());
340  if (!miniscript::IsTapscript(ctx)) return;
341  // For Tapscript we also need the control block.
342  witness.stack.push_back(*builder.GetSpendData().scripts.begin()->second.begin());
343 }
344 
345 struct MiniScriptTest : BasicTestingSetup {
347 void TestSatisfy(const KeyConverter& converter, const Node& node)
348 {
349  auto script = node.ToScript(converter);
350  const 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 uint64_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, *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) == std::nullopt);
603  const auto incomplete_multi_a{"ba20c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5ba519c"_hex_u8};
604  BOOST_CHECK(miniscript::FromScript({incomplete_multi_a.begin(), incomplete_multi_a.end()}, tap_converter) == std::nullopt);
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) == std::nullopt);
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) == std::nullopt);
653  BOOST_CHECK(miniscript::FromScript(nonminpush_script, tap_converter) == std::nullopt);
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) == std::nullopt);
658  BOOST_CHECK(miniscript::FromScript(nonminverify_script, tap_converter) == std::nullopt);
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 
729 // Confirm that ~Node(), Node::Clone() and operator=(Node&&) are stack-safe.
730 BOOST_AUTO_TEST_CASE(node_deep_destruct)
731 {
733  using miniscript::Fragment;
734  using NodeU32 = miniscript::Node<uint32_t>;
735 
736  constexpr auto ctx{miniscript::MiniscriptContext::P2WSH};
737 
738  NodeU32 root{NoDupCheck{}, ctx, Fragment::JUST_1};
739  for (uint32_t i{0}; i < 200'000; ++i) {
740  root = NodeU32{NoDupCheck{}, ctx, Fragment::WRAP_S, Vector(std::move(root))};
741  }
742  BOOST_CHECK_EQUAL(root.ScriptSize(), 200'001);
743 
744  auto clone{root.Clone()};
745  BOOST_CHECK_EQUAL(clone.ScriptSize(), root.ScriptSize());
746 
747  clone = std::move(root);
748 }
749 
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:699
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:69
assert(!tx.IsCoinBase())
enum ScriptError_t ScriptError
CHash160 & Write(std::span< const unsigned char > input)
Definition: hash.h:62
uint160 RIPEMD160(std::span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
Definition: hash.h:222
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:183
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
Definition: miniscript.h:257
std::vector< std::vector< unsigned char > > stack
Definition: script.h:580
Satisfier(const SigningProvider &provider LIFETIMEBOUND, SignatureData &sig_data LIFETIMEBOUND, const BaseSignatureCreator &creator LIFETIMEBOUND, const CScript &witscript LIFETIMEBOUND, miniscript::MiniscriptContext script_ctx)
Definition: sign.cpp:414
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
Definition: interpreter.h:242
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:235
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
std::optional< Node< typename Ctx::Key > > FromString(const std::string &str, const Ctx &ctx)
Definition: miniscript.h:2682
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, script_verify_flags flags, const BaseSignatureChecker &checker, ScriptError *serror)
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:160
const unsigned char * begin() const
Definition: pubkey.h:114
Basic testing setup.
Definition: setup_common.h:64
constexpr unsigned char * begin()
Definition: uint256.h:100
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:209
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
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
void Finalize(std::span< unsigned char > output)
Definition: hash.h:30
bool IsValid() const
Definition: pubkey.h:185
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:203
WitnessV1Taproot GetOutput()
Compute scriptPubKey (after Finalize()).
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha256.cpp:725
uint64_t GetSerializeSize(const T &t)
Definition: serialize.h:1095
static constexpr script_verify_flags STANDARD_SCRIPT_VERIFY_FLAGS
Standard script verification flags that standard transactions will comply with.
Definition: policy.h:118
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
Definition: strencodings.h:400
CPubKey GetEvenCorrespondingCPubKey() const
Definition: pubkey.cpp:223
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:104
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:21
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
void Finalize(std::span< unsigned char > output)
Definition: hash.h:55
256-bit opaque blob.
Definition: uint256.h:195
std::optional< Node< typename Ctx::Key > > FromScript(const CScript &script, const Ctx &ctx)
Definition: miniscript.h:2688
TaprootBuilder & Add(int depth, std::span< const unsigned char > script, int leaf_version, bool track=true)
Add a new script at a certain depth in the tree.
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:17
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:404
Fragment
The different node types in miniscript.
Definition: miniscript.h:211
Internal SHA-256 implementation.
Definition: sha256.cpp:67
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:23
160-bit opaque blob.
Definition: uint256.h:183
bool SignSchnorr(const uint256 &hash, std::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:273
static int count
int64_t GetInt64() const
Definition: script.h:334
const unsigned char * data() const
Definition: pubkey.h:113
An encapsulated private key.
Definition: key.h:35
A node in a miniscript expression.
Definition: miniscript.h:193
A hasher class for Bitcoin&#39;s 160-bit hash (SHA-256 + RIPEMD-160).
Definition: hash.h:49
uint64_t sequence
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 – 5 ...
Definition: serialize.h:288
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: hex_base.cpp:30
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:246
A hasher class for RIPEMD-160.
Definition: ripemd160.h:12
#define BOOST_CHECK(expr)
Definition: object.cpp:16
Internal RIPEMD-160 implementation.
Definition: ripemd160.cpp:15
SigVersion
Definition: interpreter.h:200
CHash256 & Write(std::span< const unsigned char > input)
Definition: hash.h:37