Skip to content

Commit 6d0a147

Browse files
author
MarcoFalke
committed
Merge #14908: test: Removed implicit CTransaction constructor calls from tests and benchmarks.
8db0c3d Removed implicit CTransaction conversion from benchmaks (lucash-dev) ed61abe Removed implicit CTransaction constructor from tests (lucash-dev) Pull request description: This PR was split from #14906 and is a prerequisite for it. It updates tests and benchmarks, removing all implicit calls to `CTransaction(CMutableTransaction&)` constructors. This will make possible making the constructor explicit in the next PR. The original rationale for making the constructor explicit: - Conversion constructors should not be explicit unless there's a strong reason for it (in the opinion of, for example, https://google.github.io/styleguide/cppguide.html, and https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ro-conversion. Let me know your take on this). - This particular conversion is very costly -- it implies a serialization plus hash of the transaction. - Even though `CTransaction` and `CMutableTransaction` represent the same data, they have very different use cases and performance properties. - Making it explicit allows for easier reasoning of performance trade-offs. - There has been previous performance issues caused by unneeded use of this implicit conversion. - This PR creates a map for places to look for possible refactoring and performance gains (this benefit still holds if the PR is not merged). Tree-SHA512: de8073aa6ff8a3153bcbe10818616677ecf9598e4978d8a0b4c39a262e71c36be5679cec08554c760d1f011ba6d37350318248eef15f6d9b86f9e4462b2de0d2
2 parents 38fb1b4 + 8db0c3d commit 6d0a147

13 files changed

+122
-121
lines changed

src/bench/ccoins_caching.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet)
3535
dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
3636
dummyTransactions[0].vout[1].nValue = 50 * COIN;
3737
dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
38-
AddCoins(coinsRet, dummyTransactions[0], 0);
38+
AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0);
3939

4040
dummyTransactions[1].vout.resize(2);
4141
dummyTransactions[1].vout[0].nValue = 21 * COIN;
4242
dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(key[2].GetPubKey().GetID());
4343
dummyTransactions[1].vout[1].nValue = 22 * COIN;
4444
dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID());
45-
AddCoins(coinsRet, dummyTransactions[1], 0);
45+
AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0);
4646

4747
return dummyTransactions;
4848
}
@@ -76,10 +76,11 @@ static void CCoinsCaching(benchmark::State& state)
7676
t1.vout[0].scriptPubKey << OP_1;
7777

7878
// Benchmark.
79+
const CTransaction tx_1(t1);
7980
while (state.KeepRunning()) {
80-
bool success = AreInputsStandard(t1, coins);
81+
bool success = AreInputsStandard(tx_1, coins);
8182
assert(success);
82-
CAmount value = coins.GetValueIn(t1);
83+
CAmount value = coins.GetValueIn(tx_1);
8384
assert(value == (50 + 21 + 22) * COIN);
8485
}
8586
}

src/bench/mempool_eviction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ static void MempoolEviction(benchmark::State& state)
127127
AddTx(tx6_r, 1100LL, pool);
128128
AddTx(tx7_r, 9000LL, pool);
129129
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4);
130-
pool.TrimToSize(GetVirtualTransactionSize(tx1));
130+
pool.TrimToSize(GetVirtualTransactionSize(*tx1_r));
131131
}
132132
}
133133

src/test/coins_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
377377

378378
// Call UpdateCoins on the top cache
379379
CTxUndo undo;
380-
UpdateCoins(tx, *(stack.back()), undo, height);
380+
UpdateCoins(CTransaction(tx), *(stack.back()), undo, height);
381381

382382
// Update the utxo set for future spends
383383
utxoset.insert(outpoint);

src/test/mempool_tests.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
5959

6060
// Nothing in pool, remove should do nothing:
6161
unsigned int poolSize = testPool.size();
62-
testPool.removeRecursive(txParent);
62+
testPool.removeRecursive(CTransaction(txParent));
6363
BOOST_CHECK_EQUAL(testPool.size(), poolSize);
6464

6565
// Just the parent:
6666
testPool.addUnchecked(entry.FromTx(txParent));
6767
poolSize = testPool.size();
68-
testPool.removeRecursive(txParent);
68+
testPool.removeRecursive(CTransaction(txParent));
6969
BOOST_CHECK_EQUAL(testPool.size(), poolSize - 1);
7070

7171
// Parent, children, grandchildren:
@@ -77,18 +77,18 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
7777
}
7878
// Remove Child[0], GrandChild[0] should be removed:
7979
poolSize = testPool.size();
80-
testPool.removeRecursive(txChild[0]);
80+
testPool.removeRecursive(CTransaction(txChild[0]));
8181
BOOST_CHECK_EQUAL(testPool.size(), poolSize - 2);
8282
// ... make sure grandchild and child are gone:
8383
poolSize = testPool.size();
84-
testPool.removeRecursive(txGrandChild[0]);
84+
testPool.removeRecursive(CTransaction(txGrandChild[0]));
8585
BOOST_CHECK_EQUAL(testPool.size(), poolSize);
8686
poolSize = testPool.size();
87-
testPool.removeRecursive(txChild[0]);
87+
testPool.removeRecursive(CTransaction(txChild[0]));
8888
BOOST_CHECK_EQUAL(testPool.size(), poolSize);
8989
// Remove parent, all children/grandchildren should go:
9090
poolSize = testPool.size();
91-
testPool.removeRecursive(txParent);
91+
testPool.removeRecursive(CTransaction(txParent));
9292
BOOST_CHECK_EQUAL(testPool.size(), poolSize - 5);
9393
BOOST_CHECK_EQUAL(testPool.size(), 0U);
9494

@@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
101101
// Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
102102
// put into the mempool (maybe because it is non-standard):
103103
poolSize = testPool.size();
104-
testPool.removeRecursive(txParent);
104+
testPool.removeRecursive(CTransaction(txParent));
105105
BOOST_CHECK_EQUAL(testPool.size(), poolSize - 6);
106106
BOOST_CHECK_EQUAL(testPool.size(), 0U);
107107
}
@@ -309,7 +309,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
309309
tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
310310
tx2.vout[0].nValue = 2 * COIN;
311311
pool.addUnchecked(entry.Fee(20000LL).FromTx(tx2));
312-
uint64_t tx2Size = GetVirtualTransactionSize(tx2);
312+
uint64_t tx2Size = GetVirtualTransactionSize(CTransaction(tx2));
313313

314314
/* lowest fee */
315315
CMutableTransaction tx3 = CMutableTransaction();
@@ -357,7 +357,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
357357
tx6.vout.resize(1);
358358
tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
359359
tx6.vout[0].nValue = 20 * COIN;
360-
uint64_t tx6Size = GetVirtualTransactionSize(tx6);
360+
uint64_t tx6Size = GetVirtualTransactionSize(CTransaction(tx6));
361361

362362
pool.addUnchecked(entry.Fee(0LL).FromTx(tx6));
363363
BOOST_CHECK_EQUAL(pool.size(), 6U);
@@ -376,7 +376,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
376376
tx7.vout.resize(1);
377377
tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
378378
tx7.vout[0].nValue = 10 * COIN;
379-
uint64_t tx7Size = GetVirtualTransactionSize(tx7);
379+
uint64_t tx7Size = GetVirtualTransactionSize(CTransaction(tx7));
380380

381381
/* set the fee to just below tx2's feerate when including ancestor */
382382
CAmount fee = (20000/tx2Size)*(tx7Size + tx6Size) - 1;
@@ -464,12 +464,12 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
464464
BOOST_CHECK(pool.exists(tx2.GetHash()));
465465
BOOST_CHECK(pool.exists(tx3.GetHash()));
466466

467-
pool.TrimToSize(GetVirtualTransactionSize(tx1)); // mempool is limited to tx1's size in memory usage, so nothing fits
467+
pool.TrimToSize(GetVirtualTransactionSize(CTransaction(tx1))); // mempool is limited to tx1's size in memory usage, so nothing fits
468468
BOOST_CHECK(!pool.exists(tx1.GetHash()));
469469
BOOST_CHECK(!pool.exists(tx2.GetHash()));
470470
BOOST_CHECK(!pool.exists(tx3.GetHash()));
471471

472-
CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(tx3) + GetVirtualTransactionSize(tx2));
472+
CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2)));
473473
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
474474

475475
CMutableTransaction tx4 = CMutableTransaction();

src/test/miner_tests.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ static void TestPackageSelection(const CChainParams& chainparams, const CScript&
159159
// Test that packages above the min relay fee do get included, even if one
160160
// of the transactions is below the min relay fee
161161
// Remove the low fee transaction and replace with a higher fee transaction
162-
mempool.removeRecursive(tx);
162+
mempool.removeRecursive(CTransaction(tx));
163163
tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
164164
hashLowFeeTx = tx.GetHash();
165165
mempool.addUnchecked(entry.Fee(feeToUse+2).FromTx(tx));
@@ -441,22 +441,22 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
441441
tx.nLockTime = 0;
442442
hash = tx.GetHash();
443443
mempool.addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
444-
BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
445-
BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
446-
BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 2))); // Sequence locks pass on 2nd block
444+
BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
445+
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
446+
BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 2))); // Sequence locks pass on 2nd block
447447

448448
// relative time locked
449449
tx.vin[0].prevout.hash = txFirst[1]->GetHash();
450450
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((chainActive.Tip()->GetMedianTimePast()+1-chainActive[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block
451451
prevheights[0] = baseheight + 2;
452452
hash = tx.GetHash();
453453
mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx));
454-
BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
455-
BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
454+
BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
455+
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
456456

457457
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
458458
chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
459-
BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later
459+
BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later
460460
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
461461
chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP
462462

@@ -467,9 +467,9 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
467467
tx.nLockTime = chainActive.Tip()->nHeight + 1;
468468
hash = tx.GetHash();
469469
mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx));
470-
BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails
471-
BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
472-
BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
470+
BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails
471+
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
472+
BOOST_CHECK(IsFinalTx(CTransaction(tx), chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
473473

474474
// absolute time locked
475475
tx.vin[0].prevout.hash = txFirst[3]->GetHash();
@@ -478,23 +478,23 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
478478
prevheights[0] = baseheight + 4;
479479
hash = tx.GetHash();
480480
mempool.addUnchecked(entry.Time(GetTime()).FromTx(tx));
481-
BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails
482-
BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
483-
BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
481+
BOOST_CHECK(!CheckFinalTx(CTransaction(tx), flags)); // Locktime fails
482+
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
483+
BOOST_CHECK(IsFinalTx(CTransaction(tx), chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
484484

485485
// mempool-dependent transactions (not added)
486486
tx.vin[0].prevout.hash = hash;
487487
prevheights[0] = chainActive.Tip()->nHeight + 1;
488488
tx.nLockTime = 0;
489489
tx.vin[0].nSequence = 0;
490-
BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
491-
BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
490+
BOOST_CHECK(CheckFinalTx(CTransaction(tx), flags)); // Locktime passes
491+
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
492492
tx.vin[0].nSequence = 1;
493-
BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
493+
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
494494
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
495-
BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
495+
BOOST_CHECK(TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks pass
496496
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
497-
BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
497+
BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); // Sequence locks fail
498498

499499
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
500500

src/test/multisig_tests.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,20 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
7676
// Test a AND b:
7777
keys.assign(1,key[0]);
7878
keys.push_back(key[1]);
79-
s = sign_multisig(a_and_b, keys, txTo[0], 0);
79+
s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
8080
BOOST_CHECK(VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err));
8181
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
8282

8383
for (int i = 0; i < 4; i++)
8484
{
8585
keys.assign(1,key[i]);
86-
s = sign_multisig(a_and_b, keys, txTo[0], 0);
86+
s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
8787
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i));
8888
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
8989

9090
keys.assign(1,key[1]);
9191
keys.push_back(key[i]);
92-
s = sign_multisig(a_and_b, keys, txTo[0], 0);
92+
s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
9393
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i));
9494
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
9595
}
@@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
9898
for (int i = 0; i < 4; i++)
9999
{
100100
keys.assign(1,key[i]);
101-
s = sign_multisig(a_or_b, keys, txTo[1], 0);
101+
s = sign_multisig(a_or_b, keys, CTransaction(txTo[1]), 0);
102102
if (i == 0 || i == 1)
103103
{
104104
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
@@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
121121
{
122122
keys.assign(1,key[i]);
123123
keys.push_back(key[j]);
124-
s = sign_multisig(escrow, keys, txTo[2], 0);
124+
s = sign_multisig(escrow, keys, CTransaction(txTo[2]), 0);
125125
if (i < j && i < 3 && j < 3)
126126
{
127127
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j));
@@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
209209

210210
for (int i = 0; i < 3; i++)
211211
{
212-
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
212+
BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
213213
}
214214
}
215215

src/test/policyestimator_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
4444
tx.vin[0].scriptSig = garbage;
4545
tx.vout.resize(1);
4646
tx.vout[0].nValue=0LL;
47-
CFeeRate baseRate(basefee, GetVirtualTransactionSize(tx));
47+
CFeeRate baseRate(basefee, GetVirtualTransactionSize(CTransaction(tx)));
4848

4949
// Create a fake block
5050
std::vector<CTransactionRef> block;

0 commit comments

Comments
 (0)