1 // Copyright (c) 2011-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #include "consensus/validation.h"
7 #include "validation.h"
10 #include "txmempool.h"
12 #include "script/standard.h"
13 #include "test/test_bitcoin.h"
16 #include <boost/test/unit_test.hpp>
18 BOOST_AUTO_TEST_SUITE(tx_validationcache_tests
)
21 ToMemPool(CMutableTransaction
& tx
)
25 CValidationState state
;
26 return AcceptToMemoryPool(mempool
, state
, MakeTransactionRef(tx
), false, NULL
, NULL
, true, 0);
29 BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend
, TestChain100Setup
)
31 // Make sure skipping validation of transctions that were
32 // validated going into the memory pool does not allow
33 // double-spends in blocks to pass validation when they should not.
35 CScript scriptPubKey
= CScript() << ToByteVector(coinbaseKey
.GetPubKey()) << OP_CHECKSIG
;
37 // Create a double-spend of mature coinbase txn:
38 std::vector
<CMutableTransaction
> spends
;
40 for (int i
= 0; i
< 2; i
++)
42 spends
[i
].nVersion
= 1;
43 spends
[i
].vin
.resize(1);
44 spends
[i
].vin
[0].prevout
.hash
= coinbaseTxns
[0].GetHash();
45 spends
[i
].vin
[0].prevout
.n
= 0;
46 spends
[i
].vout
.resize(1);
47 spends
[i
].vout
[0].nValue
= 11*CENT
;
48 spends
[i
].vout
[0].scriptPubKey
= scriptPubKey
;
51 std::vector
<unsigned char> vchSig
;
52 uint256 hash
= SignatureHash(scriptPubKey
, spends
[i
], 0, SIGHASH_ALL
, 0, SIGVERSION_BASE
);
53 BOOST_CHECK(coinbaseKey
.Sign(hash
, vchSig
));
54 vchSig
.push_back((unsigned char)SIGHASH_ALL
);
55 spends
[i
].vin
[0].scriptSig
<< vchSig
;
60 // Test 1: block with both of those transactions should be rejected.
61 block
= CreateAndProcessBlock(spends
, scriptPubKey
);
62 BOOST_CHECK(chainActive
.Tip()->GetBlockHash() != block
.GetHash());
64 // Test 2: ... and should be rejected if spend1 is in the memory pool
65 BOOST_CHECK(ToMemPool(spends
[0]));
66 block
= CreateAndProcessBlock(spends
, scriptPubKey
);
67 BOOST_CHECK(chainActive
.Tip()->GetBlockHash() != block
.GetHash());
70 // Test 3: ... and should be rejected if spend2 is in the memory pool
71 BOOST_CHECK(ToMemPool(spends
[1]));
72 block
= CreateAndProcessBlock(spends
, scriptPubKey
);
73 BOOST_CHECK(chainActive
.Tip()->GetBlockHash() != block
.GetHash());
76 // Final sanity test: first spend in mempool, second in block, that's OK:
77 std::vector
<CMutableTransaction
> oneSpend
;
78 oneSpend
.push_back(spends
[0]);
79 BOOST_CHECK(ToMemPool(spends
[1]));
80 block
= CreateAndProcessBlock(oneSpend
, scriptPubKey
);
81 BOOST_CHECK(chainActive
.Tip()->GetBlockHash() == block
.GetHash());
82 // spends[1] should have been removed from the mempool when the
83 // block with spends[0] is accepted:
84 BOOST_CHECK_EQUAL(mempool
.size(), 0);
87 BOOST_AUTO_TEST_SUITE_END()