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 {
313 const std::vector<unsigned char> NUMS_PK{
ParseHex(
"50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0")};
327 std::vector<CPubKey> keys;
329 std::vector<unsigned char> hash;
331 std::vector<Type> subtypes;
333 NodeInfo(
Fragment frag): fragment(frag),
k(0) {}
335 NodeInfo(
Fragment frag, uint32_t _k): fragment(frag),
k(_k) {}
336 NodeInfo(
Fragment frag, std::vector<unsigned char> h): fragment(frag),
k(0), hash(
std::move(h)) {}
337 NodeInfo(std::vector<Type> subt,
Fragment frag): fragment(frag),
k(0), subtypes(
std::move(subt)) {}
338 NodeInfo(std::vector<Type> subt,
Fragment frag, uint32_t _k): fragment(frag),
k(_k), subtypes(
std::move(subt)) {}
339 NodeInfo(
Fragment frag, uint32_t _k, std::vector<CPubKey> _keys): fragment(frag),
k(_k), keys(
std::move(_keys)) {}
343 template<
typename T,
typename A>
350 return ConsumeIndex<CPubKey>(provider, TEST_DATA.dummy_keys);
354 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.sha256);
358 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.hash256);
362 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.ripemd160);
366 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.hash160);
371 if (k == 0 || k >= 0x80000000)
return {};
389 std::optional<NodeInfo> ConsumeNodeStable(MsCtx script_ctx,
FuzzedDataProvider& provider, Type type_needed) {
390 bool allow_B = (type_needed ==
""_mst) || (type_needed <<
"B"_mst);
391 bool allow_K = (type_needed ==
""_mst) || (type_needed <<
"K"_mst);
392 bool allow_V = (type_needed ==
""_mst) || (type_needed <<
"V"_mst);
393 bool allow_W = (type_needed ==
""_mst) || (type_needed <<
"W"_mst);
397 if (!allow_B)
return {};
398 return {{Fragment::JUST_0}};
400 if (!allow_B)
return {};
401 return {{Fragment::JUST_1}};
403 if (!allow_K)
return {};
404 return {{Fragment::PK_K, ConsumePubKey(provider)}};
406 if (!allow_K)
return {};
407 return {{Fragment::PK_H, ConsumePubKey(provider)}};
409 if (!allow_B)
return {};
410 const auto k = ConsumeTimeLock(provider);
412 return {{Fragment::OLDER, *
k}};
415 if (!allow_B)
return {};
416 const auto k = ConsumeTimeLock(provider);
418 return {{Fragment::AFTER, *
k}};
421 if (!allow_B)
return {};
422 return {{Fragment::SHA256, ConsumeSha256(provider)}};
424 if (!allow_B)
return {};
425 return {{Fragment::HASH256, ConsumeHash256(provider)}};
427 if (!allow_B)
return {};
430 if (!allow_B)
return {};
431 return {{Fragment::HASH160, ConsumeHash160(provider)}};
433 if (!allow_B ||
IsTapscript(script_ctx))
return {};
436 if (n_keys > 20 || k == 0 || k > n_keys)
return {};
437 std::vector<CPubKey> keys{n_keys};
438 for (
auto& key: keys) key = ConsumePubKey(provider);
439 return {{Fragment::MULTI,
k, std::move(keys)}};
442 if (!(allow_B || allow_K || allow_V))
return {};
443 return {{{
"B"_mst, type_needed, type_needed}, Fragment::ANDOR}};
445 if (!(allow_B || allow_K || allow_V))
return {};
446 return {{{
"V"_mst, type_needed}, Fragment::AND_V}};
448 if (!allow_B)
return {};
449 return {{{
"B"_mst,
"W"_mst}, Fragment::AND_B}};
451 if (!allow_B)
return {};
452 return {{{
"B"_mst,
"W"_mst}, Fragment::OR_B}};
454 if (!allow_V)
return {};
455 return {{{
"B"_mst,
"V"_mst}, Fragment::OR_C}};
457 if (!allow_B)
return {};
458 return {{{
"B"_mst,
"B"_mst}, Fragment::OR_D}};
460 if (!(allow_B || allow_K || allow_V))
return {};
461 return {{{type_needed, type_needed}, Fragment::OR_I}};
463 if (!allow_B)
return {};
466 if (k == 0 || k > n_subs)
return {};
467 std::vector<Type> subtypes;
468 subtypes.reserve(n_subs);
469 subtypes.emplace_back(
"B"_mst);
470 for (
size_t i = 1; i < n_subs; ++i) subtypes.emplace_back(
"W"_mst);
471 return {{std::move(subtypes), Fragment::THRESH,
k}};
474 if (!allow_W)
return {};
475 return {{{
"B"_mst}, Fragment::WRAP_A}};
477 if (!allow_W)
return {};
478 return {{{
"B"_mst}, Fragment::WRAP_S}};
480 if (!allow_B)
return {};
481 return {{{
"K"_mst}, Fragment::WRAP_C}};
483 if (!allow_B)
return {};
484 return {{{
"V"_mst}, Fragment::WRAP_D}};
486 if (!allow_V)
return {};
487 return {{{
"B"_mst}, Fragment::WRAP_V}};
489 if (!allow_B)
return {};
490 return {{{
"B"_mst}, Fragment::WRAP_J}};
492 if (!allow_B)
return {};
493 return {{{
"B"_mst}, Fragment::WRAP_N}};
495 if (!allow_B || !
IsTapscript(script_ctx))
return {};
498 if (n_keys > 999 || k == 0 || k > n_keys)
return {};
499 std::vector<CPubKey> keys{n_keys};
500 for (
auto& key: keys) key = ConsumePubKey(provider);
501 return {{Fragment::MULTI_A,
k, std::move(keys)}};
518 using recipe = std::pair<Fragment, std::vector<Type>>;
519 std::map<Type, std::vector<recipe>> wsh_table, tap_table;
523 Init(wsh_table, MsCtx::P2WSH);
524 Init(tap_table, MsCtx::TAPSCRIPT);
527 void Init(std::map<Type, std::vector<recipe>>& table, MsCtx script_ctx)
530 std::vector<Type> types;
531 for (
int base = 0; base < 4; ++base) {
532 Type type_base = base == 0 ?
"B"_mst : base == 1 ?
"K"_mst : base == 2 ?
"V"_mst :
"W"_mst;
533 for (
int zo = 0; zo < 3; ++zo) {
534 Type type_zo = zo == 0 ?
"z"_mst : zo == 1 ?
"o"_mst :
""_mst;
535 for (
int n = 0; n < 2; ++n) {
536 if (zo == 0 && n == 1)
continue;
537 if (base == 3 && n == 1)
continue;
538 Type type_n = n == 0 ?
""_mst :
"n"_mst;
539 for (
int d = 0; d < 2; ++d) {
540 if (base == 2 && d == 1)
continue;
541 Type type_d = d == 0 ?
""_mst :
"d"_mst;
542 for (
int u = 0; u < 2; ++u) {
543 if (base == 2 && u == 1)
continue;
544 Type type_u = u == 0 ?
""_mst :
"u"_mst;
545 Type type = type_base | type_zo | type_n | type_d | type_u;
546 types.push_back(type);
559 auto is_super_of = [](
const recipe& a,
const recipe& b) {
560 if (a.first != b.first)
return false;
561 if (a.second.size() != b.second.size())
return false;
562 for (
size_t i = 0; i < a.second.size(); ++i) {
563 if (!(b.second[i] << a.second[i]))
return false;
573 std::sort(types.begin(), types.end());
576 for (
int fragidx = 0; fragidx <= int(Fragment::MULTI_A); ++fragidx) {
579 size_t data_size = 0;
596 case Fragment::MULTI:
597 case Fragment::MULTI_A:
601 case Fragment::OLDER:
602 case Fragment::AFTER:
605 case Fragment::SHA256:
606 case Fragment::HASH256:
610 case Fragment::HASH160:
613 case Fragment::JUST_0:
614 case Fragment::JUST_1:
616 case Fragment::WRAP_A:
617 case Fragment::WRAP_S:
618 case Fragment::WRAP_C:
619 case Fragment::WRAP_D:
620 case Fragment::WRAP_V:
621 case Fragment::WRAP_J:
622 case Fragment::WRAP_N:
625 case Fragment::AND_V:
626 case Fragment::AND_B:
633 case Fragment::ANDOR:
636 case Fragment::THRESH:
645 std::vector<Type> subt;
646 for (
int subs = sub_count; subs < sub_count + sub_range; ++subs) {
648 for (Type x : types) {
649 for (Type y : types) {
650 for (Type z : types) {
653 if (subs > 0) subt.push_back(x);
654 if (subs > 1) subt.push_back(y);
655 if (subs > 2) subt.push_back(z);
658 if ((res <<
"K"_mst) + (res <<
"V"_mst) + (res <<
"B"_mst) + (res <<
"W"_mst) != 1)
continue;
660 recipe entry{frag, subt};
661 auto super_of_entry = [&](
const recipe& rec) {
return is_super_of(rec, entry); };
664 for (Type s : types) {
665 if ((res &
"BKVWzondu"_mst) << s) {
666 auto& recipes = table[s];
668 if (!std::any_of(recipes.begin(), recipes.end(), super_of_entry)) {
669 recipes.push_back(entry);
674 if (subs <= 2)
break;
676 if (subs <= 1)
break;
678 if (subs <= 0)
break;
686 std::set<Type> useful_types{
"B"_mst,
"V"_mst,
"K"_mst,
"W"_mst};
689 size_t set_size = useful_types.size();
690 for (
const auto& [type, recipes] : table) {
691 if (useful_types.count(type) != 0) {
692 for (
const auto& [
_, subtypes] : recipes) {
693 for (
auto subtype : subtypes) useful_types.insert(subtype);
697 if (useful_types.size() == set_size)
break;
700 for (
auto type_it = table.begin(); type_it != table.end();) {
701 if (useful_types.count(type_it->first) == 0) {
702 type_it = table.erase(type_it);
713 std::set<Type> constructible_types{};
714 auto known_constructible = [&](Type type) {
return constructible_types.count(type) != 0; };
717 size_t set_size = constructible_types.size();
719 for (
const auto& [type, recipes] : table) {
720 if (!known_constructible(type)) {
722 for (
const auto& [
_, subt] : recipes) {
725 if (std::all_of(subt.begin(), subt.end(), known_constructible)) {
726 constructible_types.insert(type);
732 if (constructible_types.size() == set_size)
break;
734 for (
auto type_it = table.begin(); type_it != table.end();) {
736 type_it->second.erase(std::remove_if(type_it->second.begin(), type_it->second.end(),
737 [&](
const recipe& rec) {
738 return !std::all_of(rec.second.begin(), rec.second.end(), known_constructible);
739 }), type_it->second.end());
741 if (type_it->second.empty()) {
742 type_it = table.erase(type_it);
748 for (
auto& [type, recipes] : table) {
752 std::sort(recipes.begin(), recipes.end(),
753 [](
const recipe& a,
const recipe& b) {
754 if (a.second.size() < b.second.size()) return true;
755 if (a.second.size() > b.second.size()) return false;
773 std::optional<NodeInfo> ConsumeNodeSmart(MsCtx script_ctx,
FuzzedDataProvider& provider, Type type_needed) {
775 const auto& table{
IsTapscript(script_ctx) ? SMARTINFO.tap_table : SMARTINFO.wsh_table};
776 auto recipes_it = table.find(type_needed);
777 assert(recipes_it != table.end());
779 const auto& [frag, subt] =
PickValue(provider, recipes_it->second);
785 return {{frag, ConsumePubKey(provider)}};
786 case Fragment::MULTI: {
789 std::vector<CPubKey> keys{n_keys};
790 for (
auto& key: keys) key = ConsumePubKey(provider);
791 return {{frag,
k, std::move(keys)}};
793 case Fragment::MULTI_A: {
796 std::vector<CPubKey> keys{n_keys};
797 for (
auto& key: keys) key = ConsumePubKey(provider);
798 return {{frag,
k, std::move(keys)}};
800 case Fragment::OLDER:
801 case Fragment::AFTER:
803 case Fragment::SHA256:
804 return {{frag,
PickValue(provider, TEST_DATA.sha256)}};
805 case Fragment::HASH256:
806 return {{frag,
PickValue(provider, TEST_DATA.hash256)}};
808 return {{frag,
PickValue(provider, TEST_DATA.ripemd160)}};
809 case Fragment::HASH160:
810 return {{frag,
PickValue(provider, TEST_DATA.hash160)}};
811 case Fragment::JUST_0:
812 case Fragment::JUST_1:
813 case Fragment::WRAP_A:
814 case Fragment::WRAP_S:
815 case Fragment::WRAP_C:
816 case Fragment::WRAP_D:
817 case Fragment::WRAP_V:
818 case Fragment::WRAP_J:
819 case Fragment::WRAP_N:
820 case Fragment::AND_V:
821 case Fragment::AND_B:
826 case Fragment::ANDOR:
827 return {{subt, frag}};
828 case Fragment::THRESH: {
830 if (subt.size() < 2) {
831 children = subt.size();
838 std::vector<Type> subs = subt;
839 while (subs.size() < children) subs.push_back(subs.back());
840 return {{std::move(subs), frag,
k}};
856 NodeRef GenNode(MsCtx script_ctx, F
ConsumeNode, Type root_type,
bool strict_valid =
false) {
858 std::vector<NodeRef> stack;
860 std::vector<std::pair<Type, std::optional<NodeInfo>>> todo{{root_type, {}}};
865 uint32_t scriptsize{1};
867 while (!todo.empty()) {
869 auto type_needed = todo.back().first;
870 if (!todo.back().second) {
873 if (!node_info)
return {};
878 node_info->keys.size(), script_ctx) - 1;
880 switch (node_info->fragment) {
881 case Fragment::JUST_0:
882 case Fragment::JUST_1:
889 case Fragment::OLDER:
890 case Fragment::AFTER:
894 case Fragment::SHA256:
895 case Fragment::HASH160:
896 case Fragment::HASH256:
899 case Fragment::ANDOR:
902 case Fragment::AND_V:
904 case Fragment::AND_B:
917 case Fragment::THRESH:
918 ops += node_info->subtypes.
size();
920 case Fragment::MULTI:
923 case Fragment::MULTI_A:
924 ops += node_info->keys.size() + 1;
926 case Fragment::WRAP_A:
929 case Fragment::WRAP_S:
932 case Fragment::WRAP_C:
935 case Fragment::WRAP_D:
938 case Fragment::WRAP_V:
942 case Fragment::WRAP_J:
945 case Fragment::WRAP_N:
950 auto subtypes = node_info->subtypes;
951 todo.back().second = std::move(node_info);
952 todo.reserve(todo.size() + subtypes.size());
955 for (
size_t i = 0; i < subtypes.size(); ++i) {
956 todo.emplace_back(*(subtypes.rbegin() + i), std::nullopt);
963 NodeInfo& info = *todo.back().second;
965 std::vector<NodeRef> sub;
966 sub.reserve(info.subtypes.size());
967 for (
size_t i = 0; i < info.subtypes.size(); ++i) {
968 sub.push_back(std::move(*(stack.end() - info.subtypes.size() + i)));
970 stack.erase(stack.end() - info.subtypes.size(), stack.end());
973 if (info.keys.empty()) {
974 node =
MakeNodeRef(script_ctx, info.fragment, std::move(sub), std::move(info.hash), info.k);
977 assert(info.hash.empty());
978 node =
MakeNodeRef(script_ctx, info.fragment, std::move(info.keys), info.k);
981 if (!
node || (
node->GetType() &
"KVWB"_mst) ==
""_mst) {
985 if (!(type_needed ==
""_mst)) {
988 if (!
node->IsValid())
return {};
990 if (
node->fragment == Fragment::WRAP_V &&
node->subs[0]->GetType() <<
"x"_mst) {
999 stack.push_back(std::move(
node));
1003 assert(stack.size() == 1);
1004 assert(stack[0]->GetStaticOps() == ops);
1005 assert(stack[0]->ScriptSize() == scriptsize);
1006 stack[0]->DuplicateKeyCheck(KEY_COMP);
1007 return std::move(stack[0]);
1036 const ParserContext parser_ctx{script_ctx};
1037 std::optional<std::string> str{
node->ToString(parser_ctx)};
1044 auto script =
node->ToScript(parser_ctx);
1049 if (!(
node->GetType() <<
"K"_mst)) {
1050 bool ends_in_verify = !(
node->GetType() <<
"x"_mst);
1055 if (!
node->IsValidTopLevel())
return;
1063 assert(decoded->ToScript(parser_ctx) == script);
1064 assert(decoded->GetType() ==
node->GetType());
1079 const auto node_ops{
node->GetOps()};
1082 int add = std::min<int>(
1090 const auto node_exec_ss{
node->GetExecStackSize()};
1093 witness_mal.
stack.resize(add);
1094 witness_nonmal.
stack.resize(add);
1100 const SatisfierContext satisfier_ctx{script_ctx};
1104 const CScript script_pubkey{ScriptPubKey(script_ctx, script, builder)};
1107 std::vector<std::vector<unsigned char>> stack_mal;
1111 std::vector<std::vector<unsigned char>> stack_nonmal;
1114 if (nonmal_success) {
1119 assert(stack_nonmal.size() <= max_stack_size);
1122 assert(stack_nonmal == stack_mal);
1125 assert(wit_size <= *node->GetWitnessSize());
1128 witness_nonmal.
stack.insert(witness_nonmal.
stack.end(), std::make_move_iterator(stack_nonmal.begin()), std::make_move_iterator(stack_nonmal.end()));
1129 SatisfactionToWitness(script_ctx, witness_nonmal, script, builder);
1141 if (mal_success && (!nonmal_success || witness_mal.
stack != witness_nonmal.
stack)) {
1143 witness_mal.
stack.insert(witness_mal.
stack.end(), std::make_move_iterator(stack_mal.begin()), std::make_move_iterator(stack_mal.end()));
1144 SatisfactionToWitness(script_ctx, witness_mal, script, builder);
1152 if (
node->IsSane()) {
1154 assert(mal_success == nonmal_success);
1161 const auto is_key_satisfiable = [script_ctx](
const CPubKey& pubkey) ->
bool {
1162 auto sig_ptr{TEST_DATA.GetSig(script_ctx, pubkey)};
1163 return sig_ptr !=
nullptr && sig_ptr->second;
1165 bool satisfiable =
node->IsSatisfiable([&](
const Node&
node) ->
bool {
1166 switch (
node.fragment) {
1167 case Fragment::PK_K:
1168 case Fragment::PK_H:
1169 return is_key_satisfiable(
node.keys[0]);
1170 case Fragment::MULTI:
1171 case Fragment::MULTI_A: {
1172 size_t sats = std::count_if(
node.keys.begin(),
node.keys.end(), [&](
const auto& key) {
1173 return size_t(is_key_satisfiable(key));
1175 return sats >=
node.k;
1177 case Fragment::OLDER:
1178 case Fragment::AFTER:
1180 case Fragment::SHA256:
1181 return TEST_DATA.sha256_preimages.count(
node.data);
1182 case Fragment::HASH256:
1183 return TEST_DATA.hash256_preimages.count(
node.data);
1185 return TEST_DATA.ripemd160_preimages.count(
node.data);
1186 case Fragment::HASH160:
1187 return TEST_DATA.hash160_preimages.count(
node.data);
1193 assert(mal_success == satisfiable);
1214 for (
const auto script_ctx: {MsCtx::P2WSH, MsCtx::TAPSCRIPT}) {
1216 TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
1217 return ConsumeNodeStable(script_ctx, provider, needed_type);
1218 },
""_mst), provider);
1226 static constexpr std::array<Type, 4> BASE_TYPES{
"B"_mst,
"V"_mst,
"K"_mst,
"W"_mst};
1229 const auto script_ctx{(MsCtx)provider.
ConsumeBool()};
1230 TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
1231 return ConsumeNodeSmart(script_ctx, provider, needed_type);
1232 },
PickValue(provider, BASE_TYPES),
true), provider);
1238 if (buffer.empty())
return;
1241 const ParserContext parser_ctx{(MsCtx)provider.
ConsumeBool()};
1243 if (!parsed)
return;
1245 const auto str2 = parsed->ToString(parser_ctx);
1249 assert(*parsed == *parsed2);
1256 const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
1257 if (!script)
return;
1259 const ScriptParserContext script_parser_ctx{(MsCtx)fuzzed_data_provider.
ConsumeBool()};
1263 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.
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 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.