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);
394 static constexpr
auto B{
"B"_mst},
K{
"K"_mst}, V{
"V"_mst}, W{
"W"_mst};
398 if (!allow_B)
return {};
399 return {{Fragment::JUST_0}};
401 if (!allow_B)
return {};
402 return {{Fragment::JUST_1}};
404 if (!allow_K)
return {};
405 return {{Fragment::PK_K, ConsumePubKey(provider)}};
407 if (!allow_K)
return {};
408 return {{Fragment::PK_H, ConsumePubKey(provider)}};
410 if (!allow_B)
return {};
411 const auto k = ConsumeTimeLock(provider);
413 return {{Fragment::OLDER, *
k}};
416 if (!allow_B)
return {};
417 const auto k = ConsumeTimeLock(provider);
419 return {{Fragment::AFTER, *
k}};
422 if (!allow_B)
return {};
423 return {{Fragment::SHA256, ConsumeSha256(provider)}};
425 if (!allow_B)
return {};
426 return {{Fragment::HASH256, ConsumeHash256(provider)}};
428 if (!allow_B)
return {};
431 if (!allow_B)
return {};
432 return {{Fragment::HASH160, ConsumeHash160(provider)}};
434 if (!allow_B ||
IsTapscript(script_ctx))
return {};
437 if (n_keys > 20 || k == 0 || k > n_keys)
return {};
438 std::vector<CPubKey> keys{n_keys};
439 for (
auto& key: keys) key = ConsumePubKey(provider);
440 return {{Fragment::MULTI,
k, std::move(keys)}};
443 if (!(allow_B || allow_K || allow_V))
return {};
444 return {{{
B, type_needed, type_needed}, Fragment::ANDOR}};
446 if (!(allow_B || allow_K || allow_V))
return {};
447 return {{{V, type_needed}, Fragment::AND_V}};
449 if (!allow_B)
return {};
450 return {{{
B, W}, Fragment::AND_B}};
452 if (!allow_B)
return {};
453 return {{{
B, W}, Fragment::OR_B}};
455 if (!allow_V)
return {};
456 return {{{
B, V}, Fragment::OR_C}};
458 if (!allow_B)
return {};
459 return {{{
B,
B}, Fragment::OR_D}};
461 if (!(allow_B || allow_K || allow_V))
return {};
462 return {{{type_needed, type_needed}, Fragment::OR_I}};
464 if (!allow_B)
return {};
467 if (k == 0 || k > n_subs)
return {};
468 std::vector<Type> subtypes;
469 subtypes.reserve(n_subs);
470 subtypes.emplace_back(
"B"_mst);
471 for (
size_t i = 1; i < n_subs; ++i) subtypes.emplace_back(
"W"_mst);
472 return {{std::move(subtypes), Fragment::THRESH,
k}};
475 if (!allow_W)
return {};
476 return {{{
B}, Fragment::WRAP_A}};
478 if (!allow_W)
return {};
479 return {{{
B}, Fragment::WRAP_S}};
481 if (!allow_B)
return {};
482 return {{{
K}, Fragment::WRAP_C}};
484 if (!allow_B)
return {};
485 return {{{V}, Fragment::WRAP_D}};
487 if (!allow_V)
return {};
488 return {{{
B}, Fragment::WRAP_V}};
490 if (!allow_B)
return {};
491 return {{{
B}, Fragment::WRAP_J}};
493 if (!allow_B)
return {};
494 return {{{
B}, Fragment::WRAP_N}};
496 if (!allow_B || !
IsTapscript(script_ctx))
return {};
499 if (n_keys > 999 || k == 0 || k > n_keys)
return {};
500 std::vector<CPubKey> keys{n_keys};
501 for (
auto& key: keys) key = ConsumePubKey(provider);
502 return {{Fragment::MULTI_A,
k, std::move(keys)}};
519 using recipe = std::pair<Fragment, std::vector<Type>>;
520 std::map<Type, std::vector<recipe>> wsh_table, tap_table;
524 Init(wsh_table, MsCtx::P2WSH);
525 Init(tap_table, MsCtx::TAPSCRIPT);
528 void Init(std::map<Type, std::vector<recipe>>& table, MsCtx script_ctx)
531 std::vector<Type> types;
532 static constexpr
auto B_mst{
"B"_mst}, K_mst{
"K"_mst}, V_mst{
"V"_mst}, W_mst{
"W"_mst};
533 static constexpr
auto d_mst{
"d"_mst}, n_mst{
"n"_mst}, o_mst{
"o"_mst}, u_mst{
"u"_mst}, z_mst{
"z"_mst};
534 static constexpr
auto NONE_mst{
""_mst};
535 for (
int base = 0; base < 4; ++base) {
536 Type type_base = base == 0 ? B_mst : base == 1 ? K_mst : base == 2 ? V_mst : W_mst;
537 for (
int zo = 0; zo < 3; ++zo) {
538 Type type_zo = zo == 0 ? z_mst : zo == 1 ? o_mst : NONE_mst;
539 for (
int n = 0; n < 2; ++n) {
540 if (zo == 0 && n == 1)
continue;
541 if (base == 3 && n == 1)
continue;
542 Type type_n = n == 0 ? NONE_mst : n_mst;
543 for (
int d = 0; d < 2; ++d) {
544 if (base == 2 && d == 1)
continue;
545 Type type_d = d == 0 ? NONE_mst : d_mst;
546 for (
int u = 0; u < 2; ++u) {
547 if (base == 2 && u == 1)
continue;
548 Type type_u = u == 0 ? NONE_mst : u_mst;
549 Type type = type_base | type_zo | type_n | type_d | type_u;
550 types.push_back(type);
563 auto is_super_of = [](
const recipe& a,
const recipe& b) {
564 if (a.first != b.first)
return false;
565 if (a.second.size() != b.second.size())
return false;
566 for (
size_t i = 0; i < a.second.size(); ++i) {
567 if (!(b.second[i] << a.second[i]))
return false;
577 std::sort(types.begin(), types.end());
580 for (
int fragidx = 0; fragidx <= int(Fragment::MULTI_A); ++fragidx) {
583 size_t data_size = 0;
600 case Fragment::MULTI:
601 case Fragment::MULTI_A:
605 case Fragment::OLDER:
606 case Fragment::AFTER:
609 case Fragment::SHA256:
610 case Fragment::HASH256:
614 case Fragment::HASH160:
617 case Fragment::JUST_0:
618 case Fragment::JUST_1:
620 case Fragment::WRAP_A:
621 case Fragment::WRAP_S:
622 case Fragment::WRAP_C:
623 case Fragment::WRAP_D:
624 case Fragment::WRAP_V:
625 case Fragment::WRAP_J:
626 case Fragment::WRAP_N:
629 case Fragment::AND_V:
630 case Fragment::AND_B:
637 case Fragment::ANDOR:
640 case Fragment::THRESH:
649 std::vector<Type> subt;
650 for (
int subs = sub_count; subs < sub_count + sub_range; ++subs) {
652 for (Type x : types) {
653 for (Type y : types) {
654 for (Type z : types) {
657 if (subs > 0) subt.push_back(x);
658 if (subs > 1) subt.push_back(y);
659 if (subs > 2) subt.push_back(z);
662 if ((res <<
"K"_mst) + (res <<
"V"_mst) + (res <<
"B"_mst) + (res <<
"W"_mst) != 1)
continue;
664 recipe entry{frag, subt};
665 auto super_of_entry = [&](
const recipe& rec) {
return is_super_of(rec, entry); };
668 for (Type s : types) {
669 if ((res &
"BKVWzondu"_mst) << s) {
670 auto& recipes = table[s];
672 if (!std::any_of(recipes.begin(), recipes.end(), super_of_entry)) {
673 recipes.push_back(entry);
678 if (subs <= 2)
break;
680 if (subs <= 1)
break;
682 if (subs <= 0)
break;
690 std::set<Type> useful_types{B_mst, V_mst, K_mst, W_mst};
693 size_t set_size = useful_types.size();
694 for (
const auto& [type, recipes] : table) {
695 if (useful_types.count(type) != 0) {
696 for (
const auto& [
_, subtypes] : recipes) {
697 for (
auto subtype : subtypes) useful_types.insert(subtype);
701 if (useful_types.size() == set_size)
break;
704 for (
auto type_it = table.begin(); type_it != table.end();) {
705 if (useful_types.count(type_it->first) == 0) {
706 type_it = table.erase(type_it);
717 std::set<Type> constructible_types{};
718 auto known_constructible = [&](Type type) {
return constructible_types.count(type) != 0; };
721 size_t set_size = constructible_types.size();
723 for (
const auto& [type, recipes] : table) {
724 if (!known_constructible(type)) {
726 for (
const auto& [
_, subt] : recipes) {
729 if (std::all_of(subt.begin(), subt.end(), known_constructible)) {
730 constructible_types.insert(type);
736 if (constructible_types.size() == set_size)
break;
738 for (
auto type_it = table.begin(); type_it != table.end();) {
740 type_it->second.erase(std::remove_if(type_it->second.begin(), type_it->second.end(),
741 [&](
const recipe& rec) {
742 return !std::all_of(rec.second.begin(), rec.second.end(), known_constructible);
743 }), type_it->second.end());
745 if (type_it->second.empty()) {
746 type_it = table.erase(type_it);
752 for (
auto& [type, recipes] : table) {
756 std::sort(recipes.begin(), recipes.end(),
757 [](
const recipe& a,
const recipe& b) {
758 if (a.second.size() < b.second.size()) return true;
759 if (a.second.size() > b.second.size()) return false;
777 std::optional<NodeInfo> ConsumeNodeSmart(MsCtx script_ctx,
FuzzedDataProvider& provider, Type type_needed) {
779 const auto& table{
IsTapscript(script_ctx) ? SMARTINFO.tap_table : SMARTINFO.wsh_table};
780 auto recipes_it = table.find(type_needed);
781 assert(recipes_it != table.end());
783 const auto& [frag, subt] =
PickValue(provider, recipes_it->second);
789 return {{frag, ConsumePubKey(provider)}};
790 case Fragment::MULTI: {
793 std::vector<CPubKey> keys{n_keys};
794 for (
auto& key: keys) key = ConsumePubKey(provider);
795 return {{frag,
k, std::move(keys)}};
797 case Fragment::MULTI_A: {
800 std::vector<CPubKey> keys{n_keys};
801 for (
auto& key: keys) key = ConsumePubKey(provider);
802 return {{frag,
k, std::move(keys)}};
804 case Fragment::OLDER:
805 case Fragment::AFTER:
807 case Fragment::SHA256:
808 return {{frag,
PickValue(provider, TEST_DATA.sha256)}};
809 case Fragment::HASH256:
810 return {{frag,
PickValue(provider, TEST_DATA.hash256)}};
812 return {{frag,
PickValue(provider, TEST_DATA.ripemd160)}};
813 case Fragment::HASH160:
814 return {{frag,
PickValue(provider, TEST_DATA.hash160)}};
815 case Fragment::JUST_0:
816 case Fragment::JUST_1:
817 case Fragment::WRAP_A:
818 case Fragment::WRAP_S:
819 case Fragment::WRAP_C:
820 case Fragment::WRAP_D:
821 case Fragment::WRAP_V:
822 case Fragment::WRAP_J:
823 case Fragment::WRAP_N:
824 case Fragment::AND_V:
825 case Fragment::AND_B:
830 case Fragment::ANDOR:
831 return {{subt, frag}};
832 case Fragment::THRESH: {
834 if (subt.size() < 2) {
835 children = subt.size();
842 std::vector<Type> subs = subt;
843 while (subs.size() < children) subs.push_back(subs.back());
844 return {{std::move(subs), frag,
k}};
860 NodeRef GenNode(MsCtx script_ctx, F
ConsumeNode, Type root_type,
bool strict_valid =
false) {
862 std::vector<NodeRef> stack;
864 std::vector<std::pair<Type, std::optional<NodeInfo>>> todo{{root_type, {}}};
869 uint32_t scriptsize{1};
871 while (!todo.empty()) {
873 auto type_needed = todo.back().first;
874 if (!todo.back().second) {
877 if (!node_info)
return {};
882 node_info->keys.size(), script_ctx) - 1;
884 switch (node_info->fragment) {
885 case Fragment::JUST_0:
886 case Fragment::JUST_1:
893 case Fragment::OLDER:
894 case Fragment::AFTER:
898 case Fragment::SHA256:
899 case Fragment::HASH160:
900 case Fragment::HASH256:
903 case Fragment::ANDOR:
906 case Fragment::AND_V:
908 case Fragment::AND_B:
921 case Fragment::THRESH:
922 ops += node_info->subtypes.
size();
924 case Fragment::MULTI:
927 case Fragment::MULTI_A:
928 ops += node_info->keys.size() + 1;
930 case Fragment::WRAP_A:
933 case Fragment::WRAP_S:
936 case Fragment::WRAP_C:
939 case Fragment::WRAP_D:
942 case Fragment::WRAP_V:
946 case Fragment::WRAP_J:
949 case Fragment::WRAP_N:
954 auto subtypes = node_info->subtypes;
955 todo.back().second = std::move(node_info);
956 todo.reserve(todo.size() + subtypes.size());
959 for (
size_t i = 0; i < subtypes.size(); ++i) {
960 todo.emplace_back(*(subtypes.rbegin() + i), std::nullopt);
967 NodeInfo& info = *todo.back().second;
969 std::vector<NodeRef> sub;
970 sub.reserve(info.subtypes.size());
971 for (
size_t i = 0; i < info.subtypes.size(); ++i) {
972 sub.push_back(std::move(*(stack.end() - info.subtypes.size() + i)));
974 stack.erase(stack.end() - info.subtypes.size(), stack.end());
977 if (info.keys.empty()) {
978 node =
MakeNodeRef(script_ctx, info.fragment, std::move(sub), std::move(info.hash), info.k);
981 assert(info.hash.empty());
982 node =
MakeNodeRef(script_ctx, info.fragment, std::move(info.keys), info.k);
985 if (!
node || (
node->GetType() &
"KVWB"_mst) ==
""_mst) {
989 if (!(type_needed ==
""_mst)) {
992 if (!
node->IsValid())
return {};
994 if (
node->fragment == Fragment::WRAP_V &&
node->subs[0]->GetType() <<
"x"_mst) {
1003 stack.push_back(std::move(
node));
1007 assert(stack.size() == 1);
1008 assert(stack[0]->GetStaticOps() == ops);
1009 assert(stack[0]->ScriptSize() == scriptsize);
1010 stack[0]->DuplicateKeyCheck(KEY_COMP);
1011 return std::move(stack[0]);
1040 const ParserContext parser_ctx{script_ctx};
1041 std::optional<std::string> str{
node->ToString(parser_ctx)};
1048 auto script =
node->ToScript(parser_ctx);
1053 if (!(
node->GetType() <<
"K"_mst)) {
1054 bool ends_in_verify = !(
node->GetType() <<
"x"_mst);
1059 if (!
node->IsValidTopLevel())
return;
1067 assert(decoded->ToScript(parser_ctx) == script);
1068 assert(decoded->GetType() ==
node->GetType());
1083 const auto node_ops{
node->GetOps()};
1086 int add = std::min<int>(
1094 const auto node_exec_ss{
node->GetExecStackSize()};
1097 witness_mal.
stack.resize(add);
1098 witness_nonmal.
stack.resize(add);
1104 const SatisfierContext satisfier_ctx{script_ctx};
1108 const CScript script_pubkey{ScriptPubKey(script_ctx, script, builder)};
1111 std::vector<std::vector<unsigned char>> stack_mal;
1115 std::vector<std::vector<unsigned char>> stack_nonmal;
1118 if (nonmal_success) {
1123 assert(stack_nonmal.size() <= max_stack_size);
1126 assert(stack_nonmal == stack_mal);
1129 assert(wit_size <= *node->GetWitnessSize());
1132 witness_nonmal.
stack.insert(witness_nonmal.
stack.end(), std::make_move_iterator(stack_nonmal.begin()), std::make_move_iterator(stack_nonmal.end()));
1133 SatisfactionToWitness(script_ctx, witness_nonmal, script, builder);
1145 if (mal_success && (!nonmal_success || witness_mal.
stack != witness_nonmal.
stack)) {
1147 witness_mal.
stack.insert(witness_mal.
stack.end(), std::make_move_iterator(stack_mal.begin()), std::make_move_iterator(stack_mal.end()));
1148 SatisfactionToWitness(script_ctx, witness_mal, script, builder);
1156 if (
node->IsSane()) {
1158 assert(mal_success == nonmal_success);
1165 const auto is_key_satisfiable = [script_ctx](
const CPubKey& pubkey) ->
bool {
1166 auto sig_ptr{TEST_DATA.GetSig(script_ctx, pubkey)};
1167 return sig_ptr !=
nullptr && sig_ptr->second;
1169 bool satisfiable =
node->IsSatisfiable([&](
const Node&
node) ->
bool {
1170 switch (
node.fragment) {
1171 case Fragment::PK_K:
1172 case Fragment::PK_H:
1173 return is_key_satisfiable(
node.keys[0]);
1174 case Fragment::MULTI:
1175 case Fragment::MULTI_A: {
1176 size_t sats = std::count_if(
node.keys.begin(),
node.keys.end(), [&](
const auto& key) {
1177 return size_t(is_key_satisfiable(key));
1179 return sats >=
node.k;
1181 case Fragment::OLDER:
1182 case Fragment::AFTER:
1184 case Fragment::SHA256:
1185 return TEST_DATA.sha256_preimages.count(
node.data);
1186 case Fragment::HASH256:
1187 return TEST_DATA.hash256_preimages.count(
node.data);
1189 return TEST_DATA.ripemd160_preimages.count(
node.data);
1190 case Fragment::HASH160:
1191 return TEST_DATA.hash160_preimages.count(
node.data);
1197 assert(mal_success == satisfiable);
1218 for (
const auto script_ctx: {MsCtx::P2WSH, MsCtx::TAPSCRIPT}) {
1220 TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
1221 return ConsumeNodeStable(script_ctx, provider, needed_type);
1222 },
""_mst), provider);
1230 static constexpr std::array<Type, 4> BASE_TYPES{
"B"_mst,
"V"_mst,
"K"_mst,
"W"_mst};
1233 const auto script_ctx{(MsCtx)provider.
ConsumeBool()};
1234 TestNode(script_ctx, GenNode(script_ctx, [&](Type needed_type) {
1235 return ConsumeNodeSmart(script_ctx, provider, needed_type);
1236 },
PickValue(provider, BASE_TYPES),
true), provider);
1242 if (buffer.empty())
return;
1245 const ParserContext parser_ctx{(MsCtx)provider.
ConsumeBool()};
1247 if (!parsed)
return;
1249 const auto str2 = parsed->ToString(parser_ctx);
1253 assert(*parsed == *parsed2);
1260 const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
1261 if (!script)
return;
1263 const ScriptParserContext script_parser_ctx{(MsCtx)fuzzed_data_provider.
ConsumeBool()};
1267 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.