Skip to content

Commit 36a8441

Browse files
committed
[validation/rpc] cache + use vsize calculated in PreChecks
This is not only cleaner but also helps make sure we are always using the virtual size measure that includes the sigop weight heuristic (which is the vsize the mempool would return).
1 parent 8fa2936 commit 36a8441

File tree

3 files changed

+20
-13
lines changed

3 files changed

+20
-13
lines changed

src/rpc/rawtransaction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ static RPCHelpMan testmempoolaccept()
977977
if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
978978
const CAmount fee = tx_result.m_base_fees.value();
979979
// Check that fee does not exceed maximum fee
980-
const int64_t virtual_size = GetVirtualTransactionSize(*tx);
980+
const int64_t virtual_size = tx_result.m_vsize.value();
981981
const CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
982982
if (max_raw_tx_fee && fee > max_raw_tx_fee) {
983983
result_inner.pushKV("allowed", false);

src/validation.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,9 @@ class MemPoolAccept
503503
std::unique_ptr<CTxMemPoolEntry> m_entry;
504504
std::list<CTransactionRef> m_replaced_transactions;
505505

506+
/** Virtual size of the transaction as used by the mempool, calculated using serialized size
507+
* of the transaction and sigops. */
508+
int64_t m_vsize;
506509
CAmount m_base_fees;
507510
CAmount m_modified_fees;
508511
/** Total modified fees of all transactions being replaced. */
@@ -732,15 +735,15 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
732735

733736
entry.reset(new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
734737
fSpendsCoinbase, nSigOpsCost, lp));
735-
unsigned int nSize = entry->GetTxSize();
738+
ws.m_vsize = entry->GetTxSize();
736739

737740
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
738741
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
739742
strprintf("%d", nSigOpsCost));
740743

741744
// No transactions are allowed below minRelayTxFee except from disconnected
742745
// blocks
743-
if (!bypass_limits && !CheckFeeRate(nSize, nModifiedFees, state)) return false;
746+
if (!bypass_limits && !CheckFeeRate(ws.m_vsize, nModifiedFees, state)) return false;
744747

745748
const CTxMemPool::setEntries setIterConflicting = m_pool.GetIterSet(setConflicts);
746749
// Calculate in-mempool ancestors, up to a limit.
@@ -795,7 +798,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
795798
// to be secure by simply only having two immediately-spendable
796799
// outputs - one for each counterparty. For more info on the uses for
797800
// this, see https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html
798-
if (nSize > EXTRA_DESCENDANT_TX_SIZE_LIMIT ||
801+
if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT ||
799802
!m_pool.CalculateMemPoolAncestors(*entry, setAncestors, 2, m_limit_ancestor_size, m_limit_descendants + 1, m_limit_descendant_size + EXTRA_DESCENDANT_TX_SIZE_LIMIT, dummy_err_string)) {
800803
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", errString);
801804
}
@@ -813,7 +816,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
813816

814817
m_rbf = !setConflicts.empty();
815818
if (m_rbf) {
816-
CFeeRate newFeeRate(nModifiedFees, nSize);
819+
CFeeRate newFeeRate(nModifiedFees, ws.m_vsize);
817820
// It's possible that the replacement pays more fees than its direct conflicts but not more
818821
// than all conflicts (i.e. the direct conflicts have high-fee descendants). However, if the
819822
// replacement doesn't pay more fees than its direct conflicts, then we can be sure it's not
@@ -841,7 +844,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
841844
nConflictingFees += it->GetModifiedFee();
842845
nConflictingSize += it->GetTxSize();
843846
}
844-
if (const auto err_string{PaysForRBF(nConflictingFees, nModifiedFees, nSize, ::incrementalRelayFee, hash)}) {
847+
if (const auto err_string{PaysForRBF(nConflictingFees, nModifiedFees, ws.m_vsize,
848+
::incrementalRelayFee, hash)}) {
845849
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
846850
}
847851
}
@@ -967,14 +971,14 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
967971

968972
// Tx was accepted, but not added
969973
if (args.m_test_accept) {
970-
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_base_fees);
974+
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees);
971975
}
972976

973977
if (!Finalize(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
974978

975979
GetMainSignals().TransactionAddedToMempool(ptx, m_pool.GetAndIncrementSequence());
976980

977-
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_base_fees);
981+
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees);
978982
}
979983

980984
PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::vector<CTransactionRef>& txns, ATMPArgs& args)
@@ -1033,7 +1037,8 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
10331037
// When test_accept=true, transactions that pass PolicyScriptChecks are valid because there are
10341038
// no further mempool checks (passing PolicyScriptChecks implies passing ConsensusScriptChecks).
10351039
results.emplace(ws.m_ptx->GetWitnessHash(),
1036-
MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_base_fees));
1040+
MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions),
1041+
ws.m_vsize, ws.m_base_fees));
10371042
}
10381043
}
10391044

src/validation.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,16 @@ struct MempoolAcceptResult {
158158
// The following fields are only present when m_result_type = ResultType::VALID
159159
/** Mempool transactions replaced by the tx per BIP 125 rules. */
160160
const std::optional<std::list<CTransactionRef>> m_replaced_transactions;
161+
/** Virtual size as used by the mempool, calculated using serialized size and sigops. */
162+
const std::optional<int64_t> m_vsize;
161163
/** Raw base fees in satoshis. */
162164
const std::optional<CAmount> m_base_fees;
163165
static MempoolAcceptResult Failure(TxValidationState state) {
164166
return MempoolAcceptResult(state);
165167
}
166168

167-
static MempoolAcceptResult Success(std::list<CTransactionRef>&& replaced_txns, CAmount fees) {
168-
return MempoolAcceptResult(std::move(replaced_txns), fees);
169+
static MempoolAcceptResult Success(std::list<CTransactionRef>&& replaced_txns, int64_t vsize, CAmount fees) {
170+
return MempoolAcceptResult(std::move(replaced_txns), vsize, fees);
169171
}
170172

171173
// Private constructors. Use static methods MempoolAcceptResult::Success, etc. to construct.
@@ -177,9 +179,9 @@ struct MempoolAcceptResult {
177179
}
178180

179181
/** Constructor for success case */
180-
explicit MempoolAcceptResult(std::list<CTransactionRef>&& replaced_txns, CAmount fees)
182+
explicit MempoolAcceptResult(std::list<CTransactionRef>&& replaced_txns, int64_t vsize, CAmount fees)
181183
: m_result_type(ResultType::VALID),
182-
m_replaced_transactions(std::move(replaced_txns)), m_base_fees(fees) {}
184+
m_replaced_transactions(std::move(replaced_txns)), m_vsize{vsize}, m_base_fees(fees) {}
183185
};
184186

185187
/**

0 commit comments

Comments
 (0)