14
14
15
15
#include < boost/test/unit_test.hpp>
16
16
17
- std::vector<CTransactionRef> extra_txn ;
17
+ const std::vector<CTransactionRef> empty_extra_txn ;
18
18
19
19
BOOST_FIXTURE_TEST_SUITE (blockencodings_tests, RegTestingSetup)
20
20
21
- static CBlock BuildBlockTestCase() {
22
- CBlock block;
21
+ static CMutableTransaction BuildTransactionTestCase() {
23
22
CMutableTransaction tx;
24
23
tx.vin .resize (1 );
25
24
tx.vin [0 ].scriptSig .resize (10 );
26
25
tx.vout .resize (1 );
27
26
tx.vout [0 ].nValue = 42 ;
27
+ return tx;
28
+ }
29
+
30
+ static CBlock BuildBlockTestCase (FastRandomContext& ctx) {
31
+ CBlock block;
32
+ CMutableTransaction tx = BuildTransactionTestCase ();
28
33
29
34
block.vtx .resize (3 );
30
35
block.vtx [0 ] = MakeTransactionRef (tx);
31
36
block.nVersion = 42 ;
32
- block.hashPrevBlock = InsecureRand256 ();
37
+ block.hashPrevBlock = ctx. rand256 ();
33
38
block.nBits = 0x207fffff ;
34
39
35
- tx.vin [0 ].prevout .hash = Txid::FromUint256 (InsecureRand256 ());
40
+ tx.vin [0 ].prevout .hash = Txid::FromUint256 (ctx. rand256 ());
36
41
tx.vin [0 ].prevout .n = 0 ;
37
42
block.vtx [1 ] = MakeTransactionRef (tx);
38
43
39
44
tx.vin .resize (10 );
40
45
for (size_t i = 0 ; i < tx.vin .size (); i++) {
41
- tx.vin [i].prevout .hash = Txid::FromUint256 (InsecureRand256 ());
46
+ tx.vin [i].prevout .hash = Txid::FromUint256 (ctx. rand256 ());
42
47
tx.vin [i].prevout .n = 0 ;
43
48
}
44
49
block.vtx [2 ] = MakeTransactionRef (tx);
@@ -58,15 +63,16 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
58
63
{
59
64
CTxMemPool& pool = *Assert (m_node.mempool );
60
65
TestMemPoolEntryHelper entry;
61
- CBlock block (BuildBlockTestCase ());
66
+ auto rand_ctx (FastRandomContext (uint256{42 }));
67
+ CBlock block (BuildBlockTestCase (rand_ctx));
62
68
63
69
LOCK2 (cs_main, pool.cs );
64
70
pool.addUnchecked (entry.FromTx (block.vtx [2 ]));
65
71
BOOST_CHECK_EQUAL (pool.get (block.vtx [2 ]->GetHash ()).use_count (), SHARED_TX_OFFSET + 0 );
66
72
67
73
// Do a simple ShortTxIDs RT
68
74
{
69
- CBlockHeaderAndShortTxIDs shortIDs{block};
75
+ CBlockHeaderAndShortTxIDs shortIDs{block, rand_ctx. rand64 () };
70
76
71
77
DataStream stream{};
72
78
stream << shortIDs;
@@ -75,7 +81,7 @@ BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
75
81
stream >> shortIDs2;
76
82
77
83
PartiallyDownloadedBlock partialBlock (&pool);
78
- BOOST_CHECK (partialBlock.InitData (shortIDs2, extra_txn ) == READ_STATUS_OK);
84
+ BOOST_CHECK (partialBlock.InitData (shortIDs2, empty_extra_txn ) == READ_STATUS_OK);
79
85
BOOST_CHECK ( partialBlock.IsTxAvailable (0 ));
80
86
BOOST_CHECK (!partialBlock.IsTxAvailable (1 ));
81
87
BOOST_CHECK ( partialBlock.IsTxAvailable (2 ));
@@ -123,8 +129,8 @@ class TestHeaderAndShortIDs {
123
129
stream << orig;
124
130
stream >> *this ;
125
131
}
126
- explicit TestHeaderAndShortIDs (const CBlock& block) :
127
- TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs{block}) {}
132
+ explicit TestHeaderAndShortIDs (const CBlock& block, FastRandomContext& ctx ) :
133
+ TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs{block, ctx. rand64 () }) {}
128
134
129
135
uint64_t GetShortID (const Wtxid& txhash) const {
130
136
DataStream stream{};
@@ -141,7 +147,8 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
141
147
{
142
148
CTxMemPool& pool = *Assert (m_node.mempool );
143
149
TestMemPoolEntryHelper entry;
144
- CBlock block (BuildBlockTestCase ());
150
+ auto rand_ctx (FastRandomContext (uint256{42 }));
151
+ CBlock block (BuildBlockTestCase (rand_ctx));
145
152
146
153
LOCK2 (cs_main, pool.cs );
147
154
pool.addUnchecked (entry.FromTx (block.vtx [2 ]));
@@ -151,7 +158,7 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
151
158
152
159
// Test with pre-forwarding tx 1, but not coinbase
153
160
{
154
- TestHeaderAndShortIDs shortIDs (block);
161
+ TestHeaderAndShortIDs shortIDs (block, rand_ctx );
155
162
shortIDs.prefilledtxn .resize (1 );
156
163
shortIDs.prefilledtxn [0 ] = {1 , block.vtx [1 ]};
157
164
shortIDs.shorttxids .resize (2 );
@@ -165,7 +172,7 @@ BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
165
172
stream >> shortIDs2;
166
173
167
174
PartiallyDownloadedBlock partialBlock (&pool);
168
- BOOST_CHECK (partialBlock.InitData (shortIDs2, extra_txn ) == READ_STATUS_OK);
175
+ BOOST_CHECK (partialBlock.InitData (shortIDs2, empty_extra_txn ) == READ_STATUS_OK);
169
176
BOOST_CHECK (!partialBlock.IsTxAvailable (0 ));
170
177
BOOST_CHECK ( partialBlock.IsTxAvailable (1 ));
171
178
BOOST_CHECK ( partialBlock.IsTxAvailable (2 ));
@@ -211,7 +218,8 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
211
218
{
212
219
CTxMemPool& pool = *Assert (m_node.mempool );
213
220
TestMemPoolEntryHelper entry;
214
- CBlock block (BuildBlockTestCase ());
221
+ auto rand_ctx (FastRandomContext (uint256{42 }));
222
+ CBlock block (BuildBlockTestCase (rand_ctx));
215
223
216
224
LOCK2 (cs_main, pool.cs );
217
225
pool.addUnchecked (entry.FromTx (block.vtx [1 ]));
@@ -221,7 +229,7 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
221
229
222
230
// Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool
223
231
{
224
- TestHeaderAndShortIDs shortIDs (block);
232
+ TestHeaderAndShortIDs shortIDs (block, rand_ctx );
225
233
shortIDs.prefilledtxn .resize (2 );
226
234
shortIDs.prefilledtxn [0 ] = {0 , block.vtx [0 ]};
227
235
shortIDs.prefilledtxn [1 ] = {1 , block.vtx [2 ]}; // id == 1 as it is 1 after index 1
@@ -235,7 +243,7 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
235
243
stream >> shortIDs2;
236
244
237
245
PartiallyDownloadedBlock partialBlock (&pool);
238
- BOOST_CHECK (partialBlock.InitData (shortIDs2, extra_txn ) == READ_STATUS_OK);
246
+ BOOST_CHECK (partialBlock.InitData (shortIDs2, empty_extra_txn ) == READ_STATUS_OK);
239
247
BOOST_CHECK ( partialBlock.IsTxAvailable (0 ));
240
248
BOOST_CHECK ( partialBlock.IsTxAvailable (1 ));
241
249
BOOST_CHECK ( partialBlock.IsTxAvailable (2 ));
@@ -261,17 +269,14 @@ BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
261
269
BOOST_AUTO_TEST_CASE (EmptyBlockRoundTripTest)
262
270
{
263
271
CTxMemPool& pool = *Assert (m_node.mempool );
264
- CMutableTransaction coinbase;
265
- coinbase.vin .resize (1 );
266
- coinbase.vin [0 ].scriptSig .resize (10 );
267
- coinbase.vout .resize (1 );
268
- coinbase.vout [0 ].nValue = 42 ;
272
+ CMutableTransaction coinbase = BuildTransactionTestCase ();
269
273
270
274
CBlock block;
275
+ auto rand_ctx (FastRandomContext (uint256{42 }));
271
276
block.vtx .resize (1 );
272
277
block.vtx [0 ] = MakeTransactionRef (std::move (coinbase));
273
278
block.nVersion = 42 ;
274
- block.hashPrevBlock = InsecureRand256 ();
279
+ block.hashPrevBlock = rand_ctx. rand256 ();
275
280
block.nBits = 0x207fffff ;
276
281
277
282
bool mutated;
@@ -281,7 +286,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
281
286
282
287
// Test simple header round-trip with only coinbase
283
288
{
284
- CBlockHeaderAndShortTxIDs shortIDs{block};
289
+ CBlockHeaderAndShortTxIDs shortIDs{block, rand_ctx. rand64 () };
285
290
286
291
DataStream stream{};
287
292
stream << shortIDs;
@@ -290,7 +295,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
290
295
stream >> shortIDs2;
291
296
292
297
PartiallyDownloadedBlock partialBlock (&pool);
293
- BOOST_CHECK (partialBlock.InitData (shortIDs2, extra_txn ) == READ_STATUS_OK);
298
+ BOOST_CHECK (partialBlock.InitData (shortIDs2, empty_extra_txn ) == READ_STATUS_OK);
294
299
BOOST_CHECK (partialBlock.IsTxAvailable (0 ));
295
300
296
301
CBlock block2;
@@ -302,6 +307,53 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
302
307
}
303
308
}
304
309
310
+ BOOST_AUTO_TEST_CASE (ReceiveWithExtraTransactions) {
311
+ CTxMemPool& pool = *Assert (m_node.mempool );
312
+ TestMemPoolEntryHelper entry;
313
+ auto rand_ctx (FastRandomContext (uint256{42 }));
314
+
315
+ CMutableTransaction mtx = BuildTransactionTestCase ();
316
+ mtx.vin [0 ].prevout .hash = Txid::FromUint256 (rand_ctx.rand256 ());
317
+ mtx.vin [0 ].prevout .n = 0 ;
318
+ const CTransactionRef non_block_tx = MakeTransactionRef (std::move (mtx));
319
+
320
+ CBlock block (BuildBlockTestCase (rand_ctx));
321
+ std::vector<CTransactionRef> extra_txn;
322
+ extra_txn.resize (10 );
323
+
324
+ LOCK2 (cs_main, pool.cs );
325
+ pool.addUnchecked (entry.FromTx (block.vtx [2 ]));
326
+ BOOST_CHECK_EQUAL (pool.get (block.vtx [2 ]->GetHash ()).use_count (), SHARED_TX_OFFSET + 0 );
327
+ // Ensure the non_block_tx is actually not in the block
328
+ for (const auto &block_tx : block.vtx ) {
329
+ BOOST_CHECK_NE (block_tx->GetHash (), non_block_tx->GetHash ());
330
+ }
331
+ // Ensure block.vtx[1] is not in pool
332
+ BOOST_CHECK_EQUAL (pool.get (block.vtx [1 ]->GetHash ()), nullptr );
333
+
334
+ {
335
+ const CBlockHeaderAndShortTxIDs cmpctblock{block, rand_ctx.rand64 ()};
336
+ PartiallyDownloadedBlock partial_block (&pool);
337
+ PartiallyDownloadedBlock partial_block_with_extra (&pool);
338
+
339
+ BOOST_CHECK (partial_block.InitData (cmpctblock, extra_txn) == READ_STATUS_OK);
340
+ BOOST_CHECK ( partial_block.IsTxAvailable (0 ));
341
+ BOOST_CHECK (!partial_block.IsTxAvailable (1 ));
342
+ BOOST_CHECK ( partial_block.IsTxAvailable (2 ));
343
+
344
+ // Add an unrelated tx to extra_txn:
345
+ extra_txn[0 ] = non_block_tx;
346
+ // and a tx from the block that's not in the mempool:
347
+ extra_txn[1 ] = block.vtx [1 ];
348
+
349
+ BOOST_CHECK (partial_block_with_extra.InitData (cmpctblock, extra_txn) == READ_STATUS_OK);
350
+ BOOST_CHECK (partial_block_with_extra.IsTxAvailable (0 ));
351
+ // This transaction is now available via extra_txn:
352
+ BOOST_CHECK (partial_block_with_extra.IsTxAvailable (1 ));
353
+ BOOST_CHECK (partial_block_with_extra.IsTxAvailable (2 ));
354
+ }
355
+ }
356
+
305
357
BOOST_AUTO_TEST_CASE (TransactionsRequestSerializationTest) {
306
358
BlockTransactionsRequest req1;
307
359
req1.blockhash = InsecureRand256 ();
0 commit comments