23 using miniscript::operator
"" _mst;
30 std::vector<Key> dummy_keys;
31 std::map<Key, int> dummy_key_idx_map;
32 std::map<CKeyID, Key> dummy_keys_map;
33 std::map<Key, std::pair<std::vector<unsigned char>,
bool>> dummy_sigs;
34 std::map<XOnlyPubKey, std::pair<std::vector<unsigned char>,
bool>> schnorr_sigs;
37 std::vector<std::vector<unsigned char>>
sha256;
38 std::vector<std::vector<unsigned char>>
ripemd160;
39 std::vector<std::vector<unsigned char>> hash256;
40 std::vector<std::vector<unsigned char>> hash160;
41 std::map<std::vector<unsigned char>, std::vector<unsigned char>> sha256_preimages;
42 std::map<std::vector<unsigned char>, std::vector<unsigned char>> ripemd160_preimages;
43 std::map<std::vector<unsigned char>, std::vector<unsigned char>> hash256_preimages;
44 std::map<std::vector<unsigned char>, std::vector<unsigned char>> hash160_preimages;
48 unsigned char keydata[32] = {1};
50 auto const MESSAGE_HASH{
uint256S(
"f5cd94e18b6fe77dd7aca9e35c2b0c9cbd86356c80a71065")};
54 for (
size_t i = 0; i < 256; i++) {
57 privkey.
Set(keydata, keydata + 32,
true);
60 dummy_keys.push_back(pubkey);
61 dummy_key_idx_map.emplace(pubkey, i);
62 dummy_keys_map.insert({pubkey.GetID(), pubkey});
64 dummy_key_idx_map.emplace(xonly_pubkey, i);
66 dummy_keys_map.emplace(xonly_hash, pubkey);
68 std::vector<unsigned char> sig, schnorr_sig(64);
69 privkey.
Sign(MESSAGE_HASH, sig);
71 dummy_sigs.insert({pubkey, {sig, i & 1}});
73 schnorr_sig.push_back(1);
74 schnorr_sigs.emplace(
XOnlyPubKey{pubkey}, std::make_pair(std::move(schnorr_sig), i & 1));
76 std::vector<unsigned char> hash;
80 if (i & 1) sha256_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
82 hash256.push_back(hash);
83 if (i & 1) hash256_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
88 if (i & 1) ripemd160_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
90 hash160.push_back(hash);
91 if (i & 1) hash160_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
96 const std::pair<std::vector<unsigned char>,
bool>* GetSig(
const MsCtx script_ctx,
const Key& key)
const {
98 const auto it = dummy_sigs.find(key);
99 if (it == dummy_sigs.end())
return nullptr;
102 const auto it = schnorr_sigs.find(
XOnlyPubKey{key});
103 if (it == schnorr_sigs.end())
return nullptr;
114 struct ParserContext {
117 const MsCtx script_ctx;
119 constexpr ParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
121 bool KeyCompare(
const Key& a,
const Key& b)
const {
125 std::optional<std::string>
ToString(
const Key& key)
const
127 auto it = TEST_DATA.dummy_key_idx_map.find(key);
128 if (it == TEST_DATA.dummy_key_idx_map.end())
return {};
129 uint8_t idx = it->second;
133 std::vector<unsigned char> ToPKBytes(
const Key& key)
const {
135 return {key.begin(), key.end()};
138 return {xonly_pubkey.
begin(), xonly_pubkey.end()};
141 std::vector<unsigned char> ToPKHBytes(
const Key& key)
const {
144 return {h.begin(), h.end()};
147 return {h.
begin(), h.end()};
151 std::optional<Key>
FromString(I first, I last)
const {
152 if (last - first != 2)
return {};
153 auto idx =
ParseHex(std::string(first, last));
154 if (idx.size() != 1)
return {};
155 return TEST_DATA.dummy_keys[idx[0]];
159 std::optional<Key> FromPKBytes(I first, I last)
const {
161 Key key{first, last};
162 if (key.IsValid())
return key;
165 if (last - first != 32)
return {};
167 std::copy(first, last, xonly_pubkey.
begin());
172 std::optional<Key> FromPKHBytes(I first, I last)
const {
173 assert(last - first == 20);
175 std::copy(first, last, keyid.
begin());
176 const auto it = TEST_DATA.dummy_keys_map.find(keyid);
177 if (it == TEST_DATA.dummy_keys_map.end())
return {};
181 MsCtx MsContext()
const {
187 struct ScriptParserContext {
188 const MsCtx script_ctx;
190 constexpr ScriptParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
195 std::vector<unsigned char> data;
198 bool KeyCompare(
const Key& a,
const Key& b)
const {
199 return a.data < b.data;
202 const std::vector<unsigned char>& ToPKBytes(
const Key& key)
const
208 std::vector<unsigned char> ToPKHBytes(
const Key& key)
const
210 if (key.is_hash)
return key.data;
211 const auto h =
Hash160(key.data);
212 return {h.begin(), h.end()};
216 std::optional<Key> FromPKBytes(I first, I last)
const
219 key.data.assign(first, last);
225 std::optional<Key> FromPKHBytes(I first, I last)
const
228 key.data.assign(first, last);
233 MsCtx MsContext()
const {
239 struct SatisfierContext : ParserContext {
241 constexpr SatisfierContext(MsCtx ctx) noexcept : ParserContext(ctx) {}
245 bool CheckAfter(uint32_t value)
const {
return value % 2; }
246 bool CheckOlder(uint32_t value)
const {
return value % 2; }
250 bool sig_available{
false};
251 if (
auto res = TEST_DATA.GetSig(script_ctx, key)) {
252 std::tie(sig, sig_available) = *res;
259 const std::map<std::vector<unsigned char>, std::vector<unsigned char>>& map)
const
261 const auto it = map.find(hash);
263 preimage = it->second;
266 miniscript::Availability SatSHA256(
const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage)
const {
267 return LookupHash(hash, preimage, TEST_DATA.sha256_preimages);
269 miniscript::Availability SatRIPEMD160(
const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage)
const {
270 return LookupHash(hash, preimage, TEST_DATA.ripemd160_preimages);
272 miniscript::Availability SatHASH256(
const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage)
const {
273 return LookupHash(hash, preimage, TEST_DATA.hash256_preimages);
275 miniscript::Availability SatHASH160(
const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage)
const {
276 return LookupHash(hash, preimage, TEST_DATA.hash160_preimages);
283 bool CheckECDSASignature(
const std::vector<unsigned char>& sig,
const std::vector<unsigned char>& vchPubKey,
287 const auto it = TEST_DATA.dummy_sigs.find(key);
288 if (it == TEST_DATA.dummy_sigs.end())
return false;
289 return it->second.first == sig;
294 auto it = TEST_DATA.schnorr_sigs.find(
pk);
295 if (it == TEST_DATA.schnorr_sigs.end())
return false;
296 return it->second.
first == sig;
303 const struct KeyComparator {
324 std::vector<CPubKey> keys;
326 std::vector<unsigned char> hash;
328 std::vector<Type> subtypes;
330 NodeInfo(
Fragment frag): fragment(frag),
k(0) {}
332 NodeInfo(
Fragment frag, uint32_t _k): fragment(frag),
k(_k) {}
333 NodeInfo(
Fragment frag, std::vector<unsigned char> h): fragment(frag),
k(0), hash(
std::move(h)) {}
334 NodeInfo(std::vector<Type> subt,
Fragment frag): fragment(frag),
k(0), subtypes(
std::move(subt)) {}
335 NodeInfo(std::vector<Type> subt,
Fragment frag, uint32_t _k): fragment(frag),
k(_k), subtypes(
std::move(subt)) {}
336 NodeInfo(
Fragment frag, uint32_t _k, std::vector<CPubKey> _keys): fragment(frag),
k(_k), keys(
std::move(_keys)) {}
340 template<
typename T,
typename A>
347 return ConsumeIndex<CPubKey>(provider, TEST_DATA.dummy_keys);
351 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.sha256);
355 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.hash256);
359 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.ripemd160);
363 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.hash160);
368 if (k == 0 || k >= 0x80000000)
return {};
386 std::optional<NodeInfo> ConsumeNodeStable(MsCtx script_ctx,
FuzzedDataProvider& provider, Type type_needed) {
387 bool allow_B = (type_needed ==
""_mst) || (type_needed <<
"B"_mst);
388 bool allow_K = (type_needed ==
""_mst) || (type_needed <<
"K"_mst);
389 bool allow_V = (type_needed ==
""_mst) || (type_needed <<
"V"_mst);
390 bool allow_W = (type_needed ==
""_mst) || (type_needed <<
"W"_mst);
391 static constexpr
auto B{
"B"_mst},
K{
"K"_mst}, V{
"V"_mst}, W{
"W"_mst};
395 if (!allow_B)
return {};
396 return {{Fragment::JUST_0}};
398 if (!allow_B)
return {};
399 return {{Fragment::JUST_1}};
401 if (!allow_K)
return {};
402 return {{Fragment::PK_K, ConsumePubKey(provider)}};
404 if (!allow_K)
return {};
405 return {{Fragment::PK_H, ConsumePubKey(provider)}};
407 if (!allow_B)
return {};
408 const auto k = ConsumeTimeLock(provider);
410 return {{Fragment::OLDER, *
k}};
413 if (!allow_B)
return {};
414 const auto k = ConsumeTimeLock(provider);
416 return {{Fragment::AFTER, *
k}};
419 if (!allow_B)
return {};
420 return {{Fragment::SHA256, ConsumeSha256(provider)}};
422 if (!allow_B)
return {};
423 return {{Fragment::HASH256, ConsumeHash256(provider)}};
425 if (!allow_B)
return {};
428 if (!allow_B)
return {};
429 return {{Fragment::HASH160, ConsumeHash160(provider)}};
431 if (!allow_B ||
IsTapscript(script_ctx))
return {};
434 if (n_keys > 20 || k == 0 || k > n_keys)
return {};
435 std::vector<CPubKey> keys{n_keys};
436 for (
auto& key: keys) key = ConsumePubKey(provider);
437 return {{Fragment::MULTI,
k, std::move(keys)}};
440 if (!(allow_B || allow_K || allow_V))
return {};
441 return {{{
B, type_needed, type_needed}, Fragment::ANDOR}};
443 if (!(allow_B || allow_K || allow_V))
return {};
444 return {{{V, type_needed}, Fragment::AND_V}};
446 if (!allow_B)
return {};
447 return {{{
B, W}, Fragment::AND_B}};
449 if (!allow_B)
return {};
450 return {{{
B, W}, Fragment::OR_B}};
452 if (!allow_V)
return {};
453 return {{{
B, V}, Fragment::OR_C}};
455 if (!allow_B)
return {};
456 return {{{
B,
B}, Fragment::OR_D}};
458 if (!(allow_B || allow_K || allow_V))
return {};
459 return {{{type_needed, type_needed}, Fragment::OR_I}};
461 if (!allow_B)
return {};
464 if (k == 0 || k > n_subs)
return {};
465 std::vector<Type> subtypes;
466 subtypes.reserve(n_subs);
467 subtypes.emplace_back(
"B"_mst);
468 for (
size_t i = 1; i < n_subs; ++i) subtypes.emplace_back(
"W"_mst);
469 return {{std::move(subtypes), Fragment::THRESH,
k}};
472 if (!allow_W)
return {};
473 return {{{
B}, Fragment::WRAP_A}};
475 if (!allow_W)
return {};
476 return {{{
B}, Fragment::WRAP_S}};
478 if (!allow_B)
return {};
479 return {{{
K}, Fragment::WRAP_C}};
481 if (!allow_B)
return {};
482 return {{{V}, Fragment::WRAP_D}};
484 if (!allow_V)
return {};
485 return {{{
B}, Fragment::WRAP_V}};
487 if (!allow_B)
return {};
488 return {{{
B}, Fragment::WRAP_J}};
490 if (!allow_B)
return {};
491 return {{{
B}, Fragment::WRAP_N}};
493 if (!allow_B || !
IsTapscript(script_ctx))
return {};
496 if (n_keys > 999 || k == 0 || k > n_keys)
return {};
497 std::vector<CPubKey> keys{n_keys};
498 for (
auto& key: keys) key = ConsumePubKey(provider);
499 return {{Fragment::MULTI_A,
k, std::move(keys)}};
516 using recipe = std::pair<Fragment, std::vector<Type>>;
517 std::map<Type, std::vector<recipe>> wsh_table, tap_table;
521 Init(wsh_table, MsCtx::P2WSH);
522 Init(tap_table, MsCtx::TAPSCRIPT);
525 void Init(std::map<Type, std::vector<recipe>>& table, MsCtx script_ctx)
528 std::vector<Type> types;
529 static constexpr
auto B_mst{
"B"_mst}, K_mst{
"K"_mst}, V_mst{
"V"_mst}, W_mst{
"W"_mst};
530 static constexpr
auto d_mst{
"d"_mst}, n_mst{
"n"_mst}, o_mst{
"o"_mst}, u_mst{
"u"_mst}, z_mst{
"z"_mst};
531 static constexpr
auto NONE_mst{
""_mst};
532 for (
int base = 0; base < 4; ++base) {
533 Type type_base = base == 0 ? B_mst : base == 1 ? K_mst : base == 2 ? V_mst : W_mst;
534 for (
int zo = 0; zo < 3; ++zo) {
535 Type type_zo = zo == 0 ? z_mst : zo == 1 ? o_mst : NONE_mst;
536 for (
int n = 0; n < 2; ++n) {
537 if (zo == 0 && n == 1)
continue;
538 if (base == 3 && n == 1)
continue;
539 Type type_n = n == 0 ? NONE_mst : n_mst;
540 for (
int d = 0; d < 2; ++d) {
541 if (base == 2 && d == 1)
continue;
542 Type type_d = d == 0 ? NONE_mst : d_mst;
543 for (
int u = 0; u < 2; ++u) {
544 if (base == 2 && u == 1)
continue;
545 Type type_u = u == 0 ? NONE_mst : u_mst;
546 Type type = type_base | type_zo | type_n | type_d | type_u;
547 types.push_back(type);
560 auto is_super_of = [](
const recipe& a,
const recipe& b) {
561 if (a.first != b.first)
return false;
562 if (a.second.size() != b.second.size())
return false;
563 for (
size_t i = 0; i < a.second.size(); ++i) {
564 if (!(b.second[i] << a.second[i]))
return false;
574 std::sort(types.begin(), types.end());
577 for (
int fragidx = 0; fragidx <= int(Fragment::MULTI_A); ++fragidx) {
580 size_t data_size = 0;
597 case Fragment::MULTI:
598 case Fragment::MULTI_A:
602 case Fragment::OLDER:
603 case Fragment::AFTER:
606 case Fragment::SHA256:
607 case Fragment::HASH256:
611 case Fragment::HASH160:
614 case Fragment::JUST_0:
615 case Fragment::JUST_1:
617 case Fragment::WRAP_A:
618 case Fragment::WRAP_S:
619 case Fragment::WRAP_C:
620 case Fragment::WRAP_D:
621 case Fragment::WRAP_V:
622 case Fragment::WRAP_J:
623 case Fragment::WRAP_N:
626 case Fragment::AND_V:
627 case Fragment::AND_B:
634 case Fragment::ANDOR:
637 case Fragment::THRESH:
646 std::vector<Type> subt;
647 for (
int subs = sub_count; subs < sub_count + sub_range; ++subs) {
649 for (Type x : types) {
650 for (Type y : types) {
651 for (Type z : types) {
654 if (subs > 0) subt.push_back(x);
655 if (subs > 1) subt.push_back(y);
656 if (subs > 2) subt.push_back(z);
659 if ((res <<
"K"_mst) + (res <<
"V"_mst) + (res <<
"B"_mst) + (res <<
"W"_mst) != 1)
continue;
661 recipe entry{frag, subt};
662 auto super_of_entry = [&](
const recipe& rec) {
return is_super_of(rec, entry); };
665 for (Type s : types) {
666 if ((res &
"BKVWzondu"_mst) << s) {
667 auto& recipes = table[s];
669 if (!std::any_of(recipes.begin(), recipes.end(), super_of_entry)) {
670 recipes.push_back(entry);
675 if (subs <= 2)
break;
677 if (subs <= 1)
break;
679 if (subs <= 0)
break;
687 std::set<Type> useful_types{B_mst, V_mst, K_mst, W_mst};
690 size_t set_size = useful_types.size();
691 for (
const auto& [type, recipes] : table) {
692 if (useful_types.count(type) != 0) {
693 for (
const auto& [
_, subtypes] : recipes) {
694 for (
auto subtype : subtypes) useful_types.insert(subtype);
698 if (useful_types.size() == set_size)
break;
701 for (
auto type_it = table.begin(); type_it != table.end();) {
702 if (useful_types.count(type_it->first) == 0) {
703 type_it = table.erase(type_it);
714 std::set<Type> constructible_types{};
715 auto known_constructible = [&](Type type) {
return constructible_types.count(type) != 0; };
718 size_t set_size = constructible_types.size();
720 for (
const auto& [type, recipes] : table) {
721 if (!known_constructible(type)) {
723 for (
const auto& [
_, subt] : recipes) {
726 if (std::all_of(subt.begin(), subt.end(), known_constructible)) {
727 constructible_types.insert(type);
733 if (constructible_types.size() == set_size)
break;
735 for (
auto type_it = table.begin(); type_it != table.end();) {
737 type_it->second.erase(std::remove_if(type_it->second.begin(), type_it->second.end(),
738 [&](
const recipe& rec) {
739 return !std::all_of(rec.second.begin(), rec.second.end(), known_constructible);
740 }), type_it->second.end());
742 if (type_it->second.empty()) {
743 type_it = table.erase(type_it);
749 for (
auto& [type, recipes] : table) {
753 std::sort(recipes.begin(), recipes.end(),
754 [](
const recipe& a,
const recipe& b) {
755 if (a.second.size() < b.second.size()) return true;
756 if (a.second.size() > b.second.size()) return false;
774 std::optional<NodeInfo> ConsumeNodeSmart(MsCtx script_ctx,
FuzzedDataProvider& provider, Type type_needed) {
776 const auto& table{
IsTapscript(script_ctx) ? SMARTINFO.tap_table : SMARTINFO.wsh_table};
777 auto recipes_it = table.find(type_needed);
778 assert(recipes_it != table.end());
780 const auto& [frag, subt] =
PickValue(provider, recipes_it->second);
786 return {{frag, ConsumePubKey(provider)}};
787 case Fragment::MULTI: {
790 std::vector<CPubKey> keys{n_keys};
791 for (
auto& key: keys) key = ConsumePubKey(provider);
792 return {{frag,
k, std::move(keys)}};
794 case Fragment::MULTI_A: {
797 std::vector<CPubKey> keys{n_keys};
798 for (
auto& key: keys) key = ConsumePubKey(provider);
799 return {{frag,
k, std::move(keys)}};
801 case Fragment::OLDER:
802 case Fragment::AFTER:
804 case Fragment::SHA256:
805 return {{frag,
PickValue(provider, TEST_DATA.sha256)}};
806 case Fragment::HASH256:
807 return {{frag,
PickValue(provider, TEST_DATA.hash256)}};
809 return {{frag,
PickValue(provider, TEST_DATA.ripemd160)}};
810 case Fragment::HASH160:
811 return {{frag,
PickValue(provider, TEST_DATA.hash160)}};
812 case Fragment::JUST_0:
813 case Fragment::JUST_1:
814 case Fragment::WRAP_A:
815 case Fragment::WRAP_S:
816 case Fragment::WRAP_C:
817 case Fragment::WRAP_D:
818 case Fragment::WRAP_V:
819 case Fragment::WRAP_J:
820 case Fragment::WRAP_N:
821 case Fragment::AND_V:
822 case Fragment::AND_B:
827 case Fragment::ANDOR:
828 return {{subt, frag}};
829 case Fragment::THRESH: {
831 if (subt.size() < 2) {
832 children = subt.size();
839 std::vector<Type> subs = subt;
840 while (subs.size() < children) subs.push_back(subs.back());
841 return {{std::move(subs), frag,
k}};
857 NodeRef GenNode(MsCtx script_ctx, F
ConsumeNode, Type root_type,
bool strict_valid =
false) {
859 std::vector<NodeRef> stack;
861 std::vector<std::pair<Type, std::optional<NodeInfo>>> todo{{root_type, {}}};
866 uint32_t scriptsize{1};
868 while (!todo.empty()) {
870 auto type_needed = todo.back().first;
871 if (!todo.back().second) {
874 if (!node_info)
return {};
879 node_info->keys.size(), script_ctx) - 1;
881 switch (node_info->fragment) {
882 case Fragment::JUST_0:
883 case Fragment::JUST_1:
890 case Fragment::OLDER:
891 case Fragment::AFTER:
895 case Fragment::SHA256:
896 case Fragment::HASH160:
897 case Fragment::HASH256:
900 case Fragment::ANDOR:
903 case Fragment::AND_V:
905 case Fragment::AND_B:
918 case Fragment::THRESH:
919 ops += node_info->subtypes.
size();
921 case Fragment::MULTI:
924 case Fragment::MULTI_A:
925 ops += node_info->keys.size() + 1;
927 case Fragment::WRAP_A:
930 case Fragment::WRAP_S:
933 case Fragment::WRAP_C:
936 case Fragment::WRAP_D:
939 case Fragment::WRAP_V:
943 case Fragment::WRAP_J:
946 case Fragment::WRAP_N:
951 auto subtypes = node_info->subtypes;
952 todo.back().second = std::move(node_info);
953 todo.reserve(todo.size() + subtypes.size());
956 for (
size_t i = 0; i < subtypes.size(); ++i) {
957 todo.emplace_back(*(subtypes.rbegin() + i), std::nullopt);
964 NodeInfo& info = *todo.back().second;
966 std::vector<NodeRef> sub;
967 sub.reserve(info.subtypes.size());
968 for (
size_t i = 0; i < info.subtypes.size(); ++i) {
969 sub.push_back(std::move(*(stack.end() - info.subtypes.size() + i)));
971 stack.erase(stack.end() - info.subtypes.size(), stack.end());
974 if (info.keys.empty()) {
975 node =
MakeNodeRef(script_ctx, info.fragment, std::move(sub), std::move(info.hash), info.k);
978 assert(info.hash.empty());
979 node =
MakeNodeRef(script_ctx, info.fragment, std::move(info.keys), info.k);
982 if (!
node || (
node->GetType() &
"KVWB"_mst) ==
""_mst) {
986 if (!(type_needed ==
""_mst)) {
989 if (!
node->IsValid())
return {};
991 if (
node->fragment == Fragment::WRAP_V &&
node->subs[0]->GetType() <<
"x"_mst) {
1000 stack.push_back(std::move(
node));
1004 assert(stack.size() == 1);
1005 assert(stack[0]->GetStaticOps() == ops);
1006 assert(stack[0]->ScriptSize() == scriptsize);
1007 stack[0]->DuplicateKeyCheck(KEY_COMP);
1008 return std::move(stack[0]);
1037 const ParserContext parser_ctx{script_ctx};
1038 std::optional<std::string> str{
node->ToString(parser_ctx)};
1045 auto script =
node->ToScript(parser_ctx);
1050 if (!(
node->GetType() <<
"K"_mst)) {
1051 bool ends_in_verify = !(
node->GetType() <<
"x"_mst);
1056 if (!
node->IsValidTopLevel())
return;
1064 assert(decoded->ToScript(parser_ctx) == script);
1065 assert(decoded->GetType() ==
node->GetType());
1080 const auto node_ops{
node->GetOps()};
1083 int add = std::min<int>(
1091 const auto node_exec_ss{
node->GetExecStackSize()};
1094 witness_mal.
stack.resize(add);
1095 witness_nonmal.
stack.resize(add);
1101 const SatisfierContext satisfier_ctx{script_ctx};
1105 const CScript script_pubkey{ScriptPubKey(script_ctx, script, builder)};
1108 std::vector<std::vector<unsigned char>> stack_mal;
1112 std::vector<std::vector<unsigned char>> stack_nonmal;
1115 if (nonmal_success) {
1120 assert(stack_nonmal.size() <= max_stack_size);
1123 assert(stack_nonmal == stack_mal);
1126 assert(wit_size <= *node->GetWitnessSize());
1129 witness_nonmal.
stack.insert(witness_nonmal.
stack.end(), std::make_move_iterator(stack_nonmal.begin()), std::make_move_iterator(stack_nonmal.end()));
1130 SatisfactionToWitness(script_ctx, witness_nonmal, script, builder);
1142 if (mal_success && (!nonmal_success || witness_mal.
stack != witness_nonmal.
stack)) {
1144 witness_mal.
stack.insert(witness_mal.
stack.end(), std::make_move_iterator(stack_mal.begin()), std::make_move_iterator(stack_mal.end()));
1145 SatisfactionToWitness(script_ctx, witness_mal, script, builder);
1153 if (
node->IsSane()) {
1155 assert(mal_success == nonmal_success);
1162 const auto is_key_satisfiable = [script_ctx](
const CPubKey& pubkey) ->
bool {
1163 auto sig_ptr{TEST_DATA.GetSig(script_ctx, pubkey)};
1164 return sig_ptr !=
nullptr && sig_ptr->second;
1166 bool satisfiable =
node->IsSatisfiable([&](
const Node&
node) ->
bool {
1167 switch (
node.fragment) {
1168 case Fragment::PK_K:
1169 case Fragment::PK_H:
1170 return is_key_satisfiable(
node.keys[0]);
1171 case Fragment::MULTI:
1172 case Fragment::MULTI_A: {
1173 size_t sats = std::count_if(
node.keys.begin(),
node.keys.end(), [&](
const auto& key) {
1174 return size_t(is_key_satisfiable(key));
1176 return sats >=
node.k;
1178 case Fragment::OLDER:
1179 case Fragment::AFTER:
1181 case Fragment::SHA256:
1182 return TEST_DATA.sha256_preimages.count(
node.data);
1183 case Fragment::HASH256:
1184 return TEST_DATA.hash256_preimages.count(
node.data);
1186 return TEST_DATA.ripemd160_preimages.count(
node.data);
1187 case Fragment::HASH160:
1188 return TEST_DATA.hash160_preimages.count(
node.data);
1194 assert(mal_success == satisfiable);
1215 for (
const auto script_ctx: {MsCtx::P2WSH, MsCtx::TAPSCRIPT}) {
1217 TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
1218 return ConsumeNodeStable(script_ctx, provider, needed_type);
1219 },
""_mst), provider);
1227 static constexpr std::array<Type, 4> BASE_TYPES{
"B"_mst,
"V"_mst,
"K"_mst,
"W"_mst};
1230 const auto script_ctx{(MsCtx)provider.
ConsumeBool()};
1231 TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
1232 return ConsumeNodeSmart(script_ctx, provider, needed_type);
1233 },
PickValue(provider, BASE_TYPES),
true), provider);
1239 if (buffer.empty())
return;
1242 const ParserContext parser_ctx{(MsCtx)provider.
ConsumeBool()};
1244 if (!parsed)
return;
1246 const auto str2 = parsed->ToString(parser_ctx);
1250 assert(*parsed == *parsed2);
1257 const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
1258 if (!script)
return;
1260 const ScriptParserContext script_parser_ctx{(MsCtx)fuzzed_data_provider.
ConsumeBool()};
1264 assert(ms->ToScript(script_parser_ctx) == *script);
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
virtual bool CheckLockTime(const CScriptNum &nLockTime) const
virtual bool CheckSchnorrSignature(Span< const unsigned char > sig, Span< const unsigned char > pubkey, SigVersion sigversion, ScriptExecutionData &execdata, ScriptError *serror=nullptr) const
virtual bool CheckSequence(const CScriptNum &nSequence) const
virtual bool CheckECDSASignature(const std::vector< unsigned char > &scriptSig, const std::vector< unsigned char > &vchPubKey, const CScript &scriptCode, SigVersion sigversion) const
A hasher class for Bitcoin's 160-bit hash (SHA-256 + RIPEMD-160).
void Finalize(Span< unsigned char > output)
CHash160 & Write(Span< const unsigned char > input)
A hasher class for Bitcoin's 256-bit hash (double SHA-256).
CHash256 & Write(Span< const unsigned char > input)
void Finalize(Span< unsigned char > output)
An encapsulated private key.
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...
bool Sign(const uint256 &hash, std::vector< unsigned char > &vchSig, bool grind=true, uint32_t test_case=0) const
Create a DER-serialized signature.
CPubKey GetPubKey() const
Compute the public key from a private key.
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
A reference to a CKey: the Hash160 of its serialized public key.
An encapsulated public key.
A hasher class for RIPEMD-160.
CRIPEMD160 & Write(const unsigned char *data, size_t len)
void Finalize(unsigned char hash[OUTPUT_SIZE])
A hasher class for SHA-256.
void Finalize(unsigned char hash[OUTPUT_SIZE])
CSHA256 & Write(const unsigned char *data, size_t len)
Serialized script, used inside transaction inputs and outputs.
RAII class initializing and deinitializing global state for elliptic curve support.
std::string ConsumeBytesAsString(size_t num_bytes)
T ConsumeIntegralInRange(T min, T max)
A Span is an object that can refer to a contiguous sequence of objects.
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
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
CPubKey GetEvenCorrespondingCPubKey() const
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...
static constexpr unsigned int size()
constexpr unsigned char * begin()
This type encapsulates the miniscript type system properties.
void reserve(size_type new_capacity)
void push_back(const T &value)
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
uint160 RIPEMD160(Span< const unsigned char > data)
Compute the 160-bit RIPEMD-160 hash of an array.
#define T(expected, seed, data)
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CScriptWitness *witness, unsigned int flags, const BaseSignatureChecker &checker, ScriptError *serror)
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT
size_t ComputeScriptLen(Fragment fragment, Type sub0typ, size_t subsize, uint32_t k, size_t n_subs, size_t n_keys, MiniscriptContext ms_ctx)
Helper function for Node::CalcScriptLen.
constexpr uint32_t MaxScriptSize(MiniscriptContext ms_ctx)
The maximum size of a script depending on the context.
Type ComputeType(Fragment fragment, Type x, Type y, Type z, const std::vector< Type > &sub_types, uint32_t k, size_t data_size, size_t n_subs, size_t n_keys, MiniscriptContext ms_ctx)
Helper function for Node::CalcType.
std::shared_ptr< const Node< Key > > NodeRef
constexpr bool IsTapscript(MiniscriptContext ms_ctx)
Whether the context Tapscript, ensuring the only other possibility is P2WSH.
NodeRef< Key > MakeNodeRef(Args &&... args)
Construct a miniscript node as a shared_ptr.
NodeRef< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
Fragment
The different node types in miniscript.
Internal RIPEMD-160 implementation.
Internal SHA-256 implementation.
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS
Standard script verification flags that standard transactions will comply with.
static constexpr unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE
The maximum size in bytes of a standard witnessScript.
static const int MAX_STACK_SIZE
static const int MAX_OPS_PER_SCRIPT
enum ScriptError_t ScriptError
size_t GetSerializeSize(const T &t)
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...
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
std::vector< std::vector< unsigned char > > stack
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.
FUZZ_TARGET(miniscript_stable,.init=FuzzInit)
Fuzz target that runs TestNode on nodes generated using ConsumeNodeStable.
auto ConsumeNode(FuzzedDataProvider &fuzzed_data_provider, const std::optional< NodeId > &node_id_in=std::nullopt) noexcept
auto & PickValue(FuzzedDataProvider &fuzzed_data_provider, Collection &col)
bilingual_str _(const char *psz)
Translation function.
uint256 uint256S(const char *str)
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.