Changeset View
Changeset View
Standalone View
Standalone View
src/test/txvalidationcache_tests.cpp
Show First 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | void ValidateCheckInputsForAllFlags(const CMutableTransaction &mutableTx, | ||||
// rewrite in the future to randomly pick a set of flags to evaluate. | // rewrite in the future to randomly pick a set of flags to evaluate. | ||||
for (uint32_t test_flags = 0; test_flags < (1U << 17); test_flags += 1) { | for (uint32_t test_flags = 0; test_flags < (1U << 17); test_flags += 1) { | ||||
CValidationState state; | CValidationState state; | ||||
// Make sure the mandatory flags are enabled. | // Make sure the mandatory flags are enabled. | ||||
test_flags |= MANDATORY_SCRIPT_VERIFY_FLAGS; | test_flags |= MANDATORY_SCRIPT_VERIFY_FLAGS; | ||||
bool ret = CheckInputs(tx, state, pcoinsTip.get(), true, test_flags, | bool ret = CheckInputs(tx, state, pcoinsTip.get(), true, test_flags, | ||||
true, add_to_cache, txdata, nullptr); | true, add_to_cache, txdata, nullptr); | ||||
std::cout << "CheckInputs: " << ret | |||||
<< " Failure: " << state.GetRejectReason(); | |||||
// CheckInputs should succeed iff test_flags doesn't intersect with | // CheckInputs should succeed iff test_flags doesn't intersect with | ||||
// failing_flags | // failing_flags | ||||
bool expected_return_value = !(test_flags & failing_flags); | bool expected_return_value = !(test_flags & failing_flags); | ||||
if (expected_return_value && upgraded_nop) { | if (expected_return_value && upgraded_nop) { | ||||
// If the script flag being tested corresponds to an upgraded NOP, | // If the script flag being tested corresponds to an upgraded NOP, | ||||
// then script execution should fail if DISCOURAGE_UPGRADABLE_NOPS | // then script execution should fail if DISCOURAGE_UPGRADABLE_NOPS | ||||
// is set. | // is set. | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) { | ||||
// pubkey thing | // pubkey thing | ||||
// Create 2 outputs that match the three scripts above, spending the first | // Create 2 outputs that match the three scripts above, spending the first | ||||
// coinbase tx. | // coinbase tx. | ||||
CMutableTransaction mutableSpend_tx; | CMutableTransaction mutableSpend_tx; | ||||
mutableSpend_tx.nVersion = 1; | mutableSpend_tx.nVersion = 1; | ||||
mutableSpend_tx.vin.resize(1); | mutableSpend_tx.vin.resize(1); | ||||
mutableSpend_tx.vin[0].prevout = COutPoint(coinbaseTxns[0].GetId(), 0); | mutableSpend_tx.vin[0].prevout = COutPoint(coinbaseTxns[1].GetId(), 0); | ||||
mutableSpend_tx.vout.resize(4); | mutableSpend_tx.vout.resize(4); | ||||
mutableSpend_tx.vout[0].nValue = 11 * CENT; | mutableSpend_tx.vout[0].nValue = 11 * CENT; | ||||
mutableSpend_tx.vout[0].scriptPubKey = p2sh_scriptPubKey; | mutableSpend_tx.vout[0].scriptPubKey = p2sh_scriptPubKey; | ||||
mutableSpend_tx.vout[1].nValue = 11 * CENT; | mutableSpend_tx.vout[1].nValue = 11 * CENT; | ||||
mutableSpend_tx.vout[1].scriptPubKey = | mutableSpend_tx.vout[1].scriptPubKey = | ||||
CScript() << OP_CHECKLOCKTIMEVERIFY << OP_DROP | CScript() << OP_CHECKLOCKTIMEVERIFY << OP_DROP | ||||
<< ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; | << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; | ||||
mutableSpend_tx.vout[2].nValue = 11 * CENT; | mutableSpend_tx.vout[2].nValue = 11 * CENT; | ||||
mutableSpend_tx.vout[2].scriptPubKey = | mutableSpend_tx.vout[2].scriptPubKey = | ||||
CScript() << OP_CHECKSEQUENCEVERIFY << OP_DROP | CScript() << OP_CHECKSEQUENCEVERIFY << OP_DROP | ||||
<< ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; | << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; | ||||
mutableSpend_tx.vout[3].nValue = 11 * CENT; | mutableSpend_tx.vout[3].nValue = 11 * CENT; | ||||
mutableSpend_tx.vout[3].scriptPubKey = p2sh_scriptPubKey; | mutableSpend_tx.vout[3].scriptPubKey = p2sh_scriptPubKey; | ||||
// Sign, and push an extra element on the stack. | // Sign, and push an extra element on the stack. | ||||
{ | { | ||||
std::vector<uint8_t> vchSig; | std::vector<uint8_t> vchSig; | ||||
uint256 hash = SignatureHash( | uint256 hash = SignatureHash( | ||||
p2pk_scriptPubKey, CTransaction(mutableSpend_tx), 0, | p2pk_scriptPubKey, CTransaction(mutableSpend_tx), 0, | ||||
SigHashType().withForkId(), coinbaseTxns[0].vout[0].nValue); | SigHashType().withForkId(), coinbaseTxns[1].vout[0].nValue); | ||||
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); | BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); | ||||
vchSig.push_back(uint8_t(SIGHASH_ALL | SIGHASH_FORKID)); | vchSig.push_back(uint8_t(SIGHASH_ALL | SIGHASH_FORKID)); | ||||
mutableSpend_tx.vin[0].scriptSig << OP_TRUE << vchSig; | // First item will be dropped by CHECKMULTISIG | ||||
deadalnix: It's the last item. You are pushing onto a stack so the item you push first end up being the… | |||||
// This is to check nulldummy enforcement. It is OP_1 instead of OP_0 | |||||
mutableSpend_tx.vin[0].scriptSig << OP_1 << vchSig; | |||||
} | } | ||||
const CTransaction spend_tx(mutableSpend_tx); | const CTransaction spend_tx(mutableSpend_tx); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// Test that invalidity under a set of flags doesn't preclude validity under | // Test that invalidity under a set of flags doesn't preclude validity under | ||||
// other (eg consensus) flags. | // other (eg consensus) flags. | ||||
// spend_tx is invalid according to DERSIG | // spend_tx is invalid according to DERSIG | ||||
{ | { | ||||
CValidationState state; | CValidationState state; | ||||
PrecomputedTransactionData ptd_spend_tx(spend_tx); | PrecomputedTransactionData ptd_spend_tx(spend_tx); | ||||
BOOST_CHECK(!CheckInputs(spend_tx, state, pcoinsTip.get(), true, | BOOST_CHECK(!CheckInputs(spend_tx, state, pcoinsTip.get(), true, | ||||
MANDATORY_SCRIPT_VERIFY_FLAGS | | MANDATORY_SCRIPT_VERIFY_FLAGS | | ||||
SCRIPT_VERIFY_CLEANSTACK, | SCRIPT_VERIFY_NULLDUMMY, | ||||
true, true, ptd_spend_tx, nullptr)); | true, true, ptd_spend_tx, nullptr)); | ||||
// If we call again asking for scriptchecks (as happens in | // If we call again asking for scriptchecks (as happens in | ||||
// ConnectBlock), we should add a script check object for this -- we're | // ConnectBlock), we should add a script check object for this -- we're | ||||
// not caching invalidity (if that changes, delete this test case). | // not caching invalidity (if that changes, delete this test case). | ||||
std::vector<CScriptCheck> scriptchecks; | std::vector<CScriptCheck> scriptchecks; | ||||
BOOST_CHECK(CheckInputs(spend_tx, state, pcoinsTip.get(), true, | BOOST_CHECK( | ||||
MANDATORY_SCRIPT_VERIFY_FLAGS | | CheckInputs(spend_tx, state, pcoinsTip.get(), true, | ||||
SCRIPT_VERIFY_CLEANSTACK, | MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_NULLDUMMY, | ||||
true, true, ptd_spend_tx, &scriptchecks)); | true, true, ptd_spend_tx, &scriptchecks)); | ||||
BOOST_CHECK_EQUAL(scriptchecks.size(), 1); | BOOST_CHECK_EQUAL(scriptchecks.size(), 1); | ||||
// Test that CheckInputs returns true iff cleanstack-enforcing flags are | // Test that CheckInputs returns true iff cleanstack-enforcing flags are | ||||
// not present. Don't add these checks to the cache, so that we can test | // not present. Don't add these checks to the cache, so that we can test | ||||
// later that block validation works fine in the absence of cached | // later that block validation works fine in the absence of cached | ||||
// successes. | // successes. | ||||
ValidateCheckInputsForAllFlags(spend_tx, SCRIPT_VERIFY_CLEANSTACK, | ValidateCheckInputsForAllFlags(spend_tx, SCRIPT_VERIFY_NULLDUMMY, false, | ||||
false, false); | false); | ||||
// And if we produce a block with this tx, it should be valid (LOW_S not | // And if we produce a block with this tx, it should be valid (LOW_S not | ||||
// enabled yet), even though there's no cache entry. | // enabled yet), even though there's no cache entry. | ||||
CBlock block; | CBlock block; | ||||
block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey); | block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey); | ||||
BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash()); | BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash()); | ||||
BOOST_CHECK(pcoinsTip->GetBestBlock() == block.GetHash()); | BOOST_CHECK(pcoinsTip->GetBestBlock() == block.GetHash()); | ||||
▲ Show 20 Lines • Show All 152 Lines • Show Last 20 Lines |
It's the last item. You are pushing onto a stack so the item you push first end up being the last item on the stack.