Merge #12001: [RPC] Adding ::minRelayTxFee amount to getmempoolinfo and updating...
[bitcoinplatinum.git] / src / test / blockencodings_tests.cpp
blob32330e0548e9373ca0d32121c9833651ebd5145d
1 // Copyright (c) 2011-2017 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 LOCK(pool.cs);
66 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
68 // Do a simple ShortTxIDs RT
70 CBlockHeaderAndShortTxIDs shortIDs(block, true);
72 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
73 stream << shortIDs;
75 CBlockHeaderAndShortTxIDs shortIDs2;
76 stream >> shortIDs2;
78 PartiallyDownloadedBlock partialBlock(&pool);
79 BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
80 BOOST_CHECK( partialBlock.IsTxAvailable(0));
81 BOOST_CHECK(!partialBlock.IsTxAvailable(1));
82 BOOST_CHECK( partialBlock.IsTxAvailable(2));
84 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
86 size_t poolSize = pool.size();
87 pool.removeRecursive(*block.vtx[2]);
88 BOOST_CHECK_EQUAL(pool.size(), poolSize - 1);
90 CBlock block2;
92 PartiallyDownloadedBlock tmp = partialBlock;
93 BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
94 partialBlock = tmp;
97 // Wrong transaction
99 PartiallyDownloadedBlock tmp = partialBlock;
100 partialBlock.FillBlock(block2, {block.vtx[2]}); // Current implementation doesn't check txn here, but don't require that
101 partialBlock = tmp;
103 bool mutated;
104 BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated));
106 CBlock block3;
107 BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[1]}) == READ_STATUS_OK);
108 BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
109 BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
110 BOOST_CHECK(!mutated);
114 class TestHeaderAndShortIDs {
115 // Utility to encode custom CBlockHeaderAndShortTxIDs
116 public:
117 CBlockHeader header;
118 uint64_t nonce;
119 std::vector<uint64_t> shorttxids;
120 std::vector<PrefilledTransaction> prefilledtxn;
122 explicit TestHeaderAndShortIDs(const CBlockHeaderAndShortTxIDs& orig) {
123 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
124 stream << orig;
125 stream >> *this;
127 explicit TestHeaderAndShortIDs(const CBlock& block) :
128 TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs(block, true)) {}
130 uint64_t GetShortID(const uint256& txhash) const {
131 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
132 stream << *this;
133 CBlockHeaderAndShortTxIDs base;
134 stream >> base;
135 return base.GetShortID(txhash);
138 ADD_SERIALIZE_METHODS;
140 template <typename Stream, typename Operation>
141 inline void SerializationOp(Stream& s, Operation ser_action) {
142 READWRITE(header);
143 READWRITE(nonce);
144 size_t shorttxids_size = shorttxids.size();
145 READWRITE(VARINT(shorttxids_size));
146 shorttxids.resize(shorttxids_size);
147 for (size_t i = 0; i < shorttxids.size(); i++) {
148 uint32_t lsb = shorttxids[i] & 0xffffffff;
149 uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
150 READWRITE(lsb);
151 READWRITE(msb);
152 shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
154 READWRITE(prefilledtxn);
158 BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
160 CTxMemPool pool;
161 TestMemPoolEntryHelper entry;
162 CBlock block(BuildBlockTestCase());
164 pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(*block.vtx[2]));
165 LOCK(pool.cs);
166 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
168 uint256 txhash;
170 // Test with pre-forwarding tx 1, but not coinbase
172 TestHeaderAndShortIDs shortIDs(block);
173 shortIDs.prefilledtxn.resize(1);
174 shortIDs.prefilledtxn[0] = {1, block.vtx[1]};
175 shortIDs.shorttxids.resize(2);
176 shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[0]->GetHash());
177 shortIDs.shorttxids[1] = shortIDs.GetShortID(block.vtx[2]->GetHash());
179 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
180 stream << shortIDs;
182 CBlockHeaderAndShortTxIDs shortIDs2;
183 stream >> shortIDs2;
185 PartiallyDownloadedBlock partialBlock(&pool);
186 BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
187 BOOST_CHECK(!partialBlock.IsTxAvailable(0));
188 BOOST_CHECK( partialBlock.IsTxAvailable(1));
189 BOOST_CHECK( partialBlock.IsTxAvailable(2));
191 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
193 CBlock block2;
195 PartiallyDownloadedBlock tmp = partialBlock;
196 BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
197 partialBlock = tmp;
200 // Wrong transaction
202 PartiallyDownloadedBlock tmp = partialBlock;
203 partialBlock.FillBlock(block2, {block.vtx[1]}); // Current implementation doesn't check txn here, but don't require that
204 partialBlock = tmp;
206 bool mutated;
207 BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated));
209 CBlock block3;
210 PartiallyDownloadedBlock partialBlockCopy = partialBlock;
211 BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[0]}) == READ_STATUS_OK);
212 BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
213 BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
214 BOOST_CHECK(!mutated);
216 txhash = block.vtx[2]->GetHash();
217 block.vtx.clear();
218 block2.vtx.clear();
219 block3.vtx.clear();
220 BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); // + 1 because of partialBlockCopy.
222 BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
225 BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
227 CTxMemPool pool;
228 TestMemPoolEntryHelper entry;
229 CBlock block(BuildBlockTestCase());
231 pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(*block.vtx[1]));
232 LOCK(pool.cs);
233 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
235 uint256 txhash;
237 // Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool
239 TestHeaderAndShortIDs shortIDs(block);
240 shortIDs.prefilledtxn.resize(2);
241 shortIDs.prefilledtxn[0] = {0, block.vtx[0]};
242 shortIDs.prefilledtxn[1] = {1, block.vtx[2]}; // id == 1 as it is 1 after index 1
243 shortIDs.shorttxids.resize(1);
244 shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[1]->GetHash());
246 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
247 stream << shortIDs;
249 CBlockHeaderAndShortTxIDs shortIDs2;
250 stream >> shortIDs2;
252 PartiallyDownloadedBlock partialBlock(&pool);
253 BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
254 BOOST_CHECK( partialBlock.IsTxAvailable(0));
255 BOOST_CHECK( partialBlock.IsTxAvailable(1));
256 BOOST_CHECK( partialBlock.IsTxAvailable(2));
258 BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
260 CBlock block2;
261 PartiallyDownloadedBlock partialBlockCopy = partialBlock;
262 BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_OK);
263 BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
264 bool mutated;
265 BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
266 BOOST_CHECK(!mutated);
268 txhash = block.vtx[1]->GetHash();
269 block.vtx.clear();
270 block2.vtx.clear();
271 BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); // + 1 because of partialBlockCopy.
273 BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
276 BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
278 CTxMemPool pool;
279 CMutableTransaction coinbase;
280 coinbase.vin.resize(1);
281 coinbase.vin[0].scriptSig.resize(10);
282 coinbase.vout.resize(1);
283 coinbase.vout[0].nValue = 42;
285 CBlock block;
286 block.vtx.resize(1);
287 block.vtx[0] = MakeTransactionRef(std::move(coinbase));
288 block.nVersion = 42;
289 block.hashPrevBlock = InsecureRand256();
290 block.nBits = 0x207fffff;
292 bool mutated;
293 block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
294 assert(!mutated);
295 while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
297 // Test simple header round-trip with only coinbase
299 CBlockHeaderAndShortTxIDs shortIDs(block, false);
301 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
302 stream << shortIDs;
304 CBlockHeaderAndShortTxIDs shortIDs2;
305 stream >> shortIDs2;
307 PartiallyDownloadedBlock partialBlock(&pool);
308 BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
309 BOOST_CHECK(partialBlock.IsTxAvailable(0));
311 CBlock block2;
312 std::vector<CTransactionRef> vtx_missing;
313 BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK);
314 BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
315 BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
316 BOOST_CHECK(!mutated);
320 BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) {
321 BlockTransactionsRequest req1;
322 req1.blockhash = InsecureRand256();
323 req1.indexes.resize(4);
324 req1.indexes[0] = 0;
325 req1.indexes[1] = 1;
326 req1.indexes[2] = 3;
327 req1.indexes[3] = 4;
329 CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
330 stream << req1;
332 BlockTransactionsRequest req2;
333 stream >> req2;
335 BOOST_CHECK_EQUAL(req1.blockhash.ToString(), req2.blockhash.ToString());
336 BOOST_CHECK_EQUAL(req1.indexes.size(), req2.indexes.size());
337 BOOST_CHECK_EQUAL(req1.indexes[0], req2.indexes[0]);
338 BOOST_CHECK_EQUAL(req1.indexes[1], req2.indexes[1]);
339 BOOST_CHECK_EQUAL(req1.indexes[2], req2.indexes[2]);
340 BOOST_CHECK_EQUAL(req1.indexes[3], req2.indexes[3]);
343 BOOST_AUTO_TEST_SUITE_END()