Skip to content

Commit 450946f

Browse files
committed
Unit test for mempool with UTXO hasher.
This extends the mempool unit tests to explicitly verify that adding transactions, removing transactions, checking the pool and looking up coins / transactions still works even if we use the bare txid for some transactions as UTXO hash (as will be the case with segwit-light in the future).
1 parent 186655f commit 450946f

File tree

4 files changed

+94
-16
lines changed

4 files changed

+94
-16
lines changed

divi/src/test/MockUtxoHasher.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ uint256 MockUtxoHasher::Add(const CTransaction& tx)
1111
return value;
1212
}
1313

14+
void MockUtxoHasher::UseBareTxid(const CTransaction& tx)
15+
{
16+
customHashes.emplace(tx.GetHash(), tx.GetBareTxid());
17+
}
18+
1419
uint256 MockUtxoHasher::GetUtxoHash(const CTransaction& tx) const
1520
{
1621
const uint256 txid = tx.GetHash();

divi/src/test/MockUtxoHasher.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ class MockUtxoHasher : public TransactionUtxoHasher
3232
* is generated uniquely and returned from the function. */
3333
uint256 Add(const CTransaction& tx);
3434

35+
/** Marks the given transaction for using the bare txid rather than
36+
* the normal txid. */
37+
void UseBareTxid(const CTransaction& tx);
38+
3539
uint256 GetUtxoHash(const CTransaction& tx) const override;
3640

3741
};

divi/src/test/mempool_tests.cpp

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,70 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5-
#include "main.h"
65
#include "txmempool.h"
76

7+
#include "blockmap.h"
8+
#include "MockUtxoHasher.h"
9+
810
#include <boost/test/unit_test.hpp>
911
#include <list>
1012

13+
extern CChain chainActive;
14+
extern BlockMap mapBlockIndex;
15+
1116
class MempoolTestFixture
1217
{
1318

19+
private:
20+
21+
/** Empty coins view used to back the cached view we actually use. */
22+
CCoinsView emptyView;
23+
24+
/** Tip of our fake chain. */
25+
CBlockIndex tip;
26+
1427
protected:
1528

1629
/** A parent transaction. */
1730
CMutableTransaction txParent;
1831

19-
/** Three children of the parent. */
32+
/** Three children of the parent. They use the bare txid for their UTXOs
33+
* in our UTXO hasher. */
2034
CMutableTransaction txChild[3];
2135

2236
/** Three grand children. */
2337
CMutableTransaction txGrandChild[3];
2438

39+
/** Coins view with the parent inputs. */
40+
CCoinsViewCache view;
41+
2542
/** The test mempool instance. */
2643
CTxMemPool testPool;
2744

2845
public:
2946

3047
MempoolTestFixture()
31-
: testPool(CFeeRate(0))
48+
: view(&emptyView), testPool(CFeeRate(0))
3249
{
50+
testPool.setSanityCheck(true);
51+
auto* utxoHasher = new MockUtxoHasher();
52+
testPool.utxoHasher.reset(utxoHasher);
53+
testPool.clear();
54+
55+
CMutableTransaction base;
56+
base.vout.emplace_back(99000LL, CScript() << OP_11 << OP_EQUAL);
57+
view.ModifyCoins(base.GetHash())->FromTx(base, 0);
58+
59+
tip.pprev = nullptr;
60+
tip.nHeight = 0;
61+
mapBlockIndex[tip.GetBlockHeader().GetHash()] = &tip;
62+
view.SetBestBlock(tip.GetBlockHeader().GetHash());
63+
chainActive.SetTip(&tip);
64+
3365
txParent.vin.resize(1);
3466
txParent.vin[0].scriptSig = CScript() << OP_11;
67+
txParent.vin[0].prevout.hash = base.GetHash();
68+
txParent.vin[0].prevout.n = 0;
3569
txParent.vout.resize(3);
3670
for (int i = 0; i < 3; i++)
3771
{
@@ -48,20 +82,37 @@ class MempoolTestFixture
4882
txChild[i].vout.resize(1);
4983
txChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
5084
txChild[i].vout[0].nValue = 11000LL;
85+
utxoHasher->UseBareTxid(txChild[i]);
5186
}
5287

5388
for (int i = 0; i < 3; i++)
5489
{
5590
txGrandChild[i].vin.resize(1);
5691
txGrandChild[i].vin[0].scriptSig = CScript() << OP_11;
57-
txGrandChild[i].vin[0].prevout.hash = txChild[i].GetHash();
92+
txGrandChild[i].vin[0].prevout.hash = txChild[i].GetBareTxid();
5893
txGrandChild[i].vin[0].prevout.n = 0;
5994
txGrandChild[i].vout.resize(1);
6095
txGrandChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
6196
txGrandChild[i].vout[0].nValue = 11000LL;
6297
}
6398
}
6499

100+
~MempoolTestFixture()
101+
{
102+
mapBlockIndex.clear();
103+
}
104+
105+
/** Adds the parent, childs and grandchilds to the mempool. */
106+
void AddAll()
107+
{
108+
testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
109+
for (int i = 0; i < 3; i++)
110+
{
111+
testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
112+
testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
113+
}
114+
}
115+
65116
};
66117

67118
BOOST_FIXTURE_TEST_SUITE(mempool_tests, MempoolTestFixture)
@@ -83,12 +134,10 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
83134
removed.clear();
84135

85136
// Parent, children, grandchildren:
86-
testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
87-
for (int i = 0; i < 3; i++)
88-
{
89-
testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
90-
testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
91-
}
137+
AddAll();
138+
139+
testPool.check(&view);
140+
92141
// Remove Child[0], GrandChild[0] should be removed:
93142
testPool.remove(txChild[0], removed, true);
94143
BOOST_CHECK_EQUAL(removed.size(), 2);
@@ -123,12 +172,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexByBareTxid)
123172
CTransaction tx;
124173
std::list<CTransaction> removed;
125174

126-
testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
127-
for (int i = 0; i < 3; ++i)
128-
{
129-
testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
130-
testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
131-
}
175+
AddAll();
132176

133177
BOOST_CHECK(testPool.lookupBareTxid(txParent.GetBareTxid(), tx));
134178
BOOST_CHECK(tx.GetHash() == txParent.GetHash());
@@ -140,4 +184,28 @@ BOOST_AUTO_TEST_CASE(MempoolIndexByBareTxid)
140184
BOOST_CHECK(!testPool.lookupBareTxid(txGrandChild[0].GetBareTxid(), tx));
141185
}
142186

187+
BOOST_AUTO_TEST_CASE(MempoolOutpointLookup)
188+
{
189+
CTransaction tx;
190+
CCoins coins;
191+
192+
AddAll();
193+
CCoinsViewMemPool viewPool(&view, testPool);
194+
195+
BOOST_CHECK(testPool.lookupOutpoint(txParent.GetHash(), tx));
196+
BOOST_CHECK(!testPool.lookupOutpoint(txParent.GetBareTxid(), tx));
197+
BOOST_CHECK(!testPool.lookupOutpoint(txChild[0].GetHash(), tx));
198+
BOOST_CHECK(testPool.lookupOutpoint(txChild[0].GetBareTxid(), tx));
199+
200+
BOOST_CHECK(viewPool.HaveCoins(txParent.GetHash()));
201+
BOOST_CHECK(viewPool.GetCoins(txParent.GetHash(), coins));
202+
BOOST_CHECK(!viewPool.HaveCoins(txParent.GetBareTxid()));
203+
BOOST_CHECK(!viewPool.GetCoins(txParent.GetBareTxid(), coins));
204+
205+
BOOST_CHECK(!viewPool.HaveCoins(txChild[0].GetHash()));
206+
BOOST_CHECK(!viewPool.GetCoins(txChild[0].GetHash(), coins));
207+
BOOST_CHECK(viewPool.HaveCoins(txChild[0].GetBareTxid()));
208+
BOOST_CHECK(viewPool.GetCoins(txChild[0].GetBareTxid(), coins));
209+
}
210+
143211
BOOST_AUTO_TEST_SUITE_END()

divi/src/txmempool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class CTxMemPool
128128
std::map<uint256, const CTxMemPoolEntry*> mapBareTxid;
129129

130130
friend class BlockMemoryPoolTransactionCollector;
131+
friend class MempoolTestFixture;
131132

132133
public:
133134
mutable CCriticalSection cs;

0 commit comments

Comments
 (0)