Skip to content

Commit 3c2a41a

Browse files
committed
Merge #13011: Cache witness hash in CTransaction
fac1223 Cache witness hash in CTransaction (MarcoFalke) faab55f Make CMutableTransaction constructor explicit (MarcoFalke) Pull request description: This speeds up: * compactblocks (v2) * ATMP * validation and miner (via `BlockWitnessMerkleRoot`) * sigcache (see also unrelated #13204) * rpc and rest (nice, but irrelevant) This presumably slows down rescan, which uses a `CTransaction` and its `GetHash`, but never uses the `GetWitnessHash`. The slow down is proportional to the number of witness transactions in the rescan window. I.e. early in the chain there should be no measurable slow down. Later in the chain, there should be a slow down, but acceptable given the speedups in the modules mentioned above. Tree-SHA512: 443e86acfcceb5af2163e68840c581d44159af3fd1fce266cab3504b29fcd74c50812b69a00d41582e7e1c5ea292f420ce5e892cdfab691da9c24ed1c44536c7
2 parents b9551d3 + fac1223 commit 3c2a41a

File tree

8 files changed

+21
-23
lines changed

8 files changed

+21
-23
lines changed

src/bitcoin-tx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
546546
// mergedTx will end up with all the signatures; it
547547
// starts as a clone of the raw tx:
548548
CMutableTransaction mergedTx{tx};
549-
const CTransaction txv{tx};
549+
const CMutableTransaction txv{tx};
550550
CCoinsView viewDummy;
551551
CCoinsViewCache view(&viewDummy);
552552

src/primitives/transaction.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,18 @@ uint256 CTransaction::ComputeHash() const
6767
return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
6868
}
6969

70-
uint256 CTransaction::GetWitnessHash() const
70+
uint256 CTransaction::ComputeWitnessHash() const
7171
{
7272
if (!HasWitness()) {
73-
return GetHash();
73+
return hash;
7474
}
7575
return SerializeHash(*this, SER_GETHASH, 0);
7676
}
7777

7878
/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
79-
CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash() {}
80-
CTransaction::CTransaction(const CMutableTransaction &tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
81-
CTransaction::CTransaction(CMutableTransaction &&tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
79+
CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash{}, m_witness_hash{} {}
80+
CTransaction::CTransaction(const CMutableTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
81+
CTransaction::CTransaction(CMutableTransaction&& tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
8282

8383
CAmount CTransaction::GetValueOut() const
8484
{

src/primitives/transaction.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,10 @@ class CTransaction
286286
private:
287287
/** Memory only. */
288288
const uint256 hash;
289+
const uint256 m_witness_hash;
289290

290291
uint256 ComputeHash() const;
292+
uint256 ComputeWitnessHash() const;
291293

292294
public:
293295
/** Construct a CTransaction that qualifies as IsNull() */
@@ -311,12 +313,8 @@ class CTransaction
311313
return vin.empty() && vout.empty();
312314
}
313315

314-
const uint256& GetHash() const {
315-
return hash;
316-
}
317-
318-
// Compute a hash that includes both transaction and witness data
319-
uint256 GetWitnessHash() const;
316+
const uint256& GetHash() const { return hash; }
317+
const uint256& GetWitnessHash() const { return m_witness_hash; };
320318

321319
// Return sum of txouts.
322320
CAmount GetValueOut() const;
@@ -367,7 +365,7 @@ struct CMutableTransaction
367365
uint32_t nLockTime;
368366

369367
CMutableTransaction();
370-
CMutableTransaction(const CTransaction& tx);
368+
explicit CMutableTransaction(const CTransaction& tx);
371369

372370
template <typename Stream>
373371
inline void Serialize(Stream& s) const {

src/test/coins_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
312312
if (InsecureRandRange(10) == 0 && coinbase_coins.size()) {
313313
auto utxod = FindRandomFrom(coinbase_coins);
314314
// Reuse the exact same coinbase
315-
tx = std::get<0>(utxod->second);
315+
tx = CMutableTransaction{std::get<0>(utxod->second)};
316316
// shouldn't be available for reconnection if it's been duplicated
317317
disconnected_coins.erase(utxod->first);
318318

@@ -331,7 +331,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
331331
// 1/20 times reconnect a previously disconnected tx
332332
if (randiter % 20 == 2 && disconnected_coins.size()) {
333333
auto utxod = FindRandomFrom(disconnected_coins);
334-
tx = std::get<0>(utxod->second);
334+
tx = CMutableTransaction{std::get<0>(utxod->second)};
335335
prevout = tx.vin[0].prevout;
336336
if (!CTransaction(tx).IsCoinBase() && !utxoset.count(prevout)) {
337337
disconnected_coins.erase(utxod->first);

src/test/script_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int n
137137
return txCredit;
138138
}
139139

140-
CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CMutableTransaction& txCredit)
140+
CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit)
141141
{
142142
CMutableTransaction txSpend;
143143
txSpend.nVersion = 1;
@@ -163,7 +163,7 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript
163163
flags |= SCRIPT_VERIFY_WITNESS;
164164
}
165165
ScriptError err;
166-
CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey, nValue);
166+
const CTransaction txCredit{BuildCreditingTransaction(scriptPubKey, nValue)};
167167
CMutableTransaction tx = BuildSpendingTransaction(scriptSig, scriptWitness, txCredit);
168168
CMutableTransaction tx2 = tx;
169169
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message);
@@ -1073,7 +1073,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
10731073
CScript scriptPubKey12;
10741074
scriptPubKey12 << OP_1 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
10751075

1076-
CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12);
1076+
const CTransaction txFrom12{BuildCreditingTransaction(scriptPubKey12)};
10771077
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom12);
10781078

10791079
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
@@ -1104,7 +1104,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
11041104
CScript scriptPubKey23;
11051105
scriptPubKey23 << OP_2 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << ToByteVector(key3.GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
11061106

1107-
CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23);
1107+
const CTransaction txFrom23{BuildCreditingTransaction(scriptPubKey23)};
11081108
CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom23);
11091109

11101110
std::vector<CKey> keys;

src/test/txvalidationcache_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
2424
BOOST_AUTO_TEST_SUITE(tx_validationcache_tests)
2525

2626
static bool
27-
ToMemPool(CMutableTransaction& tx)
27+
ToMemPool(const CMutableTransaction& tx)
2828
{
2929
LOCK(cs_main);
3030

src/wallet/feebumper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
185185
// If the output is not large enough to pay the fee, fail.
186186
CAmount nDelta = new_fee - old_fee;
187187
assert(nDelta > 0);
188-
mtx = *wtx.tx;
188+
mtx = CMutableTransaction{*wtx.tx};
189189
CTxOut* poutput = &(mtx.vout[nOutput]);
190190
if (poutput->nValue < nDelta) {
191191
errors.push_back("Change output is too small to bump the fee");

src/wallet/wallet.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,8 +2075,8 @@ bool CWalletTx::IsTrusted() const
20752075

20762076
bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
20772077
{
2078-
CMutableTransaction tx1 = *this->tx;
2079-
CMutableTransaction tx2 = *_tx.tx;
2078+
CMutableTransaction tx1 {*this->tx};
2079+
CMutableTransaction tx2 {*_tx.tx};
20802080
for (auto& txin : tx1.vin) txin.scriptSig = CScript();
20812081
for (auto& txin : tx2.vin) txin.scriptSig = CScript();
20822082
return CTransaction(tx1) == CTransaction(tx2);

0 commit comments

Comments
 (0)