Skip to content

Commit ece67ac

Browse files
committed
add interest calculations via CCoinsViewCache::GetValueIn test
1 parent d2f32d6 commit ece67ac

File tree

1 file changed

+116
-15
lines changed

1 file changed

+116
-15
lines changed

src/test-komodo/test_kmd_feat.cpp

+116-15
Original file line numberDiff line numberDiff line change
@@ -23,30 +23,34 @@ const std::string testwif("Usr24VoC3h4cSfSrFiGJkWLYwmkM1VnsBiMyWZvrF6QR5ZQ6Fbuu"
2323
const std::string testpk("034b082c5819b5bf8798a387630ad236a8e800dbce4c4e24a46f36dfddab3cbff5");
2424
const std::string testaddr("RXTUtWXgkepi8f2ohWLL9KhtGKRjBV48hT");
2525

26-
const uint256 testPrevHash = uint256S("01f1fde483c591ae81bee34f3dfc26ca4d6f061bc4ca15806ae15e07befedce9");
27-
28-
// Fake the input of transaction testPrevHash/0
26+
// Fake the input of transaction mtx0/0
2927
class FakeCoinsViewDB2 : public CCoinsView { // change name to FakeCoinsViewDB2 to avoid name conflict with same class name in different files (seems a bug in macos gcc)
3028
public:
31-
FakeCoinsViewDB2() {}
29+
FakeCoinsViewDB2() {
30+
// allowed mtx0 txids
31+
sAllowedTxIn.insert(uint256S("01f1fde483c591ae81bee34f3dfc26ca4d6f061bc4ca15806ae15e07befedce9")); // 1 * COIN , nLockTime = 0
32+
sAllowedTxIn.insert(uint256S("c8ff545cdc5e921cdbbd24555a462340fc1092e09977944ec687c5bf3ef9c30b")); // 10 * COIN, nLockTime = 0
33+
sAllowedTxIn.insert(uint256S("529d8dcec041465fdf6c1f873ef1055eec106db5f02ae222814d3764bb8e6660")); // 10 * COIN, nLockTime = 1663755146
34+
sAllowedTxIn.insert(uint256S("3533600e69a22776afb765305a0ec46bcb06e1942f36a113d73733190092f9d5")); // 10 * COIN, nLockTime = 1663755147
35+
}
3236

3337
bool GetCoins(const uint256 &txid, CCoins &coins) const {
34-
if (txid == testPrevHash) {
38+
if (sAllowedTxIn.count(txid)) {
3539
CTxOut txOut;
36-
txOut.nValue = COIN;
40+
txOut.nValue = 10 * COIN;
3741
txOut.scriptPubKey = GetScriptForDestination(DecodeDestination(testaddr));
3842
CCoins newCoins;
3943
newCoins.vout.resize(1);
4044
newCoins.vout[0] = txOut;
41-
newCoins.nHeight = komodo_interest_height-1;
45+
newCoins.nHeight = komodo_interest_height-1; /* TODO: return correct nHeight depends on txid */
4246
coins.swap(newCoins);
4347
return true;
4448
}
4549
return false;
4650
}
4751

4852
bool HaveCoins(const uint256 &txid) const {
49-
if (txid == testPrevHash)
53+
if (sAllowedTxIn.count(txid))
5054
return true;
5155
return false;
5256
}
@@ -72,6 +76,7 @@ class FakeCoinsViewDB2 : public CCoinsView { // change name to FakeCoinsViewDB2
7276
}
7377

7478
uint256 bestBlockHash;
79+
std::set<uint256> sAllowedTxIn;
7580
};
7681

7782
bool TestSignTx(const CKeyStore& keystore, CMutableTransaction& mtx, int32_t vini, CAmount utxovalue, const CScript scriptPubKey)
@@ -119,7 +124,8 @@ TEST_F(KomodoFeatures, komodo_interest_validate) {
119124
// Add a fake transaction to the wallet
120125
CMutableTransaction mtx0 = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_interest_height-1);
121126
CScript scriptPubKey = GetScriptForDestination(DecodeDestination(testaddr));
122-
mtx0.vout.push_back(CTxOut(COIN, scriptPubKey));
127+
mtx0.vout.push_back(CTxOut(10 * COIN, scriptPubKey));
128+
mtx0.nLockTime = 1663755146;
123129

124130
// Fake-mine the transaction
125131
ASSERT_EQ(-1, chainActive.Height());
@@ -137,20 +143,20 @@ TEST_F(KomodoFeatures, komodo_interest_validate) {
137143
EXPECT_TRUE(chainActive.Contains(pfakeIndex));
138144
EXPECT_EQ(komodo_interest_height-1, chainActive.Height());
139145

140-
//std::cerr << " mtx0.GetHash()=" << mtx0.GetHash().GetHex() << std::endl;
141-
EXPECT_EQ(mtx0.GetHash(), testPrevHash);
142-
143146
FakeCoinsViewDB2 fakedb;
144147
fakedb.bestBlockHash = blockHash;
145148
CCoinsViewCache fakeview(&fakedb);
146149
pcoinsTip = &fakeview;
147150

151+
//std::cerr << " mtx0.GetHash()=" << mtx0.GetHash().GetHex() << std::endl;
152+
EXPECT_NE(fakedb.sAllowedTxIn.count(mtx0.GetHash()), 0);
153+
148154
CTxMemPool pool(::minRelayTxFee);
149155
bool missingInputs;
150156
CMutableTransaction mtxSpend = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_interest_height);
151157
mtxSpend.vin.push_back(CTxIn(mtx0.GetHash(), 0));
152158
CScript scriptPubKey1 = GetScriptForDestination(DecodeDestination(testaddr));
153-
mtxSpend.vout.push_back(CTxOut(COIN, scriptPubKey1));
159+
mtxSpend.vout.push_back(CTxOut(10 * COIN, scriptPubKey1));
154160

155161
CBasicKeyStore tempKeystore;
156162
CKey key = DecodeSecret(testwif);
@@ -213,7 +219,6 @@ TEST_F(KomodoFeatures, komodo_interest_validate) {
213219

214220
{
215221
// check valid interest in block
216-
217222
mtxSpend.nLockTime = chainActive.Tip()->GetMedianTimePast() - 3600; // not too long time in mempool
218223
mtxSpend.vin[0].scriptSig.clear();
219224
EXPECT_TRUE(TestSignTx(tempKeystore, mtxSpend, 0, mtx0.vout[0].nValue, mtx0.vout[0].scriptPubKey));
@@ -227,6 +232,102 @@ TEST_F(KomodoFeatures, komodo_interest_validate) {
227232
CValidationState state1;
228233
EXPECT_TRUE(ContextualCheckBlock(false, block, state1, pfakeIndex));
229234
}
235+
236+
{
237+
// test interest calculations via CCoinsViewCache::GetValueIn
238+
239+
const uint32_t tipTimes[] = {
240+
1663755146,
241+
1663762346, // chainActive.Tip()->GetMedianTimePast() + 2 * 3600 (MTP from 1663755146 + 2 * 3600)
242+
1663762346 + 31 * 24 * 60 * 60, /* month */
243+
1663762346 + 6 * 30 * 24 * 60 * 60, /* half of a year */
244+
1663762346 + 12 * 30 * 24 * 60 * 60, /* year (360 days) */
245+
1663762346 + 365 * 24 * 60 * 60, /* year (365 days) */
246+
};
247+
248+
/* komodo_interest_height = 247205+1 */
249+
const CAmount interestCollectedBefore250k[] = {0, 11415, 4545454, 25000000, 50000000, 50000000};
250+
/* komodo_interest_height = 333332 */
251+
const CAmount interestCollectedBefore1M[] = {0, 5802, 4252378, 24663337, 49320871, 49994387};
252+
/* komodo_interest_height = 3000000 */
253+
const CAmount interestCollected[] = {0, 5795, 4235195, 4235195, 4235195, 4235195};
254+
255+
/* check collected interest */
256+
257+
const size_t nMaxTipTimes = sizeof(tipTimes) / sizeof(tipTimes[0]);
258+
const size_t nMaxInterestCollected = sizeof(interestCollected) / sizeof(interestCollected[0]);
259+
assert(nMaxTipTimes == nMaxInterestCollected);
260+
261+
const int testHeights[] = {
262+
247205 + 1, 333332, 3000000};
263+
264+
CValidationState state;
265+
266+
for (size_t idx_ht = 0; idx_ht < sizeof(testHeights) / sizeof(testHeights[0]); ++idx_ht)
267+
{
268+
269+
pfakeIndex->nHeight = testHeights[idx_ht] - 1;
270+
mtx0.nLockTime = 1663755146;
271+
mtxSpend.vin[0] = CTxIn(mtx0.GetHash(), 0);
272+
273+
for (size_t idx = 0; idx < nMaxTipTimes; ++idx)
274+
{
275+
// make fake last block
276+
CBlock lastBlock;
277+
lastBlock.nTime = tipTimes[idx];
278+
279+
CBlockIndex *pLastBlockIndex = new CBlockIndex(block);
280+
pLastBlockIndex->pprev = pfakeIndex;
281+
pLastBlockIndex->nHeight = testHeights[idx_ht];
282+
pLastBlockIndex->nTime = lastBlock.nTime;
283+
chainActive.SetTip(pLastBlockIndex);
284+
285+
mtxSpend.nLockTime = lastBlock.nTime;
286+
mtxSpend.vin[0].scriptSig.clear();
287+
EXPECT_TRUE(TestSignTx(tempKeystore, mtxSpend, 0, mtx0.vout[0].nValue, mtx0.vout[0].scriptPubKey));
288+
CTransaction tx1(mtxSpend);
289+
290+
mempool.clear();
291+
mapBlockIndex.clear();
292+
293+
// put tx which we trying to spend into mempool,
294+
// bcz CCoinsViewCache::GetValueIn will call komodo_accrued_interest
295+
// -> komodo_interest_args -> GetTransaction
296+
297+
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
298+
SetMockTime(mtxSpend.nLockTime);
299+
CTxMemPoolEntry entry(mtx0, 0, GetTime(), 0, chainActive.Height(), mempool.HasNoInputsOf(mtx0), false, consensusBranchId);
300+
mempool.addUnchecked(mtx0.GetHash(), entry, false);
301+
302+
EXPECT_TRUE(mempool.exists(mtx0.GetHash()));
303+
304+
// force komodo_getblockindex in komodo_interest_args return a value
305+
uint256 zero;
306+
zero.SetNull();
307+
mapBlockIndex.insert(std::make_pair(zero, pfakeIndex));
308+
309+
fakeview.GetBestBlock(); // bring the best block into scope
310+
EXPECT_EQ(chainActive.Tip()->nHeight, testHeights[idx_ht]);
311+
CAmount interest = 0;
312+
CAmount nValueIn = fakeview.GetValueIn(chainActive.Tip()->nHeight, interest, tx1);
313+
314+
switch (testHeights[idx_ht])
315+
{
316+
case 247205 + 1:
317+
ASSERT_EQ(interest, interestCollectedBefore250k[idx]);
318+
break;
319+
case 333332:
320+
ASSERT_EQ(interest, interestCollectedBefore1M[idx]);
321+
break;
322+
default:
323+
ASSERT_EQ(interest, interestCollected[idx]);
324+
break;
325+
}
326+
327+
delete pLastBlockIndex;
328+
}
329+
}
330+
}
230331
}
231332

232333
// check komodo_interestnew calculations
@@ -365,4 +466,4 @@ TEST_F(KomodoFeatures, komodo_interest) {
365466
}
366467
}
367468
}
368-
}
469+
}

0 commit comments

Comments
 (0)