@@ -70,6 +70,7 @@ struct TestData {
70
70
sig.push_back (1 ); // SIGHASH_ALL
71
71
dummy_sigs.insert ({pubkey, {sig, i & 1 }});
72
72
assert (privkey.SignSchnorr (MESSAGE_HASH, schnorr_sig, nullptr , EMPTY_AUX));
73
+ schnorr_sig.push_back (1 ); // Maximally-sized signature has sighash byte
73
74
schnorr_sigs.emplace (XOnlyPubKey{pubkey}, std::make_pair (std::move (schnorr_sig), i & 1 ));
74
75
75
76
std::vector<unsigned char > hash;
@@ -113,7 +114,9 @@ struct TestData {
113
114
struct ParserContext {
114
115
typedef CPubKey Key;
115
116
116
- MsCtx script_ctx{MsCtx::P2WSH};
117
+ const MsCtx script_ctx;
118
+
119
+ constexpr ParserContext (MsCtx ctx) noexcept : script_ctx(ctx) {}
117
120
118
121
bool KeyCompare (const Key& a, const Key& b) const {
119
122
return a < b;
@@ -178,11 +181,13 @@ struct ParserContext {
178
181
MsCtx MsContext () const {
179
182
return script_ctx;
180
183
}
181
- } PARSER_CTX ;
184
+ };
182
185
183
186
// ! Context that implements naive conversion from/to script only, for roundtrip testing.
184
187
struct ScriptParserContext {
185
- MsCtx script_ctx{MsCtx::P2WSH};
188
+ const MsCtx script_ctx;
189
+
190
+ constexpr ScriptParserContext (MsCtx ctx) noexcept : script_ctx(ctx) {}
186
191
187
192
// ! For Script roundtrip we never need the key from a key hash.
188
193
struct Key {
@@ -228,10 +233,13 @@ struct ScriptParserContext {
228
233
MsCtx MsContext () const {
229
234
return script_ctx;
230
235
}
231
- } SCRIPT_PARSER_CONTEXT ;
236
+ };
232
237
233
238
// ! Context to produce a satisfaction for a Miniscript node using the pre-computed data.
234
- struct SatisfierContext : ParserContext {
239
+ struct SatisfierContext : ParserContext {
240
+
241
+ constexpr SatisfierContext (MsCtx ctx) noexcept : ParserContext(ctx) {}
242
+
235
243
// Timelock challenges satisfaction. Make the value (deterministically) vary to explore different
236
244
// paths.
237
245
bool CheckAfter (uint32_t value) const { return value % 2 ; }
@@ -267,12 +275,10 @@ struct SatisfierContext: ParserContext {
267
275
miniscript::Availability SatHASH160 (const std::vector<unsigned char >& hash, std::vector<unsigned char >& preimage) const {
268
276
return LookupHash (hash, preimage, TEST_DATA.hash160_preimages );
269
277
}
270
- } SATISFIER_CTX ;
278
+ };
271
279
272
280
// ! Context to check a satisfaction against the pre-computed data.
273
- struct CheckerContext : BaseSignatureChecker {
274
- TestData *test_data;
275
-
281
+ const struct CheckerContext : BaseSignatureChecker {
276
282
// Signature checker methods. Checks the right dummy signature is used.
277
283
bool CheckECDSASignature (const std::vector<unsigned char >& sig, const std::vector<unsigned char >& vchPubKey,
278
284
const CScript& scriptCode, SigVersion sigversion) const override
@@ -294,7 +300,7 @@ struct CheckerContext: BaseSignatureChecker {
294
300
} CHECKER_CTX;
295
301
296
302
// ! Context to check for duplicates when instancing a Node.
297
- struct KeyComparator {
303
+ const struct KeyComparator {
298
304
bool KeyCompare (const CPubKey& a, const CPubKey& b) const {
299
305
return a < b;
300
306
}
@@ -1027,15 +1033,15 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
1027
1033
if (!node) return ;
1028
1034
1029
1035
// Check that it roundtrips to text representation
1030
- PARSER_CTX. script_ctx = script_ctx;
1031
- std::optional<std::string> str{node->ToString (PARSER_CTX )};
1036
+ const ParserContext parser_ctx{ script_ctx} ;
1037
+ std::optional<std::string> str{node->ToString (parser_ctx )};
1032
1038
assert (str);
1033
- auto parsed = miniscript::FromString (*str, PARSER_CTX );
1039
+ auto parsed = miniscript::FromString (*str, parser_ctx );
1034
1040
assert (parsed);
1035
1041
assert (*parsed == *node);
1036
1042
1037
1043
// Check consistency between script size estimation and real size.
1038
- auto script = node->ToScript (PARSER_CTX );
1044
+ auto script = node->ToScript (parser_ctx );
1039
1045
assert (node->ScriptSize () == script.size ());
1040
1046
1041
1047
// Check consistency of "x" property with the script (type K is excluded, because it can end
@@ -1049,12 +1055,12 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
1049
1055
if (!node->IsValidTopLevel ()) return ;
1050
1056
1051
1057
// Check roundtrip to script
1052
- auto decoded = miniscript::FromScript (script, PARSER_CTX );
1058
+ auto decoded = miniscript::FromScript (script, parser_ctx );
1053
1059
assert (decoded);
1054
1060
// Note we can't use *decoded == *node because the miniscript representation may differ, so we check that:
1055
1061
// - The script corresponding to that decoded form matches exactly
1056
1062
// - The type matches exactly
1057
- assert (decoded->ToScript (PARSER_CTX ) == script);
1063
+ assert (decoded->ToScript (parser_ctx ) == script);
1058
1064
assert (decoded->GetType () == node->GetType ());
1059
1065
1060
1066
// Optionally pad the script or the witness in order to increase the sensitivity of the tests of
@@ -1091,19 +1097,19 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
1091
1097
}
1092
1098
}
1093
1099
1094
- SATISFIER_CTX. script_ctx = script_ctx;
1100
+ const SatisfierContext satisfier_ctx{ script_ctx} ;
1095
1101
1096
1102
// Get the ScriptPubKey for this script, filling spend data if it's Taproot.
1097
1103
TaprootBuilder builder;
1098
1104
const CScript script_pubkey{ScriptPubKey (script_ctx, script, builder)};
1099
1105
1100
1106
// Run malleable satisfaction algorithm.
1101
1107
std::vector<std::vector<unsigned char >> stack_mal;
1102
- const bool mal_success = node->Satisfy (SATISFIER_CTX , stack_mal, false ) == miniscript::Availability::YES;
1108
+ const bool mal_success = node->Satisfy (satisfier_ctx , stack_mal, false ) == miniscript::Availability::YES;
1103
1109
1104
1110
// Run non-malleable satisfaction algorithm.
1105
1111
std::vector<std::vector<unsigned char >> stack_nonmal;
1106
- const bool nonmal_success = node->Satisfy (SATISFIER_CTX , stack_nonmal, true ) == miniscript::Availability::YES;
1112
+ const bool nonmal_success = node->Satisfy (satisfier_ctx , stack_nonmal, true ) == miniscript::Availability::YES;
1107
1113
1108
1114
if (nonmal_success) {
1109
1115
// Non-malleable satisfactions are bounded by the satisfaction size plus:
@@ -1114,6 +1120,9 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
1114
1120
// If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
1115
1121
assert (mal_success);
1116
1122
assert (stack_nonmal == stack_mal);
1123
+ // Compute witness size (excluding script push, control block, and witness count encoding).
1124
+ const size_t wit_size = GetSerializeSize (stack_nonmal, PROTOCOL_VERSION) - GetSizeOfCompactSize (stack_nonmal.size ());
1125
+ assert (wit_size <= *node->GetWitnessSize ());
1117
1126
1118
1127
// Test non-malleable satisfaction.
1119
1128
witness_nonmal.stack .insert (witness_nonmal.stack .end (), std::make_move_iterator (stack_nonmal.begin ()), std::make_move_iterator (stack_nonmal.end ()));
@@ -1229,13 +1238,13 @@ FUZZ_TARGET(miniscript_string, .init = FuzzInit)
1229
1238
if (buffer.empty ()) return ;
1230
1239
FuzzedDataProvider provider (buffer.data (), buffer.size ());
1231
1240
auto str = provider.ConsumeBytesAsString (provider.remaining_bytes () - 1 );
1232
- PARSER_CTX. script_ctx = (MsCtx)provider.ConsumeBool ();
1233
- auto parsed = miniscript::FromString (str, PARSER_CTX );
1241
+ const ParserContext parser_ctx{ (MsCtx)provider.ConsumeBool ()} ;
1242
+ auto parsed = miniscript::FromString (str, parser_ctx );
1234
1243
if (!parsed) return ;
1235
1244
1236
- const auto str2 = parsed->ToString (PARSER_CTX );
1245
+ const auto str2 = parsed->ToString (parser_ctx );
1237
1246
assert (str2);
1238
- auto parsed2 = miniscript::FromString (*str2, PARSER_CTX );
1247
+ auto parsed2 = miniscript::FromString (*str2, parser_ctx );
1239
1248
assert (parsed2);
1240
1249
assert (*parsed == *parsed2);
1241
1250
}
@@ -1247,9 +1256,9 @@ FUZZ_TARGET(miniscript_script)
1247
1256
const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
1248
1257
if (!script) return ;
1249
1258
1250
- SCRIPT_PARSER_CONTEXT. script_ctx = (MsCtx)fuzzed_data_provider.ConsumeBool ();
1251
- const auto ms = miniscript::FromScript (*script, SCRIPT_PARSER_CONTEXT );
1259
+ const ScriptParserContext script_parser_ctx{ (MsCtx)fuzzed_data_provider.ConsumeBool ()} ;
1260
+ const auto ms = miniscript::FromScript (*script, script_parser_ctx );
1252
1261
if (!ms) return ;
1253
1262
1254
- assert (ms->ToScript (SCRIPT_PARSER_CONTEXT ) == *script);
1263
+ assert (ms->ToScript (script_parser_ctx ) == *script);
1255
1264
}
0 commit comments