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

Function TestNode

src/test/fuzz/miniscript.cpp:1030–1193  ·  view source on GitHub ↗

Perform various applicable tests on a miniscript Node. */

Source from the content-addressed store, hash-verified

1028
1029/** Perform various applicable tests on a miniscript Node. */
1030void TestNode(const MsCtx script_ctx, const std::optional<Node>& node, FuzzedDataProvider& provider)
1031{
1032 if (!node) return;
1033
1034 // Check that it roundtrips to text representation
1035 const ParserContext parser_ctx{script_ctx};
1036 std::optional<std::string> str{node->ToString(parser_ctx)};
1037 assert(str);
1038 auto parsed = miniscript::FromString(*str, parser_ctx);
1039 assert(parsed);
1040 assert(*parsed == *node);
1041
1042 // Check consistency between script size estimation and real size.
1043 auto script = node->ToScript(parser_ctx);
1044 assert(node->ScriptSize() == script.size());
1045
1046 // Check consistency of "x" property with the script (type K is excluded, because it can end
1047 // with a push of a key, which could match these opcodes).
1048 if (!(node->GetType() << "K"_mst)) {
1049 bool ends_in_verify = !(node->GetType() << "x"_mst);
1050 assert(ends_in_verify == (script.back() == OP_CHECKSIG || script.back() == OP_CHECKMULTISIG || script.back() == OP_EQUAL || script.back() == OP_NUMEQUAL));
1051 }
1052
1053 // The rest of the checks only apply when testing a valid top-level script.
1054 if (!node->IsValidTopLevel()) return;
1055
1056 // Check roundtrip to script
1057 auto decoded = miniscript::FromScript(script, parser_ctx);
1058 assert(decoded);
1059 // Note we can't use *decoded == *node because the miniscript representation may differ, so we check that:
1060 // - The script corresponding to that decoded form matches exactly
1061 // - The type matches exactly
1062 assert(decoded->ToScript(parser_ctx) == script);
1063 assert(decoded->GetType() == node->GetType());
1064
1065 // Optionally pad the script or the witness in order to increase the sensitivity of the tests of
1066 // the resources limits logic.
1067 CScriptWitness witness_mal, witness_nonmal;
1068 if (provider.ConsumeBool()) {
1069 // Under P2WSH, optionally pad the script with OP_NOPs to max op the ops limit of the constructed script.
1070 // This makes the script obviously not actually miniscript-compatible anymore, but the
1071 // signatures constructed in this test don't commit to the script anyway, so the same
1072 // miniscript satisfier will work. This increases the sensitivity of the test to the ops
1073 // counting logic being too low, especially for simple scripts.
1074 // Do this optionally because we're not solely interested in cases where the number of ops is
1075 // maximal.
1076 // Do not pad more than what would cause MAX_STANDARD_P2WSH_SCRIPT_SIZE to be reached, however,
1077 // as that also invalidates scripts.
1078 const auto node_ops{node->GetOps()};
1079 if (!IsTapscript(script_ctx) && node_ops && *node_ops < MAX_OPS_PER_SCRIPT
1080 && node->ScriptSize() < MAX_STANDARD_P2WSH_SCRIPT_SIZE) {
1081 int add = std::min<int>(
1082 MAX_OPS_PER_SCRIPT - *node_ops,
1083 MAX_STANDARD_P2WSH_SCRIPT_SIZE - node->ScriptSize());
1084 for (int i = 0; i < add; ++i) script.push_back(OP_NOP);
1085 }
1086
1087 // Under Tapscript, optionally pad the stack up to the limit minus the calculated maximum execution stack

Callers 1

miniscript.cppFile · 0.70

Calls 15

FromStringFunction · 0.85
FromScriptFunction · 0.85
IsTapscriptFunction · 0.85
GetSerializeSizeFunction · 0.85
GetSizeOfCompactSizeFunction · 0.85
VerifyScriptFunction · 0.85
ToScriptMethod · 0.80
IsValidTopLevelMethod · 0.80
ConsumeBoolMethod · 0.80
GetOpsMethod · 0.80
GetExecStackSizeMethod · 0.80
SatisfyMethod · 0.80

Tested by

no test coverage detected