@@ -70,6 +70,7 @@ struct TestData {
7070 sig.push_back (1 ); // SIGHASH_ALL
7171 dummy_sigs.insert ({pubkey, {sig, i & 1 }});
7272 assert (privkey.SignSchnorr (MESSAGE_HASH, schnorr_sig, nullptr , EMPTY_AUX));
73+ schnorr_sig.push_back (1 ); // Maximally-sized signature has sighash byte
7374 schnorr_sigs.emplace (XOnlyPubKey{pubkey}, std::make_pair (std::move (schnorr_sig), i & 1 ));
7475
7576 std::vector<unsigned char > hash;
@@ -113,7 +114,9 @@ struct TestData {
113114struct ParserContext {
114115 typedef CPubKey Key;
115116
116- MsCtx script_ctx{MsCtx::P2WSH};
117+ const MsCtx script_ctx;
118+
119+ constexpr ParserContext (MsCtx ctx) noexcept : script_ctx(ctx) {}
117120
118121 bool KeyCompare (const Key& a, const Key& b) const {
119122 return a < b;
@@ -178,11 +181,13 @@ struct ParserContext {
178181 MsCtx MsContext () const {
179182 return script_ctx;
180183 }
181- } PARSER_CTX ;
184+ };
182185
183186// ! Context that implements naive conversion from/to script only, for roundtrip testing.
184187struct ScriptParserContext {
185- MsCtx script_ctx{MsCtx::P2WSH};
188+ const MsCtx script_ctx;
189+
190+ constexpr ScriptParserContext (MsCtx ctx) noexcept : script_ctx(ctx) {}
186191
187192 // ! For Script roundtrip we never need the key from a key hash.
188193 struct Key {
@@ -228,10 +233,13 @@ struct ScriptParserContext {
228233 MsCtx MsContext () const {
229234 return script_ctx;
230235 }
231- } SCRIPT_PARSER_CONTEXT ;
236+ };
232237
233238// ! 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+
235243 // Timelock challenges satisfaction. Make the value (deterministically) vary to explore different
236244 // paths.
237245 bool CheckAfter (uint32_t value) const { return value % 2 ; }
@@ -267,12 +275,10 @@ struct SatisfierContext: ParserContext {
267275 miniscript::Availability SatHASH160 (const std::vector<unsigned char >& hash, std::vector<unsigned char >& preimage) const {
268276 return LookupHash (hash, preimage, TEST_DATA.hash160_preimages );
269277 }
270- } SATISFIER_CTX ;
278+ };
271279
272280// ! Context to check a satisfaction against the pre-computed data.
273- struct CheckerContext : BaseSignatureChecker {
274- TestData *test_data;
275-
281+ const struct CheckerContext : BaseSignatureChecker {
276282 // Signature checker methods. Checks the right dummy signature is used.
277283 bool CheckECDSASignature (const std::vector<unsigned char >& sig, const std::vector<unsigned char >& vchPubKey,
278284 const CScript& scriptCode, SigVersion sigversion) const override
@@ -294,7 +300,7 @@ struct CheckerContext: BaseSignatureChecker {
294300} CHECKER_CTX;
295301
296302// ! Context to check for duplicates when instancing a Node.
297- struct KeyComparator {
303+ const struct KeyComparator {
298304 bool KeyCompare (const CPubKey& a, const CPubKey& b) const {
299305 return a < b;
300306 }
@@ -1027,15 +1033,15 @@ void TestNode(const MsCtx script_ctx, const NodeRef& node, FuzzedDataProvider& p
10271033 if (!node) return ;
10281034
10291035 // 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 )};
10321038 assert (str);
1033- auto parsed = miniscript::FromString (*str, PARSER_CTX );
1039+ auto parsed = miniscript::FromString (*str, parser_ctx );
10341040 assert (parsed);
10351041 assert (*parsed == *node);
10361042
10371043 // Check consistency between script size estimation and real size.
1038- auto script = node->ToScript (PARSER_CTX );
1044+ auto script = node->ToScript (parser_ctx );
10391045 assert (node->ScriptSize () == script.size ());
10401046
10411047 // 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
10491055 if (!node->IsValidTopLevel ()) return ;
10501056
10511057 // Check roundtrip to script
1052- auto decoded = miniscript::FromScript (script, PARSER_CTX );
1058+ auto decoded = miniscript::FromScript (script, parser_ctx );
10531059 assert (decoded);
10541060 // Note we can't use *decoded == *node because the miniscript representation may differ, so we check that:
10551061 // - The script corresponding to that decoded form matches exactly
10561062 // - The type matches exactly
1057- assert (decoded->ToScript (PARSER_CTX ) == script);
1063+ assert (decoded->ToScript (parser_ctx ) == script);
10581064 assert (decoded->GetType () == node->GetType ());
10591065
10601066 // 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
10911097 }
10921098 }
10931099
1094- SATISFIER_CTX. script_ctx = script_ctx;
1100+ const SatisfierContext satisfier_ctx{ script_ctx} ;
10951101
10961102 // Get the ScriptPubKey for this script, filling spend data if it's Taproot.
10971103 TaprootBuilder builder;
10981104 const CScript script_pubkey{ScriptPubKey (script_ctx, script, builder)};
10991105
11001106 // Run malleable satisfaction algorithm.
11011107 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;
11031109
11041110 // Run non-malleable satisfaction algorithm.
11051111 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;
11071113
11081114 if (nonmal_success) {
11091115 // 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
11141120 // If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
11151121 assert (mal_success);
11161122 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 ());
11171126
11181127 // Test non-malleable satisfaction.
11191128 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)
12291238 if (buffer.empty ()) return ;
12301239 FuzzedDataProvider provider (buffer.data (), buffer.size ());
12311240 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 );
12341243 if (!parsed) return ;
12351244
1236- const auto str2 = parsed->ToString (PARSER_CTX );
1245+ const auto str2 = parsed->ToString (parser_ctx );
12371246 assert (str2);
1238- auto parsed2 = miniscript::FromString (*str2, PARSER_CTX );
1247+ auto parsed2 = miniscript::FromString (*str2, parser_ctx );
12391248 assert (parsed2);
12401249 assert (*parsed == *parsed2);
12411250}
@@ -1247,9 +1256,9 @@ FUZZ_TARGET(miniscript_script)
12471256 const std::optional<CScript> script = ConsumeDeserializable<CScript>(fuzzed_data_provider);
12481257 if (!script) return ;
12491258
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 );
12521261 if (!ms) return ;
12531262
1254- assert (ms->ToScript (SCRIPT_PARSER_CONTEXT ) == *script);
1263+ assert (ms->ToScript (script_parser_ctx ) == *script);
12551264}
0 commit comments