mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 15:50:07 +01:00
[qa] script_tests: witness tests can specify tx amount
Add tests that witness signatures cover value
This commit is contained in:
committed by
Pieter Wuille
parent
330b0f31ee
commit
d846e02372
@@ -13,6 +13,7 @@
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "test/test_bitcoin.h"
|
||||
#include "rpc/server.h"
|
||||
|
||||
#if defined(HAVE_CONSENSUS_LIB)
|
||||
#include "script/bitcoinconsensus.h"
|
||||
@@ -118,7 +119,7 @@ ScriptError_t ParseScriptError(const std::string &name)
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(script_tests, BasicTestingSetup)
|
||||
|
||||
CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey)
|
||||
CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0)
|
||||
{
|
||||
CMutableTransaction txCredit;
|
||||
txCredit.nVersion = 1;
|
||||
@@ -129,7 +130,7 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey)
|
||||
txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0);
|
||||
txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
|
||||
txCredit.vout[0].scriptPubKey = scriptPubKey;
|
||||
txCredit.vout[0].nValue = 0;
|
||||
txCredit.vout[0].nValue = nValue;
|
||||
|
||||
return txCredit;
|
||||
}
|
||||
@@ -148,12 +149,12 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CSc
|
||||
txSpend.vin[0].scriptSig = scriptSig;
|
||||
txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
|
||||
txSpend.vout[0].scriptPubKey = CScript();
|
||||
txSpend.vout[0].nValue = 0;
|
||||
txSpend.vout[0].nValue = txCredit.vout[0].nValue;
|
||||
|
||||
return txSpend;
|
||||
}
|
||||
|
||||
void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, int flags, const std::string& message, int scriptError)
|
||||
void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, int flags, const std::string& message, int scriptError, CAmount nValue = 0)
|
||||
{
|
||||
bool expect = (scriptError == SCRIPT_ERR_OK);
|
||||
if (flags & SCRIPT_VERIFY_CLEANSTACK) {
|
||||
@@ -161,7 +162,7 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript
|
||||
flags |= SCRIPT_VERIFY_WITNESS;
|
||||
}
|
||||
ScriptError err;
|
||||
CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey);
|
||||
CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey, nValue);
|
||||
CMutableTransaction tx = BuildSpendingTransaction(scriptSig, scriptWitness, txCredit);
|
||||
CMutableTransaction tx2 = tx;
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message);
|
||||
@@ -276,6 +277,7 @@ private:
|
||||
std::string comment;
|
||||
int flags;
|
||||
int scriptError;
|
||||
CAmount nValue;
|
||||
|
||||
void DoPush()
|
||||
{
|
||||
@@ -293,7 +295,7 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WITNESS_NONE, int witnessversion = 0) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK)
|
||||
TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WITNESS_NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK), nValue(nValue_)
|
||||
{
|
||||
CScript scriptPubKey = script;
|
||||
if (wm == WITNESS_PKH) {
|
||||
@@ -311,7 +313,7 @@ public:
|
||||
redeemscript = scriptPubKey;
|
||||
scriptPubKey = CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemscript)) << OP_EQUAL;
|
||||
}
|
||||
creditTx = BuildCreditingTransaction(scriptPubKey);
|
||||
creditTx = BuildCreditingTransaction(scriptPubKey, nValue);
|
||||
spendTx = BuildSpendingTransaction(CScript(), CScriptWitness(), creditTx);
|
||||
}
|
||||
|
||||
@@ -346,9 +348,9 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_BASE)
|
||||
TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_BASE, CAmount amount = 0)
|
||||
{
|
||||
uint256 hash = SignatureHash(script, spendTx, 0, nHashType, 0, sigversion);
|
||||
uint256 hash = SignatureHash(script, spendTx, 0, nHashType, amount, sigversion);
|
||||
std::vector<unsigned char> vchSig, r, s;
|
||||
uint32_t iter = 0;
|
||||
do {
|
||||
@@ -364,9 +366,11 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestBuilder& PushWitSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_WITNESS_V0)
|
||||
TestBuilder& PushWitSig(const CKey& key, CAmount amount = -1, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_WITNESS_V0)
|
||||
{
|
||||
return PushSig(key, nHashType, lenR, lenS, sigversion).AsWit();
|
||||
if (amount == -1)
|
||||
amount = nValue;
|
||||
return PushSig(key, nHashType, lenR, lenS, sigversion, amount).AsWit();
|
||||
}
|
||||
|
||||
TestBuilder& Push(const CPubKey& pubkey)
|
||||
@@ -411,7 +415,7 @@ public:
|
||||
{
|
||||
TestBuilder copy = *this; // Make a copy so we can rollback the push.
|
||||
DoPush();
|
||||
DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, scriptWitness, flags, comment, scriptError);
|
||||
DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, scriptWitness, flags, comment, scriptError, nValue);
|
||||
*this = copy;
|
||||
return *this;
|
||||
}
|
||||
@@ -433,6 +437,7 @@ public:
|
||||
for (unsigned i = 0; i < scriptWitness.stack.size(); i++) {
|
||||
wit.push_back(HexStr(scriptWitness.stack[i]));
|
||||
}
|
||||
wit.push_back(ValueFromAmount(nValue));
|
||||
array.push_back(wit);
|
||||
}
|
||||
array.push_back(FormatScript(spendTx.vin[0].scriptSig));
|
||||
@@ -734,17 +739,17 @@ BOOST_AUTO_TEST_CASE(script_build)
|
||||
).PushSig(keys.key0).PushRedeem());
|
||||
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
|
||||
"Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH
|
||||
).PushWitSig(keys.key0).PushWitRedeem());
|
||||
"Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
|
||||
0, 1).PushWitSig(keys.key0).PushWitRedeem());
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
|
||||
"Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH
|
||||
).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit());
|
||||
"Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH,
|
||||
0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit());
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
|
||||
"Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH
|
||||
).PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
|
||||
"Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
|
||||
0, 1).PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
|
||||
"Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH
|
||||
).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem());
|
||||
"Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH,
|
||||
0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem());
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
|
||||
"Basic P2WSH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH
|
||||
).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
|
||||
@@ -769,6 +774,18 @@ BOOST_AUTO_TEST_CASE(script_build)
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
|
||||
"Basic P2SH(P2WPKH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_PKH
|
||||
).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem());
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
|
||||
"Basic P2WSH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH,
|
||||
0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
|
||||
"Basic P2WPKH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH,
|
||||
0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE));
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
|
||||
"Basic P2SH(P2WSH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH,
|
||||
0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
|
||||
"Basic P2SH(P2WPKH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH,
|
||||
0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
|
||||
|
||||
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
|
||||
"P2WPKH with future witness version", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH |
|
||||
@@ -841,20 +858,25 @@ BOOST_AUTO_TEST_CASE(script_json_test)
|
||||
{
|
||||
// Read tests from test/data/script_tests.json
|
||||
// Format is an array of arrays
|
||||
// Inner arrays are [ ["wit"...]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
|
||||
// Inner arrays are [ ["wit"..., nValue]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
|
||||
// ... where scriptSig and scriptPubKey are stringified
|
||||
// scripts.
|
||||
// If a witness is given, then the last value in the array should be the
|
||||
// amount (nValue) to use in the crediting tx
|
||||
UniValue tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests)));
|
||||
|
||||
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
||||
UniValue test = tests[idx];
|
||||
string strTest = test.write();
|
||||
CScriptWitness witness;
|
||||
CAmount nValue = 0;
|
||||
unsigned int pos = 0;
|
||||
if (test.size() > 0 && test[pos].isArray()) {
|
||||
for (unsigned int i = 0; i < test[pos].size(); i++) {
|
||||
unsigned int i=0;
|
||||
for (i = 0; i < test[pos].size()-1; i++) {
|
||||
witness.stack.push_back(ParseHex(test[pos][i].get_str()));
|
||||
}
|
||||
nValue = AmountFromValue(test[pos][i]);
|
||||
pos++;
|
||||
}
|
||||
if (test.size() < 4 + pos) // Allow size > 3; extra stuff ignored (useful for comments)
|
||||
@@ -871,7 +893,7 @@ BOOST_AUTO_TEST_CASE(script_json_test)
|
||||
unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str());
|
||||
int scriptError = ParseScriptError(test[pos++].get_str());
|
||||
|
||||
DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError);
|
||||
DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError, nValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user