Skip to content

Commit ce1e9a5

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 afd8e56 commit ce1e9a5

File tree

6 files changed

+94
-21
lines changed

6 files changed

+94
-21
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: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,27 @@
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

1419
private:
1520

1621
CCoinsView coinsDummy;
1722

23+
/** Tip of our fake chain. */
24+
CBlockIndex tip;
25+
1826
protected:
1927

2028
/* The test mempool will use these flags instead of the global ones. */
@@ -24,7 +32,8 @@ class MempoolTestFixture
2432
/** A parent transaction. */
2533
CMutableTransaction txParent;
2634

27-
/** Three children of the parent. */
35+
/** Three children of the parent. They use the bare txid for their UTXOs
36+
* in our UTXO hasher. */
2837
CMutableTransaction txChild[3];
2938

3039
/** Three grand children. */
@@ -45,11 +54,19 @@ class MempoolTestFixture
4554
: testPool(CFeeRate(0), addressIndex, spentIndex),
4655
coinsMemPool(&coinsDummy, testPool), coins(&coinsMemPool)
4756
{
57+
std::unique_ptr<MockUtxoHasher> utxoHasher(new MockUtxoHasher());
58+
4859
CMutableTransaction mtx;
49-
mtx.vout.emplace_back(COIN, CScript () << OP_TRUE);
60+
mtx.vout.emplace_back(2 * COIN, CScript () << OP_TRUE);
5061
mtx.vout.emplace_back(COIN, CScript () << OP_TRUE);
5162
coins.ModifyCoins(mtx.GetHash())->FromTx(mtx, 0);
5263

64+
tip.pprev = nullptr;
65+
tip.nHeight = 0;
66+
mapBlockIndex[tip.GetBlockHeader().GetHash()] = &tip;
67+
coins.SetBestBlock(tip.GetBlockHeader().GetHash());
68+
chainActive.SetTip(&tip);
69+
5370
txParent.vin.resize(2);
5471
txParent.vin[0].prevout = COutPoint(mtx.GetHash(), 0);
5572
txParent.vin[0].scriptSig = CScript() << OP_11;
@@ -61,7 +78,7 @@ class MempoolTestFixture
6178
for (int i = 0; i < 3; i++)
6279
{
6380
txParent.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
64-
txParent.vout[i].nValue = 33000LL;
81+
txParent.vout[i].nValue = COIN;
6582
}
6683
assert(txParent.GetHash() != txParent.GetBareTxid());
6784

@@ -73,19 +90,40 @@ class MempoolTestFixture
7390
txChild[i].vin[0].prevout.n = i;
7491
txChild[i].vout.resize(1);
7592
txChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
76-
txChild[i].vout[0].nValue = 11000LL;
93+
txChild[i].vout[0].nValue = COIN;
94+
utxoHasher->UseBareTxid(txChild[i]);
7795
}
7896

7997
for (int i = 0; i < 3; i++)
8098
{
8199
txGrandChild[i].vin.resize(1);
82100
txGrandChild[i].vin[0].scriptSig = CScript() << OP_11;
83-
txGrandChild[i].vin[0].prevout.hash = txChild[i].GetHash();
101+
txGrandChild[i].vin[0].prevout.hash = txChild[i].GetBareTxid();
84102
txGrandChild[i].vin[0].prevout.n = 0;
85103
txGrandChild[i].vout.resize(1);
86104
txGrandChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
87-
txGrandChild[i].vout[0].nValue = 11000LL;
105+
txGrandChild[i].vout[0].nValue = COIN;
88106
}
107+
108+
testPool.setSanityCheck(true);
109+
testPool.SetUtxoHasherForTesting(std::move(utxoHasher));
110+
testPool.clear();
111+
}
112+
113+
~MempoolTestFixture()
114+
{
115+
mapBlockIndex.clear();
116+
}
117+
118+
/** Adds the parent, childs and grandchilds to the mempool. */
119+
void AddAll()
120+
{
121+
testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1), coins);
122+
for (int i = 0; i < 3; i++)
123+
{
124+
testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1), coins);
125+
testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1), coins);
126+
}
89127
}
90128

91129
};
@@ -109,12 +147,10 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
109147
removed.clear();
110148

111149
// Parent, children, grandchildren:
112-
testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1), coins);
113-
for (int i = 0; i < 3; i++)
114-
{
115-
testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1), coins);
116-
testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1), coins);
117-
}
150+
AddAll();
151+
152+
testPool.check(&coins);
153+
118154
// Remove Child[0], GrandChild[0] should be removed:
119155
testPool.remove(txChild[0], removed, true);
120156
BOOST_CHECK_EQUAL(removed.size(), 2);
@@ -149,12 +185,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexByBareTxid)
149185
CTransaction tx;
150186
std::list<CTransaction> removed;
151187

152-
testPool.addUnchecked(txParent.GetHash(), CTxMemPoolEntry(txParent, 0, 0, 0.0, 1), coins);
153-
for (int i = 0; i < 3; ++i)
154-
{
155-
testPool.addUnchecked(txChild[i].GetHash(), CTxMemPoolEntry(txChild[i], 0, 0, 0.0, 1), coins);
156-
testPool.addUnchecked(txGrandChild[i].GetHash(), CTxMemPoolEntry(txGrandChild[i], 0, 0, 0.0, 1), coins);
157-
}
188+
AddAll();
158189

159190
BOOST_CHECK(testPool.lookupBareTxid(txParent.GetBareTxid(), tx));
160191
BOOST_CHECK(tx.GetHash() == txParent.GetHash());
@@ -189,4 +220,28 @@ BOOST_AUTO_TEST_CASE(MempoolSpentIndex)
189220
BOOST_CHECK(!testPool.getSpentIndex(keyChild, value));
190221
}
191222

223+
BOOST_AUTO_TEST_CASE(MempoolOutpointLookup)
224+
{
225+
CTransaction tx;
226+
CCoins c;
227+
228+
AddAll();
229+
CCoinsViewMemPool viewPool(&coins, testPool);
230+
231+
BOOST_CHECK(testPool.lookupOutpoint(txParent.GetHash(), tx));
232+
BOOST_CHECK(!testPool.lookupOutpoint(txParent.GetBareTxid(), tx));
233+
BOOST_CHECK(!testPool.lookupOutpoint(txChild[0].GetHash(), tx));
234+
BOOST_CHECK(testPool.lookupOutpoint(txChild[0].GetBareTxid(), tx));
235+
236+
BOOST_CHECK(viewPool.HaveCoins(txParent.GetHash()));
237+
BOOST_CHECK(viewPool.GetCoins(txParent.GetHash(), c));
238+
BOOST_CHECK(!viewPool.HaveCoins(txParent.GetBareTxid()));
239+
BOOST_CHECK(!viewPool.GetCoins(txParent.GetBareTxid(), c));
240+
241+
BOOST_CHECK(!viewPool.HaveCoins(txChild[0].GetHash()));
242+
BOOST_CHECK(!viewPool.GetCoins(txChild[0].GetHash(), c));
243+
BOOST_CHECK(viewPool.HaveCoins(txChild[0].GetBareTxid()));
244+
BOOST_CHECK(viewPool.GetCoins(txChild[0].GetBareTxid(), c));
245+
}
246+
192247
BOOST_AUTO_TEST_SUITE_END()

divi/src/txmempool.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,11 @@ const TransactionUtxoHasher& CTxMemPool::GetUtxoHasher() const
465465
return *utxoHasher;
466466
}
467467

468+
void CTxMemPool::SetUtxoHasherForTesting(std::unique_ptr<TransactionUtxoHasher> hasher)
469+
{
470+
utxoHasher = std::move(hasher);
471+
}
472+
468473
void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view)
469474
{
470475
LOCK(cs);

divi/src/txmempool.h

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

178+
/** Replaces the UTXO hasher used in the mempool with the given instance,
179+
* which allows dependency injection for unit tests. */
180+
void SetUtxoHasherForTesting(std::unique_ptr<TransactionUtxoHasher> hasher);
181+
178182
/** Affect CreateNewBlock prioritisation of transactions */
179183
void PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, const CAmount& nFeeDelta);
180184
void ApplyDeltas(const uint256 hash, double& dPriorityDelta, CAmount& nFeeDelta);

0 commit comments

Comments
 (0)