Use the variable name _ for unused return values
[bitcoinplatinum.git] / src / test / blockencodings_tests.cpp
blobf2d5b385d078fdd451eee44167d5b80d3f5c9527
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 "blockencodings.h"
6 #include "consensus/merkle.h"
7 #include "chainparams.h"
8 #include "random.h"
10 #include "test/test_bitcoin.h"
12 #include <boost/test/unit_test.hpp>
14 std::vector<std::pair<uint256, CTransactionRef>> extra_txn;
16 struct RegtestingSetup : public TestingSetup {
17 RegtestingSetup() : TestingSetup(CBaseChainParams::REGTEST) {}
20 BOOST_FIXTURE_TEST_SUITE(blockencodings_tests, RegtestingSetup)
22 static CBlock BuildBlockTestCase() {
23 CBlock block;
24 CMutableTransaction tx;
25 tx.vin.resize(1);
26 tx.vin[0].scriptSig.resize(10);
27 tx.vout.resize(1);
28 tx.vout[0].nValue = 42;
30 block.vtx.resize(3);
31 block.vtx[0] = MakeTransactionRef(tx);
32 block.nVersion = 42;
33 block.hashPrevBlock = InsecureRand256();
34 block.nBits = 0x207fffff;
36 tx.vin[0].prevout.hash = InsecureRand256();
37 tx.vin[0].prevout.n = 0;
38 block.vtx[1] = MakeTransactionRef(tx);
40 tx.vin.resize(10);
41 for (size_t i = 0; i < tx.vin.size(); i++) {
42 tx.vin[i].prevout.hash = InsecureRand256();
43 tx.vin[i].prevout.n = 0;
45 block.vtx[2] = MakeTransactionRef(tx);
47 bool mutated;
48 block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
49 assert(!mutated);
50 while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
51 return block;
54 // Number of shared use_counts we expect for a tx we haven't touched
55 // == 2 (mempool + our copy from the GetSharedTx call)
56 #define SHARED_TX_OFFSET 2
58 BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
60 CTxMemPool pool;
61 TestMemPoolEntryHelper entry;
62 CBlock block(BuildBlockTestCase());
64 pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(*block.vtx[2]));
65 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
67 // Do a simple ShortTxIDs RT
69 CBlockHeaderAndShortTxIDs shortIDs(block, true);
71 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
72 stream << shortIDs;
74 CBlockHeaderAndShortTxIDs shortIDs2;
75 stream >> shortIDs2;
77 PartiallyDownloadedBlock partialBlock(&pool);
78 BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
79 BOOST_CHECK( partialBlock.IsTxAvailable(0));
80 BOOST_CHECK(!partialBlock.IsTxAvailable(1));
81 BOOST_CHECK( partialBlock.IsTxAvailable(2));
83 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
85 size_t poolSize = pool.size();
86 pool.removeRecursive(*block.vtx[2]);
87 BOOST_CHECK_EQUAL(pool.size(), poolSize - 1);
89 CBlock block2;
91 PartiallyDownloadedBlock tmp = partialBlock;
92 BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
93 partialBlock = tmp;
96 // Wrong transaction
98 PartiallyDownloadedBlock tmp = partialBlock;
99 partialBlock.FillBlock(block2, {block.vtx[2]}); // Current implementation doesn't check txn here, but don't require that
100 partialBlock = tmp;
102 bool mutated;
103 BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated));
105 CBlock block3;
106 BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[1]}) == READ_STATUS_OK);
107 BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
108 BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
109 BOOST_CHECK(!mutated);
113 class TestHeaderAndShortIDs {
114 // Utility to encode custom CBlockHeaderAndShortTxIDs
115 public:
116 CBlockHeader header;
117 uint64_t nonce;
118 std::vector<uint64_t> shorttxids;
119 std::vector<PrefilledTransaction> prefilledtxn;
121 explicit TestHeaderAndShortIDs(const CBlockHeaderAndShortTxIDs& orig) {
122 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
123 stream << orig;
124 stream >> *this;
126 explicit TestHeaderAndShortIDs(const CBlock& block) :
127 TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs(block, true)) {}
129 uint64_t GetShortID(const uint256& txhash) const {
130 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
131 stream << *this;
132 CBlockHeaderAndShortTxIDs base;
133 stream >> base;
134 return base.GetShortID(txhash);
137 ADD_SERIALIZE_METHODS;
139 template <typename Stream, typename Operation>
140 inline void SerializationOp(Stream& s, Operation ser_action) {
141 READWRITE(header);
142 READWRITE(nonce);
143 size_t shorttxids_size = shorttxids.size();
144 READWRITE(VARINT(shorttxids_size));
145 shorttxids.resize(shorttxids_size);
146 for (size_t i = 0; i < shorttxids.size(); i++) {
147 uint32_t lsb = shorttxids[i] & 0xffffffff;
148 uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
149 READWRITE(lsb);
150 READWRITE(msb);
151 shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
153 READWRITE(prefilledtxn);
157 BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
159 CTxMemPool pool;
160 TestMemPoolEntryHelper entry;
161 CBlock block(BuildBlockTestCase());
163 pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(*block.vtx[2]));
164 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
166 uint256 txhash;
168 // Test with pre-forwarding tx 1, but not coinbase
170 TestHeaderAndShortIDs shortIDs(block);
171 shortIDs.prefilledtxn.resize(1);
172 shortIDs.prefilledtxn[0] = {1, block.vtx[1]};
173 shortIDs.shorttxids.resize(2);
174 shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[0]->GetHash());
175 shortIDs.shorttxids[1] = shortIDs.GetShortID(block.vtx[2]->GetHash());
177 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
178 stream << shortIDs;
180 CBlockHeaderAndShortTxIDs shortIDs2;
181 stream >> shortIDs2;
183 PartiallyDownloadedBlock partialBlock(&pool);
184 BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
185 BOOST_CHECK(!partialBlock.IsTxAvailable(0));
186 BOOST_CHECK( partialBlock.IsTxAvailable(1));
187 BOOST_CHECK( partialBlock.IsTxAvailable(2));
189 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
191 CBlock block2;
193 PartiallyDownloadedBlock tmp = partialBlock;
194 BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
195 partialBlock = tmp;
198 // Wrong transaction
200 PartiallyDownloadedBlock tmp = partialBlock;
201 partialBlock.FillBlock(block2, {block.vtx[1]}); // Current implementation doesn't check txn here, but don't require that
202 partialBlock = tmp;
204 bool mutated;
205 BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated));
207 CBlock block3;
208 PartiallyDownloadedBlock partialBlockCopy = partialBlock;
209 BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[0]}) == READ_STATUS_OK);
210 BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
211 BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
212 BOOST_CHECK(!mutated);
214 txhash = block.vtx[2]->GetHash();
215 block.vtx.clear();
216 block2.vtx.clear();
217 block3.vtx.clear();
218 BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); // + 1 because of partialBlockCopy.
220 BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
223 BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
225 CTxMemPool pool;
226 TestMemPoolEntryHelper entry;
227 CBlock block(BuildBlockTestCase());
229 pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(*block.vtx[1]));
230 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
232 uint256 txhash;
234 // Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool
236 TestHeaderAndShortIDs shortIDs(block);
237 shortIDs.prefilledtxn.resize(2);
238 shortIDs.prefilledtxn[0] = {0, block.vtx[0]};
239 shortIDs.prefilledtxn[1] = {1, block.vtx[2]}; // id == 1 as it is 1 after index 1
240 shortIDs.shorttxids.resize(1);
241 shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[1]->GetHash());
243 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
244 stream << shortIDs;
246 CBlockHeaderAndShortTxIDs shortIDs2;
247 stream >> shortIDs2;
249 PartiallyDownloadedBlock partialBlock(&pool);
250 BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
251 BOOST_CHECK( partialBlock.IsTxAvailable(0));
252 BOOST_CHECK( partialBlock.IsTxAvailable(1));
253 BOOST_CHECK( partialBlock.IsTxAvailable(2));
255 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
257 CBlock block2;
258 PartiallyDownloadedBlock partialBlockCopy = partialBlock;
259 BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_OK);
260 BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
261 bool mutated;
262 BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
263 BOOST_CHECK(!mutated);
265 txhash = block.vtx[1]->GetHash();
266 block.vtx.clear();
267 block2.vtx.clear();
268 BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); // + 1 because of partialBlockCopy.
270 BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
273 BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
275 CTxMemPool pool;
276 CMutableTransaction coinbase;
277 coinbase.vin.resize(1);
278 coinbase.vin[0].scriptSig.resize(10);
279 coinbase.vout.resize(1);
280 coinbase.vout[0].nValue = 42;
282 CBlock block;
283 block.vtx.resize(1);
284 block.vtx[0] = MakeTransactionRef(std::move(coinbase));
285 block.nVersion = 42;
286 block.hashPrevBlock = InsecureRand256();
287 block.nBits = 0x207fffff;
289 bool mutated;
290 block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
291 assert(!mutated);
292 while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
294 // Test simple header round-trip with only coinbase
296 CBlockHeaderAndShortTxIDs shortIDs(block, false);
298 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
299 stream << shortIDs;
301 CBlockHeaderAndShortTxIDs shortIDs2;
302 stream >> shortIDs2;
304 PartiallyDownloadedBlock partialBlock(&pool);
305 BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
306 BOOST_CHECK(partialBlock.IsTxAvailable(0));
308 CBlock block2;
309 std::vector<CTransactionRef> vtx_missing;
310 BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK);
311 BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
312 BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
313 BOOST_CHECK(!mutated);
317 BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) {
318 BlockTransactionsRequest req1;
319 req1.blockhash = InsecureRand256();
320 req1.indexes.resize(4);
321 req1.indexes[0] = 0;
322 req1.indexes[1] = 1;
323 req1.indexes[2] = 3;
324 req1.indexes[3] = 4;
326 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
327 stream << req1;
329 BlockTransactionsRequest req2;
330 stream >> req2;
332 BOOST_CHECK_EQUAL(req1.blockhash.ToString(), req2.blockhash.ToString());
333 BOOST_CHECK_EQUAL(req1.indexes.size(), req2.indexes.size());
334 BOOST_CHECK_EQUAL(req1.indexes[0], req2.indexes[0]);
335 BOOST_CHECK_EQUAL(req1.indexes[1], req2.indexes[1]);
336 BOOST_CHECK_EQUAL(req1.indexes[2], req2.indexes[2]);
337 BOOST_CHECK_EQUAL(req1.indexes[3], req2.indexes[3]);
340 BOOST_AUTO_TEST_SUITE_END()