25using miniscript::operator
""_mst;
32 std::vector<Key> dummy_keys;
33 std::map<Key, int> dummy_key_idx_map;
34 std::map<CKeyID, Key> dummy_keys_map;
35 std::map<Key, std::pair<std::vector<unsigned char>,
bool>> dummy_sigs;
36 std::map<XOnlyPubKey, std::pair<std::vector<unsigned char>,
bool>> schnorr_sigs;
39 std::vector<std::vector<unsigned char>>
sha256;
40 std::vector<std::vector<unsigned char>>
ripemd160;
41 std::vector<std::vector<unsigned char>> hash256;
42 std::vector<std::vector<unsigned char>> hash160;
43 std::map<std::vector<unsigned char>, std::vector<unsigned char>> sha256_preimages;
44 std::map<std::vector<unsigned char>, std::vector<unsigned char>> ripemd160_preimages;
45 std::map<std::vector<unsigned char>, std::vector<unsigned char>> hash256_preimages;
46 std::map<std::vector<unsigned char>, std::vector<unsigned char>> hash160_preimages;
50 unsigned char keydata[32] = {1};
52 constexpr uint256 MESSAGE_HASH{
"0000000000000000f5cd94e18b6fe77dd7aca9e35c2b0c9cbd86356c80a71065"};
56 for (
size_t i = 0; i < 256; i++) {
59 privkey.
Set(keydata, keydata + 32,
true);
62 dummy_keys.push_back(pubkey);
63 dummy_key_idx_map.emplace(pubkey, i);
64 dummy_keys_map.insert({pubkey.GetID(), pubkey});
66 dummy_key_idx_map.emplace(xonly_pubkey, i);
68 dummy_keys_map.emplace(xonly_hash, pubkey);
70 std::vector<unsigned char> sig, schnorr_sig(64);
71 privkey.
Sign(MESSAGE_HASH, sig);
73 dummy_sigs.insert({pubkey, {sig, i & 1}});
75 schnorr_sig.push_back(1);
76 schnorr_sigs.emplace(
XOnlyPubKey{pubkey}, std::make_pair(std::move(schnorr_sig), i & 1));
78 std::vector<unsigned char> hash;
82 if (i & 1) sha256_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
84 hash256.push_back(hash);
85 if (i & 1) hash256_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
90 if (i & 1) ripemd160_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
92 hash160.push_back(hash);
93 if (i & 1) hash160_preimages[hash] = std::vector<unsigned char>(keydata, keydata + 32);
98 const std::pair<std::vector<unsigned char>,
bool>* GetSig(
const MsCtx script_ctx,
const Key& key)
const {
100 const auto it = dummy_sigs.find(key);
101 if (it == dummy_sigs.end())
return nullptr;
104 const auto it = schnorr_sigs.find(
XOnlyPubKey{key});
105 if (it == schnorr_sigs.end())
return nullptr;
116struct ParserContext {
119 const MsCtx script_ctx;
121 constexpr ParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
123 bool KeyCompare(
const Key& a,
const Key& b)
const {
127 std::optional<std::string>
ToString(
const Key& key)
const
129 auto it = TEST_DATA.dummy_key_idx_map.find(key);
130 if (it == TEST_DATA.dummy_key_idx_map.end())
return {};
131 uint8_t idx = it->second;
135 std::vector<unsigned char> ToPKBytes(
const Key& key)
const {
137 return {key.begin(), key.end()};
140 return {xonly_pubkey.
begin(), xonly_pubkey.end()};
143 std::vector<unsigned char> ToPKHBytes(
const Key& key)
const {
146 return {h.begin(), h.end()};
149 return {h.
begin(), h.end()};
153 std::optional<Key>
FromString(I first, I last)
const {
154 if (last - first != 2)
return {};
155 auto idx =
ParseHex(std::string(first, last));
156 if (idx.size() != 1)
return {};
157 return TEST_DATA.dummy_keys[idx[0]];
161 std::optional<Key> FromPKBytes(I first, I last)
const {
163 Key key{first, last};
164 if (key.IsValid())
return key;
167 if (last - first != 32)
return {};
169 std::copy(first, last, xonly_pubkey.
begin());
174 std::optional<Key> FromPKHBytes(I first, I last)
const {
175 assert(last - first == 20);
177 std::copy(first, last, keyid.
begin());
178 const auto it = TEST_DATA.dummy_keys_map.find(keyid);
179 if (it == TEST_DATA.dummy_keys_map.end())
return {};
183 MsCtx MsContext()
const {
189struct ScriptParserContext {
190 const MsCtx script_ctx;
192 constexpr ScriptParserContext(MsCtx ctx) noexcept : script_ctx(ctx) {}
197 std::vector<unsigned char>
data;
200 bool KeyCompare(
const Key& a,
const Key& b)
const {
201 return a.data < b.data;
204 const std::vector<unsigned char>& ToPKBytes(
const Key& key)
const
210 std::vector<unsigned char> ToPKHBytes(
const Key& key)
const
212 if (key.is_hash)
return key.data;
213 const auto h =
Hash160(key.data);
214 return {h.begin(), h.end()};
218 std::optional<Key> FromPKBytes(I first, I last)
const
221 key.data.assign(first, last);
227 std::optional<Key> FromPKHBytes(I first, I last)
const
230 key.data.assign(first, last);
235 MsCtx MsContext()
const {
241struct SatisfierContext : ParserContext {
243 constexpr SatisfierContext(MsCtx ctx) noexcept : ParserContext(ctx) {}
247 bool CheckAfter(uint32_t value)
const {
return value % 2; }
248 bool CheckOlder(uint32_t value)
const {
return value % 2; }
252 bool sig_available{
false};
253 if (
auto res = TEST_DATA.GetSig(script_ctx, key)) {
254 std::tie(sig, sig_available) = *res;
261 const std::map<std::vector<unsigned char>, std::vector<unsigned char>>& map)
const
263 const auto it = map.find(hash);
265 preimage = it->second;
268 miniscript::Availability SatSHA256(
const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage)
const {
269 return LookupHash(hash, preimage, TEST_DATA.sha256_preimages);
271 miniscript::Availability SatRIPEMD160(
const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage)
const {
272 return LookupHash(hash, preimage, TEST_DATA.ripemd160_preimages);
274 miniscript::Availability SatHASH256(
const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage)
const {
275 return LookupHash(hash, preimage, TEST_DATA.hash256_preimages);
277 miniscript::Availability SatHASH160(
const std::vector<unsigned char>& hash, std::vector<unsigned char>& preimage)
const {
278 return LookupHash(hash, preimage, TEST_DATA.hash160_preimages);
285 bool CheckECDSASignature(
const std::vector<unsigned char>& sig,
const std::vector<unsigned char>& vchPubKey,
289 const auto it = TEST_DATA.dummy_sigs.find(key);
290 if (it == TEST_DATA.dummy_sigs.end())
return false;
291 return it->second.first == sig;
296 auto it = TEST_DATA.schnorr_sigs.find(
pk);
297 if (it == TEST_DATA.schnorr_sigs.end())
return false;
298 return std::ranges::equal(it->second.first, sig);
305const struct KeyComparator {
326 std::vector<CPubKey> keys;
328 std::vector<unsigned char> hash;
330 std::vector<Type> subtypes;
332 NodeInfo(
Fragment frag): fragment(frag),
k(0) {}
334 NodeInfo(
Fragment frag, uint32_t _k): fragment(frag),
k(_k) {}
335 NodeInfo(
Fragment frag, std::vector<unsigned char> h): fragment(frag),
k(0), hash(
std::move(h)) {}
336 NodeInfo(std::vector<Type> subt,
Fragment frag): fragment(frag),
k(0), subtypes(
std::move(subt)) {}
337 NodeInfo(std::vector<Type> subt,
Fragment frag, uint32_t _k): fragment(frag),
k(_k), subtypes(
std::move(subt)) {}
338 NodeInfo(
Fragment frag, uint32_t _k, std::vector<CPubKey> _keys): fragment(frag),
k(_k), keys(
std::move(_keys)) {}
342template<
typename T,
typename A>
349 return ConsumeIndex<CPubKey>(provider, TEST_DATA.dummy_keys);
353 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.sha256);
357 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.hash256);
361 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.ripemd160);
365 return ConsumeIndex<std::vector<unsigned char>>(provider, TEST_DATA.hash160);
370 if (k == 0 || k >= 0x80000000)
return {};
388std::optional<NodeInfo> ConsumeNodeStable(MsCtx script_ctx,
FuzzedDataProvider& provider, Type type_needed) {
389 bool allow_B = (type_needed ==
""_mst) || (type_needed <<
"B"_mst);
390 bool allow_K = (type_needed ==
""_mst) || (type_needed <<
"K"_mst);
391 bool allow_V = (type_needed ==
""_mst) || (type_needed <<
"V"_mst);
392 bool allow_W = (type_needed ==
""_mst) || (type_needed <<
"W"_mst);
393 static constexpr auto B{
"B"_mst},
K{
"K"_mst}, V{
"V"_mst}, W{
"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, type_needed, type_needed}, Fragment::ANDOR}};
445 if (!(allow_B || allow_K || allow_V))
return {};
446 return {{{V, type_needed}, Fragment::AND_V}};
448 if (!allow_B)
return {};
449 return {{{
B, W}, Fragment::AND_B}};
451 if (!allow_B)
return {};
452 return {{{
B, W}, Fragment::OR_B}};
454 if (!allow_V)
return {};
455 return {{{
B, V}, Fragment::OR_C}};
457 if (!allow_B)
return {};
458 return {{{
B,
B}, 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}, Fragment::WRAP_A}};
477 if (!allow_W)
return {};
478 return {{{
B}, Fragment::WRAP_S}};
480 if (!allow_B)
return {};
481 return {{{
K}, Fragment::WRAP_C}};
483 if (!allow_B)
return {};
484 return {{{V}, Fragment::WRAP_D}};
486 if (!allow_V)
return {};
487 return {{{
B}, Fragment::WRAP_V}};
489 if (!allow_B)
return {};
490 return {{{
B}, Fragment::WRAP_J}};
492 if (!allow_B)
return {};
493 return {{{
B}, 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 static constexpr auto B_mst{
"B"_mst}, K_mst{
"K"_mst}, V_mst{
"V"_mst}, W_mst{
"W"_mst};
532 static constexpr auto d_mst{
"d"_mst}, n_mst{
"n"_mst}, o_mst{
"o"_mst}, u_mst{
"u"_mst}, z_mst{
"z"_mst};
533 static constexpr auto NONE_mst{
""_mst};
534 for (
int base = 0; base < 4; ++base) {
535 Type type_base = base == 0 ? B_mst : base == 1 ? K_mst : base == 2 ? V_mst : W_mst;
536 for (
int zo = 0; zo < 3; ++zo) {
537 Type type_zo = zo == 0 ? z_mst : zo == 1 ? o_mst : NONE_mst;
538 for (
int n = 0; n < 2; ++n) {
539 if (zo == 0 && n == 1)
continue;
540 if (base == 3 && n == 1)
continue;
541 Type type_n = n == 0 ? NONE_mst : n_mst;
542 for (
int d = 0; d < 2; ++d) {
543 if (base == 2 && d == 1)
continue;
544 Type type_d = d == 0 ? NONE_mst : d_mst;
545 for (
int u = 0; u < 2; ++u) {
546 if (base == 2 && u == 1)
continue;
547 Type type_u = u == 0 ? NONE_mst : u_mst;
548 Type type = type_base | type_zo | type_n | type_d | type_u;
549 types.push_back(type);
562 auto is_super_of = [](
const recipe& a,
const recipe& b) {
563 if (a.first != b.first)
return false;
564 if (a.second.size() != b.second.size())
return false;
565 for (
size_t i = 0; i < a.second.size(); ++i) {
566 if (!(b.second[i] << a.second[i]))
return false;
576 std::sort(types.begin(), types.end());
579 for (
int fragidx = 0; fragidx <= int(Fragment::MULTI_A); ++fragidx) {
582 size_t data_size = 0;
599 case Fragment::MULTI:
600 case Fragment::MULTI_A:
604 case Fragment::OLDER:
605 case Fragment::AFTER:
608 case Fragment::SHA256:
609 case Fragment::HASH256:
613 case Fragment::HASH160:
616 case Fragment::JUST_0:
617 case Fragment::JUST_1:
619 case Fragment::WRAP_A:
620 case Fragment::WRAP_S:
621 case Fragment::WRAP_C:
622 case Fragment::WRAP_D:
623 case Fragment::WRAP_V:
624 case Fragment::WRAP_J:
625 case Fragment::WRAP_N:
628 case Fragment::AND_V:
629 case Fragment::AND_B:
636 case Fragment::ANDOR:
639 case Fragment::THRESH:
648 std::vector<Type> subt;
649 for (
int subs = sub_count; subs < sub_count + sub_range; ++subs) {
651 for (Type x : types) {
652 for (Type y : types) {
653 for (Type z : types) {
656 if (subs > 0) subt.push_back(x);
657 if (subs > 1) subt.push_back(y);
658 if (subs > 2) subt.push_back(z);
661 if ((res <<
"K"_mst) + (res <<
"V"_mst) + (res <<
"B"_mst) + (res <<
"W"_mst) != 1)
continue;
663 recipe entry{frag, subt};
664 auto super_of_entry = [&](
const recipe& rec) {
return is_super_of(rec, entry); };
667 for (Type
s : types) {
668 if ((res &
"BKVWzondu"_mst) <<
s) {
669 auto& recipes = table[
s];
671 if (!std::any_of(recipes.begin(), recipes.end(), super_of_entry)) {
672 recipes.push_back(entry);
677 if (subs <= 2)
break;
679 if (subs <= 1)
break;
681 if (subs <= 0)
break;
689 std::set<Type> useful_types{B_mst, V_mst, K_mst, W_mst};
692 size_t set_size = useful_types.size();
693 for (
const auto& [type, recipes] : table) {
694 if (useful_types.count(type) != 0) {
695 for (
const auto& [
_, subtypes] : recipes) {
696 for (
auto subtype : subtypes) useful_types.insert(subtype);
700 if (useful_types.size() == set_size)
break;
703 for (
auto type_it = table.begin(); type_it != table.end();) {
704 if (useful_types.count(type_it->first) == 0) {
705 type_it = table.erase(type_it);
716 std::set<Type> constructible_types{};
717 auto known_constructible = [&](Type type) {
return constructible_types.count(type) != 0; };
720 size_t set_size = constructible_types.size();
722 for (
const auto& [type, recipes] : table) {
723 if (!known_constructible(type)) {
725 for (
const auto& [
_, subt] : recipes) {
728 if (std::all_of(subt.begin(), subt.end(), known_constructible)) {
729 constructible_types.insert(type);
735 if (constructible_types.size() == set_size)
break;
737 for (
auto type_it = table.begin(); type_it != table.end();) {
739 type_it->second.erase(std::remove_if(type_it->second.begin(), type_it->second.end(),
740 [&](
const recipe& rec) {
741 return !std::all_of(rec.second.begin(), rec.second.end(), known_constructible);
742 }), type_it->second.end());
744 if (type_it->second.empty()) {
745 type_it = table.erase(type_it);
751 for (
auto& [type, recipes] : table) {
755 std::sort(recipes.begin(), recipes.end(),
756 [](
const recipe& a,
const recipe& b) {
757 if (a.second.size() < b.second.size()) return true;
758 if (a.second.size() > b.second.size()) return false;
776std::optional<NodeInfo> ConsumeNodeSmart(MsCtx script_ctx,
FuzzedDataProvider& provider, Type type_needed) {
778 const auto& table{
IsTapscript(script_ctx) ? SMARTINFO.tap_table : SMARTINFO.wsh_table};
779 auto recipes_it = table.find(type_needed);
780 assert(recipes_it != table.end());
782 const auto& [frag, subt] =
PickValue(provider, recipes_it->second);
788 return {{frag, ConsumePubKey(provider)}};
789 case Fragment::MULTI: {
792 std::vector<CPubKey> keys{n_keys};
793 for (
auto& key: keys) key = ConsumePubKey(provider);
794 return {{frag,
k, std::move(keys)}};
796 case Fragment::MULTI_A: {
799 std::vector<CPubKey> keys{n_keys};
800 for (
auto& key: keys) key = ConsumePubKey(provider);
801 return {{frag,
k, std::move(keys)}};
803 case Fragment::OLDER:
804 case Fragment::AFTER:
806 case Fragment::SHA256:
807 return {{frag,
PickValue(provider, TEST_DATA.sha256)}};
808 case Fragment::HASH256:
809 return {{frag,
PickValue(provider, TEST_DATA.hash256)}};
811 return {{frag,
PickValue(provider, TEST_DATA.ripemd160)}};
812 case Fragment::HASH160:
813 return {{frag,
PickValue(provider, TEST_DATA.hash160)}};
814 case Fragment::JUST_0:
815 case Fragment::JUST_1:
816 case Fragment::WRAP_A:
817 case Fragment::WRAP_S:
818 case Fragment::WRAP_C:
819 case Fragment::WRAP_D:
820 case Fragment::WRAP_V:
821 case Fragment::WRAP_J:
822 case Fragment::WRAP_N:
823 case Fragment::AND_V:
824 case Fragment::AND_B:
829 case Fragment::ANDOR:
830 return {{subt, frag}};
831 case Fragment::THRESH: {
833 if (subt.size() < 2) {
834 children = subt.size();
841 std::vector<Type> subs = subt;
842 while (subs.size() < children) subs.push_back(subs.back());
843 return {{std::move(subs), frag,
k}};
859NodeRef GenNode(MsCtx script_ctx, F
ConsumeNode, Type root_type,
bool strict_valid =
false) {
861 std::vector<NodeRef> stack;
863 std::vector<std::pair<Type, std::optional<NodeInfo>>> todo{{root_type, {}}};
868 uint32_t scriptsize{1};
870 while (!todo.empty()) {
872 auto type_needed = todo.back().first;
873 if (!todo.back().second) {
876 if (!node_info)
return {};
881 node_info->keys.size(), script_ctx) - 1;
883 switch (node_info->fragment) {
884 case Fragment::JUST_0:
885 case Fragment::JUST_1:
892 case Fragment::OLDER:
893 case Fragment::AFTER:
897 case Fragment::SHA256:
898 case Fragment::HASH160:
899 case Fragment::HASH256:
902 case Fragment::ANDOR:
905 case Fragment::AND_V:
907 case Fragment::AND_B:
920 case Fragment::THRESH:
921 ops += node_info->subtypes.
size();
923 case Fragment::MULTI:
926 case Fragment::MULTI_A:
927 ops += node_info->keys.size() + 1;
929 case Fragment::WRAP_A:
932 case Fragment::WRAP_S:
935 case Fragment::WRAP_C:
938 case Fragment::WRAP_D:
941 case Fragment::WRAP_V:
945 case Fragment::WRAP_J:
948 case Fragment::WRAP_N:
953 auto subtypes = node_info->subtypes;
954 todo.back().second = std::move(node_info);
955 todo.reserve(todo.size() + subtypes.size());
958 for (
size_t i = 0; i < subtypes.size(); ++i) {
959 todo.emplace_back(*(subtypes.rbegin() + i), std::nullopt);
966 NodeInfo& info = *todo.back().second;
968 std::vector<NodeRef> sub;
969 sub.reserve(info.subtypes.size());
970 for (
size_t i = 0; i < info.subtypes.size(); ++i) {
971 sub.push_back(std::move(*(stack.end() - info.subtypes.size() + i)));
973 stack.erase(stack.end() - info.subtypes.size(), stack.end());
976 if (info.keys.empty()) {
977 node =
MakeNodeRef(script_ctx, info.fragment, std::move(sub), std::move(info.hash), info.k);
980 assert(info.hash.empty());
981 node =
MakeNodeRef(script_ctx, info.fragment, std::move(info.keys), info.k);
984 if (!
node || (
node->GetType() &
"KVWB"_mst) ==
""_mst) {
988 if (!(type_needed ==
""_mst)) {
991 if (!
node->IsValid())
return {};
993 if (
node->fragment == Fragment::WRAP_V &&
node->subs[0]->GetType() <<
"x"_mst) {
1002 stack.push_back(std::move(
node));
1006 assert(stack.size() == 1);
1007 assert(stack[0]->GetStaticOps() == ops);
1008 assert(stack[0]->ScriptSize() == scriptsize);
1009 stack[0]->DuplicateKeyCheck(KEY_COMP);
1010 return std::move(stack[0]);
1039 const ParserContext parser_ctx{script_ctx};
1040 std::optional<std::string> str{
node->ToString(parser_ctx)};
1052 if (!(
node->GetType() <<
"K"_mst)) {
1053 bool ends_in_verify = !(
node->GetType() <<
"x"_mst);
1058 if (!
node->IsValidTopLevel())
return;
1067 assert(decoded->GetType() ==
node->GetType());
1082 const auto node_ops{
node->GetOps()};
1085 int add = std::min<int>(
1088 for (
int i = 0; i < add; ++i)
script.push_back(
OP_NOP);
1093 const auto node_exec_ss{
node->GetExecStackSize()};
1096 witness_mal.
stack.resize(add);
1097 witness_nonmal.
stack.resize(add);
1099 for (
unsigned i = 0; i < add; ++i)
script.push_back(
OP_NIP);
1103 const SatisfierContext satisfier_ctx{script_ctx};
1107 const CScript script_pubkey{ScriptPubKey(script_ctx,
script, builder)};
1110 std::vector<std::vector<unsigned char>> stack_mal;
1114 std::vector<std::vector<unsigned char>> stack_nonmal;
1117 if (nonmal_success) {
1122 assert(stack_nonmal.size() <= max_stack_size);
1125 assert(stack_nonmal == stack_mal);
1128 assert(wit_size <= *node->GetWitnessSize());
1131 witness_nonmal.
stack.insert(witness_nonmal.
stack.end(), std::make_move_iterator(stack_nonmal.begin()), std::make_move_iterator(stack_nonmal.end()));
1132 SatisfactionToWitness(script_ctx, witness_nonmal,
script, builder);
1144 if (mal_success && (!nonmal_success || witness_mal.
stack != witness_nonmal.
stack)) {
1146 witness_mal.
stack.insert(witness_mal.
stack.end(), std::make_move_iterator(stack_mal.begin()), std::make_move_iterator(stack_mal.end()));
1147 SatisfactionToWitness(script_ctx, witness_mal,
script, builder);
1155 if (
node->IsSane()) {
1157 assert(mal_success == nonmal_success);
1164 const auto is_key_satisfiable = [script_ctx](
const CPubKey& pubkey) ->
bool {
1165 auto sig_ptr{TEST_DATA.GetSig(script_ctx, pubkey)};
1166 return sig_ptr !=
nullptr && sig_ptr->second;
1168 bool satisfiable =
node->IsSatisfiable([&](
const Node&
node) ->
bool {
1169 switch (
node.fragment) {
1170 case Fragment::PK_K:
1171 case Fragment::PK_H:
1172 return is_key_satisfiable(
node.keys[0]);
1173 case Fragment::MULTI:
1174 case Fragment::MULTI_A: {
1175 size_t sats = std::count_if(
node.keys.begin(),
node.keys.end(), [&](
const auto& key) {
1176 return size_t(is_key_satisfiable(key));
1178 return sats >=
node.k;
1180 case Fragment::OLDER:
1181 case Fragment::AFTER:
1183 case Fragment::SHA256:
1184 return TEST_DATA.sha256_preimages.count(
node.data);
1185 case Fragment::HASH256:
1186 return TEST_DATA.hash256_preimages.count(
node.data);
1188 return TEST_DATA.ripemd160_preimages.count(
node.data);
1189 case Fragment::HASH160:
1190 return TEST_DATA.hash160_preimages.count(
node.data);
1196 assert(mal_success == satisfiable);
1217 for (
const auto script_ctx: {MsCtx::P2WSH, MsCtx::TAPSCRIPT}) {
1219 TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
1220 return ConsumeNodeStable(script_ctx, provider, needed_type);
1221 },
""_mst), provider);
1229 static constexpr std::array<Type, 4> BASE_TYPES{
"B"_mst,
"V"_mst,
"K"_mst,
"W"_mst};
1232 const auto script_ctx{(MsCtx)provider.
ConsumeBool()};
1233 TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
1234 return ConsumeNodeSmart(script_ctx, provider, needed_type);
1235 },
PickValue(provider, BASE_TYPES),
true), provider);
1241 if (buffer.empty())
return;
1244 const ParserContext parser_ctx{(MsCtx)provider.
ConsumeBool()};
1246 if (!parsed)
return;
1248 const auto str2 = parsed->ToString(parser_ctx);
1252 assert(*parsed == *parsed2);
1259 const std::optional<CScript>
script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
1262 const ScriptParserContext script_parser_ctx{(MsCtx)fuzzed_data_provider.
ConsumeBool()};
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).
void Finalize(Span< unsigned char > output)
CHash256 & Write(Span< const unsigned char > input)
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.
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
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...
CPubKey GetEvenCorrespondingCPubKey() const
static constexpr unsigned int size()
constexpr unsigned char * begin()
This type encapsulates the miniscript type system properties.
static const uint256 ZERO
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)
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
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.
NodeRef< typename Ctx::Key > FromString(const std::string &str, const Ctx &ctx)
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< typename Ctx::Key > FromScript(const CScript &script, const Ctx &ctx)
NodeRef< Key > MakeNodeRef(Args &&... args)
Construct a miniscript node as a shared_ptr.
Fragment
The different node types in miniscript.
Internal RIPEMD-160 implementation.
Internal SHA-256 implementation.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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::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 _(ConstevalStringLiteral str)
Translation function.