Bitcoin Core  27.99.0
P2P Digital Currency
blockencodings_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2022 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.
4 
5 #include <blockencodings.h>
6 #include <chainparams.h>
7 #include <consensus/merkle.h>
8 #include <pow.h>
9 #include <streams.h>
10 #include <test/util/random.h>
11 #include <test/util/txmempool.h>
12 
13 #include <test/util/setup_common.h>
14 
15 #include <boost/test/unit_test.hpp>
16 
17 const std::vector<CTransactionRef> empty_extra_txn;
18 
19 BOOST_FIXTURE_TEST_SUITE(blockencodings_tests, RegTestingSetup)
20 
23  tx.vin.resize(1);
24  tx.vin[0].scriptSig.resize(10);
25  tx.vout.resize(1);
26  tx.vout[0].nValue = 42;
27  return tx;
28 }
29 
31  CBlock block;
33 
34  block.vtx.resize(3);
35  block.vtx[0] = MakeTransactionRef(tx);
36  block.nVersion = 42;
37  block.hashPrevBlock = ctx.rand256();
38  block.nBits = 0x207fffff;
39 
40  tx.vin[0].prevout.hash = Txid::FromUint256(ctx.rand256());
41  tx.vin[0].prevout.n = 0;
42  block.vtx[1] = MakeTransactionRef(tx);
43 
44  tx.vin.resize(10);
45  for (size_t i = 0; i < tx.vin.size(); i++) {
46  tx.vin[i].prevout.hash = Txid::FromUint256(ctx.rand256());
47  tx.vin[i].prevout.n = 0;
48  }
49  block.vtx[2] = MakeTransactionRef(tx);
50 
51  bool mutated;
52  block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
53  assert(!mutated);
54  while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
55  return block;
56 }
57 
58 // Number of shared use_counts we expect for a tx we haven't touched
59 // (block + mempool entry + mempool txns_randomized + our copy from the GetSharedTx call)
60 constexpr long SHARED_TX_OFFSET{4};
61 
62 BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
63 {
64  CTxMemPool& pool = *Assert(m_node.mempool);
66  auto rand_ctx(FastRandomContext(uint256{42}));
67  CBlock block(BuildBlockTestCase(rand_ctx));
68 
69  LOCK2(cs_main, pool.cs);
70  pool.addUnchecked(entry.FromTx(block.vtx[2]));
71  BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
72 
73  // Do a simple ShortTxIDs RT
74  {
75  CBlockHeaderAndShortTxIDs shortIDs{block, rand_ctx.rand64()};
76 
77  DataStream stream{};
78  stream << shortIDs;
79 
80  CBlockHeaderAndShortTxIDs shortIDs2;
81  stream >> shortIDs2;
82 
83  PartiallyDownloadedBlock partialBlock(&pool);
84  BOOST_CHECK(partialBlock.InitData(shortIDs2, empty_extra_txn) == READ_STATUS_OK);
85  BOOST_CHECK( partialBlock.IsTxAvailable(0));
86  BOOST_CHECK(!partialBlock.IsTxAvailable(1));
87  BOOST_CHECK( partialBlock.IsTxAvailable(2));
88 
89  BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 1);
90 
91  size_t poolSize = pool.size();
93  BOOST_CHECK_EQUAL(pool.size(), poolSize - 1);
94 
95  CBlock block2;
96  {
97  PartiallyDownloadedBlock tmp = partialBlock;
98  BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
99  partialBlock = tmp;
100  }
101 
102  // Wrong transaction
103  {
104  PartiallyDownloadedBlock tmp = partialBlock;
105  partialBlock.FillBlock(block2, {block.vtx[2]}); // Current implementation doesn't check txn here, but don't require that
106  partialBlock = tmp;
107  }
108  bool mutated;
109  BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated));
110 
111  CBlock block3;
112  BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[1]}) == READ_STATUS_OK);
113  BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
114  BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
115  BOOST_CHECK(!mutated);
116  }
117 }
118 
120  // Utility to encode custom CBlockHeaderAndShortTxIDs
121 public:
123  uint64_t nonce;
124  std::vector<uint64_t> shorttxids;
125  std::vector<PrefilledTransaction> prefilledtxn;
126 
128  DataStream stream{};
129  stream << orig;
130  stream >> *this;
131  }
132  explicit TestHeaderAndShortIDs(const CBlock& block, FastRandomContext& ctx) :
133  TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs{block, ctx.rand64()}) {}
134 
135  uint64_t GetShortID(const Wtxid& txhash) const {
136  DataStream stream{};
137  stream << *this;
139  stream >> base;
140  return base.GetShortID(txhash);
141  }
142 
144 };
145 
146 BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
147 {
148  CTxMemPool& pool = *Assert(m_node.mempool);
150  auto rand_ctx(FastRandomContext(uint256{42}));
151  CBlock block(BuildBlockTestCase(rand_ctx));
152 
153  LOCK2(cs_main, pool.cs);
154  pool.addUnchecked(entry.FromTx(block.vtx[2]));
155  BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
156 
157  uint256 txhash;
158 
159  // Test with pre-forwarding tx 1, but not coinbase
160  {
161  TestHeaderAndShortIDs shortIDs(block, rand_ctx);
162  shortIDs.prefilledtxn.resize(1);
163  shortIDs.prefilledtxn[0] = {1, block.vtx[1]};
164  shortIDs.shorttxids.resize(2);
165  shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[0]->GetWitnessHash());
166  shortIDs.shorttxids[1] = shortIDs.GetShortID(block.vtx[2]->GetWitnessHash());
167 
168  DataStream stream{};
169  stream << shortIDs;
170 
171  CBlockHeaderAndShortTxIDs shortIDs2;
172  stream >> shortIDs2;
173 
174  PartiallyDownloadedBlock partialBlock(&pool);
175  BOOST_CHECK(partialBlock.InitData(shortIDs2, empty_extra_txn) == READ_STATUS_OK);
176  BOOST_CHECK(!partialBlock.IsTxAvailable(0));
177  BOOST_CHECK( partialBlock.IsTxAvailable(1));
178  BOOST_CHECK( partialBlock.IsTxAvailable(2));
179 
180  BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 1); // +1 because of partialBlock
181 
182  CBlock block2;
183  {
184  PartiallyDownloadedBlock tmp = partialBlock;
185  BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
186  partialBlock = tmp;
187  }
188 
189  // Wrong transaction
190  {
191  PartiallyDownloadedBlock tmp = partialBlock;
192  partialBlock.FillBlock(block2, {block.vtx[1]}); // Current implementation doesn't check txn here, but don't require that
193  partialBlock = tmp;
194  }
195  BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 2); // +2 because of partialBlock and block2
196  bool mutated;
197  BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated));
198 
199  CBlock block3;
200  PartiallyDownloadedBlock partialBlockCopy = partialBlock;
201  BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[0]}) == READ_STATUS_OK);
202  BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
203  BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
204  BOOST_CHECK(!mutated);
205 
206  BOOST_CHECK_EQUAL(pool.get(block.vtx[2]->GetHash()).use_count(), SHARED_TX_OFFSET + 3); // +2 because of partialBlock and block2 and block3
207 
208  txhash = block.vtx[2]->GetHash();
209  block.vtx.clear();
210  block2.vtx.clear();
211  block3.vtx.clear();
212  BOOST_CHECK_EQUAL(pool.get(txhash).use_count(), SHARED_TX_OFFSET + 1 - 1); // + 1 because of partialBlock; -1 because of block.
213  }
214  BOOST_CHECK_EQUAL(pool.get(txhash).use_count(), SHARED_TX_OFFSET - 1); // -1 because of block
215 }
216 
217 BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
218 {
219  CTxMemPool& pool = *Assert(m_node.mempool);
221  auto rand_ctx(FastRandomContext(uint256{42}));
222  CBlock block(BuildBlockTestCase(rand_ctx));
223 
224  LOCK2(cs_main, pool.cs);
225  pool.addUnchecked(entry.FromTx(block.vtx[1]));
226  BOOST_CHECK_EQUAL(pool.get(block.vtx[1]->GetHash()).use_count(), SHARED_TX_OFFSET + 0);
227 
228  uint256 txhash;
229 
230  // Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool
231  {
232  TestHeaderAndShortIDs shortIDs(block, rand_ctx);
233  shortIDs.prefilledtxn.resize(2);
234  shortIDs.prefilledtxn[0] = {0, block.vtx[0]};
235  shortIDs.prefilledtxn[1] = {1, block.vtx[2]}; // id == 1 as it is 1 after index 1
236  shortIDs.shorttxids.resize(1);
237  shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[1]->GetWitnessHash());
238 
239  DataStream stream{};
240  stream << shortIDs;
241 
242  CBlockHeaderAndShortTxIDs shortIDs2;
243  stream >> shortIDs2;
244 
245  PartiallyDownloadedBlock partialBlock(&pool);
246  BOOST_CHECK(partialBlock.InitData(shortIDs2, empty_extra_txn) == READ_STATUS_OK);
247  BOOST_CHECK( partialBlock.IsTxAvailable(0));
248  BOOST_CHECK( partialBlock.IsTxAvailable(1));
249  BOOST_CHECK( partialBlock.IsTxAvailable(2));
250 
251  BOOST_CHECK_EQUAL(pool.get(block.vtx[1]->GetHash()).use_count(), SHARED_TX_OFFSET + 1);
252 
253  CBlock block2;
254  PartiallyDownloadedBlock partialBlockCopy = partialBlock;
255  BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_OK);
256  BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
257  bool mutated;
258  BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
259  BOOST_CHECK(!mutated);
260 
261  txhash = block.vtx[1]->GetHash();
262  block.vtx.clear();
263  block2.vtx.clear();
264  BOOST_CHECK_EQUAL(pool.get(txhash).use_count(), SHARED_TX_OFFSET + 1 - 1); // + 1 because of partialBlock; -1 because of block.
265  }
266  BOOST_CHECK_EQUAL(pool.get(txhash).use_count(), SHARED_TX_OFFSET - 1); // -1 because of block
267 }
268 
269 BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
270 {
271  CTxMemPool& pool = *Assert(m_node.mempool);
273 
274  CBlock block;
275  auto rand_ctx(FastRandomContext(uint256{42}));
276  block.vtx.resize(1);
277  block.vtx[0] = MakeTransactionRef(std::move(coinbase));
278  block.nVersion = 42;
279  block.hashPrevBlock = rand_ctx.rand256();
280  block.nBits = 0x207fffff;
281 
282  bool mutated;
283  block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
284  assert(!mutated);
285  while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
286 
287  // Test simple header round-trip with only coinbase
288  {
289  CBlockHeaderAndShortTxIDs shortIDs{block, rand_ctx.rand64()};
290 
291  DataStream stream{};
292  stream << shortIDs;
293 
294  CBlockHeaderAndShortTxIDs shortIDs2;
295  stream >> shortIDs2;
296 
297  PartiallyDownloadedBlock partialBlock(&pool);
298  BOOST_CHECK(partialBlock.InitData(shortIDs2, empty_extra_txn) == READ_STATUS_OK);
299  BOOST_CHECK(partialBlock.IsTxAvailable(0));
300 
301  CBlock block2;
302  std::vector<CTransactionRef> vtx_missing;
303  BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK);
304  BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
305  BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
306  BOOST_CHECK(!mutated);
307  }
308 }
309 
310 BOOST_AUTO_TEST_CASE(ReceiveWithExtraTransactions) {
311  CTxMemPool& pool = *Assert(m_node.mempool);
313  auto rand_ctx(FastRandomContext(uint256{42}));
314 
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 
357 BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) {
359  req1.blockhash = InsecureRand256();
360  req1.indexes.resize(4);
361  req1.indexes[0] = 0;
362  req1.indexes[1] = 1;
363  req1.indexes[2] = 3;
364  req1.indexes[3] = 4;
365 
366  DataStream stream{};
367  stream << req1;
368 
370  stream >> req2;
371 
373  BOOST_CHECK_EQUAL(req1.indexes.size(), req2.indexes.size());
374  BOOST_CHECK_EQUAL(req1.indexes[0], req2.indexes[0]);
375  BOOST_CHECK_EQUAL(req1.indexes[1], req2.indexes[1]);
376  BOOST_CHECK_EQUAL(req1.indexes[2], req2.indexes[2]);
377  BOOST_CHECK_EQUAL(req1.indexes[3], req2.indexes[3]);
378 }
379 
380 BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationMaxTest) {
381  // Check that the highest legal index is decoded correctly
383  req0.blockhash = InsecureRand256();
384  req0.indexes.resize(1);
385  req0.indexes[0] = 0xffff;
386  DataStream stream{};
387  stream << req0;
388 
390  stream >> req1;
391  BOOST_CHECK_EQUAL(req0.indexes.size(), req1.indexes.size());
392  BOOST_CHECK_EQUAL(req0.indexes[0], req1.indexes[0]);
393 }
394 
395 BOOST_AUTO_TEST_CASE(TransactionsRequestDeserializationOverflowTest) {
396  // Any set of index deltas that starts with N values that sum to (0x10000 - N)
397  // causes the edge-case overflow that was originally not checked for. Such
398  // a request cannot be created by serializing a real BlockTransactionsRequest
399  // due to the overflow, so here we'll serialize from raw deltas.
401  req0.blockhash = InsecureRand256();
402  req0.indexes.resize(3);
403  req0.indexes[0] = 0x7000;
404  req0.indexes[1] = 0x10000 - 0x7000 - 2;
405  req0.indexes[2] = 0;
406  DataStream stream{};
407  stream << req0.blockhash;
408  WriteCompactSize(stream, req0.indexes.size());
409  WriteCompactSize(stream, req0.indexes[0]);
410  WriteCompactSize(stream, req0.indexes[1]);
411  WriteCompactSize(stream, req0.indexes[2]);
412 
414  try {
415  stream >> req1;
416  // before patch: deserialize above succeeds and this check fails, demonstrating the overflow
417  BOOST_CHECK(req1.indexes[1] < req1.indexes[2]);
418  // this shouldn't be reachable before or after patch
419  BOOST_CHECK(0);
420  } catch(std::ios_base::failure &) {
421  // deserialize should fail
422  BOOST_CHECK(true); // Needed to suppress "Test case [...] did not check any assertions"
423  }
424 }
425 
node::NodeContext m_node
Definition: bitcoin-gui.cpp:37
@ READ_STATUS_OK
@ READ_STATUS_INVALID
static CBlock BuildBlockTestCase(FastRandomContext &ctx)
BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
const std::vector< CTransactionRef > empty_extra_txn
constexpr long SHARED_TX_OFFSET
static CMutableTransaction BuildTransactionTestCase()
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
Definition: check.h:77
std::vector< uint16_t > indexes
uint64_t GetShortID(const Wtxid &wtxid) const
Nodes collect new transactions into a block, hash them into a hash tree, and scan through nonce value...
Definition: block.h:22
uint32_t nNonce
Definition: block.h:30
uint32_t nBits
Definition: block.h:29
int32_t nVersion
Definition: block.h:25
uint256 hashPrevBlock
Definition: block.h:26
uint256 hashMerkleRoot
Definition: block.h:27
uint256 GetHash() const
Definition: block.cpp:11
Definition: block.h:69
std::vector< CTransactionRef > vtx
Definition: block.h:72
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:304
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition: txmempool.h:388
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: txmempool.cpp:562
CTransactionRef get(const uint256 &hash) const
Definition: txmempool.cpp:848
unsigned long size() const
Definition: txmempool.h:645
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void addUnchecked(const CTxMemPoolEntry &entry) EXCLUSIVE_LOCKS_REQUIRED(cs
If sanity-checking is turned on, check makes sure the pool is consistent (does not contain two transa...
Definition: txmempool.h:461
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:147
Fast randomness source.
Definition: random.h:377
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< CTransactionRef > &extra_txn)
bool IsTxAvailable(size_t index) const
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
uint256 rand256() noexcept
generate a random uint256.
Definition: random.h:308
TestHeaderAndShortIDs(const CBlockHeaderAndShortTxIDs &orig)
std::vector< uint64_t > shorttxids
std::vector< PrefilledTransaction > prefilledtxn
TestHeaderAndShortIDs(const CBlock &block, FastRandomContext &ctx)
uint64_t GetShortID(const Wtxid &txhash) const
SERIALIZE_METHODS(TestHeaderAndShortIDs, obj)
std::string ToString() const
Definition: uint256.cpp:47
transaction_identifier represents the two canonical transaction identifier types (txid,...
static transaction_identifier FromUint256(const uint256 &id)
256-bit opaque blob.
Definition: uint256.h:127
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:8
BOOST_AUTO_TEST_SUITE_END()
@ REPLACED
Removed for replacement.
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
Definition: merkle.cpp:65
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:148
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params &params)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
Definition: pow.cpp:125
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:424
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
static Wrapper< Formatter, T & > Using(T &&t)
Cause serialization/deserialization of an object to be done using a specified formatter class.
Definition: serialize.h:495
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
Definition: serialize.h:1095
#define READWRITE(...)
Definition: serialize.h:156
A mutable version of CTransaction.
Definition: transaction.h:378
std::vector< CTxOut > vout
Definition: transaction.h:380
std::vector< CTxIn > vin
Definition: transaction.h:379
Serialization wrapper class for custom integers and enums.
Definition: serialize.h:528
Identical to TestingSetup, but chain set to regtest.
Definition: setup_common.h:101
Definition: txmempool.h:19
CTxMemPoolEntry FromTx(const CMutableTransaction &tx) const
Definition: txmempool.cpp:33
Formatter to serialize/deserialize vector elements using another formatter.
Definition: serialize.h:657
std::unique_ptr< CTxMemPool > mempool
Definition: context.h:65
#define LOCK2(cs1, cs2)
Definition: sync.h:258
static uint256 InsecureRand256()
Definition: random.h:35
assert(!tx.IsCoinBase())