Skip to content

Commit 131d377

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 aec878a commit 131d377

File tree

6 files changed

+106
-22
lines changed

6 files changed

+106
-22
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/UtxoCheckingAndUpdating_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ BOOST_AUTO_TEST_CASE(addsCorrectOutputs)
4141
const auto id2 = utxoHasher.Add(tx2);
4242

4343
CTxUndo txundo;
44-
UpdateCoins(tx1, coins, txundo, utxoHasher, 101);
45-
UpdateCoins(tx2, coins, txundo, utxoHasher, 102);
44+
UpdateCoinsWithTransaction(tx1, coins, txundo, utxoHasher, 101);
45+
UpdateCoinsWithTransaction(tx2, coins, txundo, utxoHasher, 102);
4646

4747
BOOST_CHECK(coins.HaveCoins(tx1.GetHash()));
4848
BOOST_CHECK(!coins.HaveCoins(tx2.GetHash()));

divi/src/test/mempool_tests.cpp

Lines changed: 86 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,67 @@
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
{
33-
txParent.vin.resize(2);
50+
std::unique_ptr<MockUtxoHasher> utxoHasher(new MockUtxoHasher());
51+
52+
CMutableTransaction base;
53+
base.vout.emplace_back(99000LL, CScript() << OP_11 << OP_EQUAL);
54+
view.ModifyCoins(base.GetHash())->FromTx(base, 0);
55+
56+
tip.pprev = nullptr;
57+
tip.nHeight = 0;
58+
mapBlockIndex[tip.GetBlockHeader().GetHash()] = &tip;
59+
view.SetBestBlock(tip.GetBlockHeader().GetHash());
60+
chainActive.SetTip(&tip);
61+
62+
txParent.vin.resize(1);
3463
txParent.vin[0].scriptSig = CScript() << OP_11;
35-
/* Add a second input to make sure the transaction does not qualify as
36-
coinbase and thus has a bare txid unequal to its normal hash. */
37-
txParent.vin[1].scriptSig = CScript() << OP_12;
64+
txParent.vin[0].prevout.hash = base.GetHash();
65+
txParent.vin[0].prevout.n = 0;
3866
txParent.vout.resize(3);
3967
for (int i = 0; i < 3; i++)
4068
{
@@ -52,18 +80,39 @@ class MempoolTestFixture
5280
txChild[i].vout.resize(1);
5381
txChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
5482
txChild[i].vout[0].nValue = 11000LL;
83+
utxoHasher->UseBareTxid(txChild[i]);
5584
}
5685

5786
for (int i = 0; i < 3; i++)
5887
{
5988
txGrandChild[i].vin.resize(1);
6089
txGrandChild[i].vin[0].scriptSig = CScript() << OP_11;
61-
txGrandChild[i].vin[0].prevout.hash = txChild[i].GetHash();
90+
txGrandChild[i].vin[0].prevout.hash = txChild[i].GetBareTxid();
6291
txGrandChild[i].vin[0].prevout.n = 0;
6392
txGrandChild[i].vout.resize(1);
6493
txGrandChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
6594
txGrandChild[i].vout[0].nValue = 11000LL;
6695
}
96+
97+
testPool.setSanityCheck(true);
98+
testPool.SetUtxoHasherForTesting(std::move(utxoHasher));
99+
testPool.clear();
100+
}
101+
102+
~MempoolTestFixture()
103+
{
104+
mapBlockIndex.clear();
105+
}
106+
107+
/** Adds the parent, childs and grandchilds to the mempool. */
108+
void AddAll()
109+
{
110+
testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
111+
for (int i = 0; i < 3; i++)
112+
{
113+
testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
114+
testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
115+
}
67116
}
68117

69118
};
@@ -87,12 +136,10 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
87136
removed.clear();
88137

89138
// Parent, children, grandchildren:
90-
testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
91-
for (int i = 0; i < 3; i++)
92-
{
93-
testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
94-
testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
95-
}
139+
AddAll();
140+
141+
testPool.check(&view);
142+
96143
// Remove Child[0], GrandChild[0] should be removed:
97144
testPool.remove(txChild[0], removed, true);
98145
BOOST_CHECK_EQUAL(removed.size(), 2);
@@ -127,12 +174,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexByBareTxid)
127174
CTransaction tx;
128175
std::list<CTransaction> removed;
129176

130-
testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1));
131-
for (int i = 0; i < 3; ++i)
132-
{
133-
testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1));
134-
testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1));
135-
}
177+
AddAll();
136178

137179
BOOST_CHECK(testPool.lookupBareTxid(txParent.GetBareTxid(), tx));
138180
BOOST_CHECK(tx.GetHash() == txParent.GetHash());
@@ -144,4 +186,28 @@ BOOST_AUTO_TEST_CASE(MempoolIndexByBareTxid)
144186
BOOST_CHECK(!testPool.lookupBareTxid(txGrandChild[0].GetBareTxid(), tx));
145187
}
146188

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

divi/src/txmempool.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,11 @@ const TransactionUtxoHasher& CTxMemPool::GetUtxoHasher() const
451451
return *utxoHasher;
452452
}
453453

454+
void CTxMemPool::SetUtxoHasherForTesting(std::unique_ptr<TransactionUtxoHasher> hasher)
455+
{
456+
utxoHasher = std::move(hasher);
457+
}
458+
454459
void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view)
455460
{
456461
LOCK(cs);

divi/src/txmempool.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ class CTxMemPool
158158
/** Returns the UTXO hasher instance used in the mempool. */
159159
const TransactionUtxoHasher& GetUtxoHasher() const;
160160

161+
/** Replaces the UTXO hasher used in the mempool with the given instance,
162+
* which allows dependency injection for unit tests. */
163+
void SetUtxoHasherForTesting(std::unique_ptr<TransactionUtxoHasher> hasher);
164+
161165
void addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view);
162166
bool getAddressIndex(std::vector<std::pair<uint160, int> > &addresses,
163167
std::vector<std::pair<CMempoolAddressDeltaKey, CMempoolAddressDelta> > &results);

0 commit comments

Comments
 (0)