MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / TestSatisfy

Method TestSatisfy

src/test/miniscript_tests.cpp:347–433  ·  view source on GitHub ↗

Run random satisfaction tests. */

Source from the content-addressed store, hash-verified

345struct MiniScriptTest : BasicTestingSetup {
346/** Run random satisfaction tests. */
347void TestSatisfy(const KeyConverter& converter, const Node& node)
348{
349 auto script = node.ToScript(converter);
350 const auto challenges{FindChallenges(node)}; // Find all challenges in the generated miniscript.
351 std::vector<Challenge> challist(challenges.begin(), challenges.end());
352 for (int iter = 0; iter < 3; ++iter) {
353 std::shuffle(challist.begin(), challist.end(), m_rng);
354 Satisfier satisfier(converter.MsContext());
355 TestSignatureChecker checker(satisfier);
356 bool prev_mal_success = false, prev_nonmal_success = false;
357 // Go over all challenges involved in this miniscript in random order.
358 for (int add = -1; add < (int)challist.size(); ++add) {
359 if (add >= 0) satisfier.supported.insert(challist[add]); // The first iteration does not add anything
360
361 // Get the ScriptPubKey for this script, filling spend data if it's Taproot.
362 TaprootBuilder builder;
363 const CScript script_pubkey{ScriptPubKey(converter.MsContext(), script, builder)};
364
365 // Run malleable satisfaction algorithm.
366 CScriptWitness witness_mal;
367 const bool mal_success = node.Satisfy(satisfier, witness_mal.stack, false) == miniscript::Availability::YES;
368 SatisfactionToWitness(converter.MsContext(), witness_mal, script, builder);
369
370 // Run non-malleable satisfaction algorithm.
371 CScriptWitness witness_nonmal;
372 const bool nonmal_success = node.Satisfy(satisfier, witness_nonmal.stack, true) == miniscript::Availability::YES;
373 // Compute witness size (excluding script push, control block, and witness count encoding).
374 const uint64_t wit_size{GetSerializeSize(witness_nonmal.stack) - GetSizeOfCompactSize(witness_nonmal.stack.size())};
375 SatisfactionToWitness(converter.MsContext(), witness_nonmal, script, builder);
376
377 if (nonmal_success) {
378 // Non-malleable satisfactions are bounded by the satisfaction size plus:
379 // - For P2WSH spends, the witness script
380 // - For Tapscript spends, both the witness script and the control block
381 const size_t max_stack_size{*node.GetStackSize() + 1 + miniscript::IsTapscript(converter.MsContext())};
382 BOOST_CHECK(witness_nonmal.stack.size() <= max_stack_size);
383 // If a non-malleable satisfaction exists, the malleable one must also exist, and be identical to it.
384 BOOST_CHECK(mal_success);
385 BOOST_CHECK(witness_nonmal.stack == witness_mal.stack);
386 assert(wit_size <= *node.GetWitnessSize());
387
388 // Test non-malleable satisfaction.
389 ScriptError serror;
390 bool res = VerifyScript(CScript(), script_pubkey, &witness_nonmal, STANDARD_SCRIPT_VERIFY_FLAGS, checker, &serror);
391 // Non-malleable satisfactions are guaranteed to be valid if ValidSatisfactions().
392 if (node.ValidSatisfactions()) BOOST_CHECK(res);
393 // More detailed: non-malleable satisfactions must be valid, or could fail with ops count error (if CheckOpsLimit failed),
394 // or with a stack size error (if CheckStackSize check fails).
395 BOOST_CHECK(res ||
396 (!node.CheckOpsLimit() && serror == ScriptError::SCRIPT_ERR_OP_COUNT) ||
397 (!node.CheckStackSize() && serror == ScriptError::SCRIPT_ERR_STACK_SIZE));
398 }
399
400 if (mal_success && (!nonmal_success || witness_mal.stack != witness_nonmal.stack)) {
401 // Test malleable satisfaction only if it's different from the non-malleable one.
402 ScriptError serror;
403 bool res = VerifyScript(CScript(), script_pubkey, &witness_mal, STANDARD_SCRIPT_VERIFY_FLAGS, checker, &serror);
404 // Malleable satisfactions are not guaranteed to be valid under any conditions, but they can only

Callers

nothing calls this directly

Calls 15

FindChallengesFunction · 0.85
GetSerializeSizeFunction · 0.85
GetSizeOfCompactSizeFunction · 0.85
IsTapscriptFunction · 0.85
VerifyScriptFunction · 0.85
ToScriptMethod · 0.80
SatisfyMethod · 0.80
GetStackSizeMethod · 0.80
GetWitnessSizeMethod · 0.80
ValidSatisfactionsMethod · 0.80
CheckOpsLimitMethod · 0.80
CheckStackSizeMethod · 0.80

Tested by

no test coverage detected