mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
test: improves tapscript unit tests
This commit creates new test utilities for future Taproot script tests within script_tests.json. The key features of this commit are the addition of three new tags: `#SCRIPT#`, `#CONTROLBLOCK#`, and `#TAPROOTOUTPUT#`. These tags streamline the test creation process by eliminating the need to manually generate these components outside the test suite. * `#SCRIPT#`: Parses Tapscript and outputs a byte string of opcodes. * `#CONTROLBLOCK#`: Automatically generates the control block for a given Taproot output. * `#TAPROOTOUTPUT#`: Generates the final Taproot scriptPubKey. Update src/test/script_tests.cpp Co-authored-by: Jan B <608446+janb84@users.noreply.github.com>
This commit is contained in:
parent
3e167085ba
commit
e3d7533ac9
2 changed files with 86 additions and 5 deletions
|
@ -2610,6 +2610,63 @@
|
||||||
[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"],
|
[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"],
|
||||||
[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"],
|
[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"],
|
||||||
|
|
||||||
|
["Tapscript tests"],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"1ffe1234567890",
|
||||||
|
"00",
|
||||||
|
"#SCRIPT# HASH256 DUP SHA1 DROP DUP DROP TOALTSTACK HASH256 DUP DROP TOALTSTACK FROMALTSTACK",
|
||||||
|
"#CONTROLBLOCK#",
|
||||||
|
0.00000001
|
||||||
|
],
|
||||||
|
"",
|
||||||
|
"0x51 0x20 #TAPROOTOUTPUT#",
|
||||||
|
"P2SH,WITNESS,TAPROOT",
|
||||||
|
"OK",
|
||||||
|
"TAPSCRIPT Tests testing tapscript with many different op codes including ALTSTACK interactions"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"abcdef",
|
||||||
|
"#SCRIPT# 1 IF SHA256 ENDIF SIZE SWAP DROP 32 EQUAL",
|
||||||
|
"#CONTROLBLOCK#",
|
||||||
|
0.00000001
|
||||||
|
],
|
||||||
|
"",
|
||||||
|
"0x51 0x20 #TAPROOTOUTPUT#",
|
||||||
|
"P2SH,WITNESS,TAPROOT",
|
||||||
|
"OK",
|
||||||
|
"TAPSCRIPT Test IF conditional when true"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"abcdef",
|
||||||
|
"#SCRIPT# 0 IF SHA256 ENDIF SIZE SWAP DROP 32 EQUAL",
|
||||||
|
"#CONTROLBLOCK#",
|
||||||
|
0.00000001
|
||||||
|
],
|
||||||
|
"",
|
||||||
|
"0x51 0x20 #TAPROOTOUTPUT#",
|
||||||
|
"P2SH,WITNESS,TAPROOT",
|
||||||
|
"EVAL_FALSE",
|
||||||
|
"TAPSCRIPT Test IF conditional when false"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"aa",
|
||||||
|
"bb",
|
||||||
|
"cc",
|
||||||
|
"#SCRIPT# EQUAL IF DROP DROP ENDIF",
|
||||||
|
"#CONTROLBLOCK#",
|
||||||
|
0.00000001
|
||||||
|
],
|
||||||
|
"",
|
||||||
|
"0x51 0x20 #TAPROOTOUTPUT#",
|
||||||
|
"P2SH,WITNESS,TAPROOT",
|
||||||
|
"OK",
|
||||||
|
"TAPSCRIPT Test that DROP operations do not execute inside of a false IF conditional"
|
||||||
|
],
|
||||||
|
|
||||||
["NULLFAIL should cover all signatures and signatures only"],
|
["NULLFAIL should cover all signatures and signatures only"],
|
||||||
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"],
|
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"],
|
||||||
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"],
|
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"],
|
||||||
|
|
|
@ -916,21 +916,38 @@ BOOST_AUTO_TEST_CASE(script_json_test)
|
||||||
// amount (nValue) to use in the crediting tx
|
// amount (nValue) to use in the crediting tx
|
||||||
UniValue tests = read_json(json_tests::script_tests);
|
UniValue tests = read_json(json_tests::script_tests);
|
||||||
|
|
||||||
|
const KeyData keys;
|
||||||
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
||||||
const UniValue& test = tests[idx];
|
const UniValue& test = tests[idx];
|
||||||
std::string strTest = test.write();
|
std::string strTest = test.write();
|
||||||
CScriptWitness witness;
|
CScriptWitness witness;
|
||||||
|
TaprootBuilder taprootBuilder;
|
||||||
CAmount nValue = 0;
|
CAmount nValue = 0;
|
||||||
unsigned int pos = 0;
|
unsigned int pos = 0;
|
||||||
if (test.size() > 0 && test[pos].isArray()) {
|
if (test.size() > 0 && test[pos].isArray()) {
|
||||||
unsigned int i=0;
|
unsigned int i=0;
|
||||||
for (i = 0; i < test[pos].size()-1; i++) {
|
for (i = 0; i < test[pos].size()-1; i++) {
|
||||||
auto element = test[pos][i].get_str();
|
auto element = test[pos][i].get_str();
|
||||||
const auto witness_value{TryParseHex<unsigned char>(element)};
|
// We use #SCRIPT# to flag a non-hex script that we can read using ParseScript
|
||||||
if (!witness_value.has_value()) {
|
// Taproot script must be third from the last element in witness stack
|
||||||
BOOST_ERROR("Bad witness in test: " << strTest << " witness is not hex: " << element);
|
static const std::string SCRIPT_FLAG{"#SCRIPT#"};
|
||||||
|
if (element.starts_with(SCRIPT_FLAG)) {
|
||||||
|
CScript script = ParseScript(element.substr(SCRIPT_FLAG.size()));
|
||||||
|
witness.stack.push_back(ToByteVector(script));
|
||||||
|
} else if (element == "#CONTROLBLOCK#") {
|
||||||
|
// Taproot script control block - second from the last element in witness stack
|
||||||
|
// If #CONTROLBLOCK# we auto-generate the control block
|
||||||
|
taprootBuilder.Add(/*depth=*/0, witness.stack.back(), TAPROOT_LEAF_TAPSCRIPT, /*track=*/true);
|
||||||
|
taprootBuilder.Finalize(XOnlyPubKey(keys.key0.GetPubKey()));
|
||||||
|
auto controlblocks = taprootBuilder.GetSpendData().scripts[{witness.stack.back(), TAPROOT_LEAF_TAPSCRIPT}];
|
||||||
|
witness.stack.push_back(*(controlblocks.begin()));
|
||||||
|
} else {
|
||||||
|
const auto witness_value{TryParseHex<unsigned char>(element)};
|
||||||
|
if (!witness_value.has_value()) {
|
||||||
|
BOOST_ERROR("Bad witness in test: " << strTest << " witness is not hex: " << element);
|
||||||
|
}
|
||||||
|
witness.stack.push_back(witness_value.value());
|
||||||
}
|
}
|
||||||
witness.stack.push_back(witness_value.value());
|
|
||||||
}
|
}
|
||||||
nValue = AmountFromValue(test[pos][i]);
|
nValue = AmountFromValue(test[pos][i]);
|
||||||
pos++;
|
pos++;
|
||||||
|
@ -945,7 +962,14 @@ BOOST_AUTO_TEST_CASE(script_json_test)
|
||||||
std::string scriptSigString = test[pos++].get_str();
|
std::string scriptSigString = test[pos++].get_str();
|
||||||
CScript scriptSig = ParseScript(scriptSigString);
|
CScript scriptSig = ParseScript(scriptSigString);
|
||||||
std::string scriptPubKeyString = test[pos++].get_str();
|
std::string scriptPubKeyString = test[pos++].get_str();
|
||||||
CScript scriptPubKey = ParseScript(scriptPubKeyString);
|
CScript scriptPubKey;
|
||||||
|
// If requested, auto-generate the taproot output
|
||||||
|
if (scriptPubKeyString == "0x51 0x20 #TAPROOTOUTPUT#") {
|
||||||
|
BOOST_CHECK_MESSAGE(taprootBuilder.IsComplete(), "Failed to autogenerate Tapscript output key");
|
||||||
|
scriptPubKey = CScript() << OP_1 << ToByteVector(taprootBuilder.GetOutput());
|
||||||
|
} else {
|
||||||
|
scriptPubKey = ParseScript(scriptPubKeyString);
|
||||||
|
}
|
||||||
unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str());
|
unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str());
|
||||||
int scriptError = ParseScriptError(test[pos++].get_str());
|
int scriptError = ParseScriptError(test[pos++].get_str());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue