| 27 | BOOST_AUTO_TEST_SUITE(txvalidationcache_tests) |
| 28 | |
| 29 | BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, Dersig100Setup) |
| 30 | { |
| 31 | // Make sure skipping validation of transactions that were |
| 32 | // validated going into the memory pool does not allow |
| 33 | // double-spends in blocks to pass validation when they should not. |
| 34 | |
| 35 | CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG; |
| 36 | |
| 37 | const auto ToMemPool = [this](const CMutableTransaction& tx) { |
| 38 | LOCK(cs_main); |
| 39 | |
| 40 | const MempoolAcceptResult result = m_node.chainman->ProcessTransaction(MakeTransactionRef(tx)); |
| 41 | return result.m_result_type == MempoolAcceptResult::ResultType::VALID; |
| 42 | }; |
| 43 | |
| 44 | // Create a double-spend of mature coinbase txn: |
| 45 | std::vector<CMutableTransaction> spends; |
| 46 | spends.resize(2); |
| 47 | for (int i = 0; i < 2; i++) |
| 48 | { |
| 49 | spends[i].nVersion = 1; |
| 50 | spends[i].vin.resize(1); |
| 51 | spends[i].vin[0].prevout.hash = m_coinbase_txns[0]->GetHash(); |
| 52 | spends[i].vin[0].prevout.n = 0; |
| 53 | spends[i].vout.resize(1); |
| 54 | spends[i].vout[0].nValue = 11*CENT; |
| 55 | spends[i].vout[0].scriptPubKey = scriptPubKey; |
| 56 | |
| 57 | // Sign: |
| 58 | std::vector<unsigned char> vchSig; |
| 59 | uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SigVersion::BASE, 0); |
| 60 | BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); |
| 61 | vchSig.push_back((unsigned char)SIGHASH_ALL); |
| 62 | spends[i].vin[0].scriptSig << vchSig; |
| 63 | } |
| 64 | |
| 65 | CBlock block; |
| 66 | |
| 67 | // Test 1: block with both of those transactions should be rejected. |
| 68 | block = CreateAndProcessBlock(spends, scriptPubKey); |
| 69 | { |
| 70 | LOCK(cs_main); |
| 71 | BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash()); |
| 72 | } |
| 73 | |
| 74 | // Test 2: ... and should be rejected if spend1 is in the memory pool |
| 75 | BOOST_CHECK(ToMemPool(spends[0])); |
| 76 | block = CreateAndProcessBlock(spends, scriptPubKey); |
| 77 | { |
| 78 | LOCK(cs_main); |
| 79 | BOOST_CHECK(m_node.chainman->ActiveChain().Tip()->GetBlockHash() != block.GetHash()); |
| 80 | } |
| 81 | m_node.mempool->clear(); |
| 82 | |
| 83 | // Test 3: ... and should be rejected if spend2 is in the memory pool |
| 84 | BOOST_CHECK(ToMemPool(spends[1])); |
| 85 | block = CreateAndProcessBlock(spends, scriptPubKey); |
| 86 | { |
nothing calls this directly
no test coverage detected