mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
[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).
This commit is contained in:
parent
8fa2936b34
commit
36a8441912
3 changed files with 20 additions and 13 deletions
|
@ -977,7 +977,7 @@ static RPCHelpMan testmempoolaccept()
|
||||||
if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
|
||||||
const CAmount fee = tx_result.m_base_fees.value();
|
const CAmount fee = tx_result.m_base_fees.value();
|
||||||
// Check that fee does not exceed maximum fee
|
// Check that fee does not exceed maximum fee
|
||||||
const int64_t virtual_size = GetVirtualTransactionSize(*tx);
|
const int64_t virtual_size = tx_result.m_vsize.value();
|
||||||
const CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
|
const CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
|
||||||
if (max_raw_tx_fee && fee > max_raw_tx_fee) {
|
if (max_raw_tx_fee && fee > max_raw_tx_fee) {
|
||||||
result_inner.pushKV("allowed", false);
|
result_inner.pushKV("allowed", false);
|
||||||
|
|
|
@ -503,6 +503,9 @@ private:
|
||||||
std::unique_ptr<CTxMemPoolEntry> m_entry;
|
std::unique_ptr<CTxMemPoolEntry> m_entry;
|
||||||
std::list<CTransactionRef> m_replaced_transactions;
|
std::list<CTransactionRef> m_replaced_transactions;
|
||||||
|
|
||||||
|
/** Virtual size of the transaction as used by the mempool, calculated using serialized size
|
||||||
|
* of the transaction and sigops. */
|
||||||
|
int64_t m_vsize;
|
||||||
CAmount m_base_fees;
|
CAmount m_base_fees;
|
||||||
CAmount m_modified_fees;
|
CAmount m_modified_fees;
|
||||||
/** Total modified fees of all transactions being replaced. */
|
/** Total modified fees of all transactions being replaced. */
|
||||||
|
@ -732,7 +735,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||||
|
|
||||||
entry.reset(new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
|
entry.reset(new CTxMemPoolEntry(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(),
|
||||||
fSpendsCoinbase, nSigOpsCost, lp));
|
fSpendsCoinbase, nSigOpsCost, lp));
|
||||||
unsigned int nSize = entry->GetTxSize();
|
ws.m_vsize = entry->GetTxSize();
|
||||||
|
|
||||||
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
|
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
|
||||||
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
||||||
|
@ -740,7 +743,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||||
|
|
||||||
// No transactions are allowed below minRelayTxFee except from disconnected
|
// No transactions are allowed below minRelayTxFee except from disconnected
|
||||||
// blocks
|
// blocks
|
||||||
if (!bypass_limits && !CheckFeeRate(nSize, nModifiedFees, state)) return false;
|
if (!bypass_limits && !CheckFeeRate(ws.m_vsize, nModifiedFees, state)) return false;
|
||||||
|
|
||||||
const CTxMemPool::setEntries setIterConflicting = m_pool.GetIterSet(setConflicts);
|
const CTxMemPool::setEntries setIterConflicting = m_pool.GetIterSet(setConflicts);
|
||||||
// Calculate in-mempool ancestors, up to a limit.
|
// Calculate in-mempool ancestors, up to a limit.
|
||||||
|
@ -795,7 +798,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||||
// to be secure by simply only having two immediately-spendable
|
// to be secure by simply only having two immediately-spendable
|
||||||
// outputs - one for each counterparty. For more info on the uses for
|
// outputs - one for each counterparty. For more info on the uses for
|
||||||
// this, see https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html
|
// this, see https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-November/016518.html
|
||||||
if (nSize > EXTRA_DESCENDANT_TX_SIZE_LIMIT ||
|
if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT ||
|
||||||
!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)) {
|
!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)) {
|
||||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", errString);
|
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", errString);
|
||||||
}
|
}
|
||||||
|
@ -813,7 +816,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||||
|
|
||||||
m_rbf = !setConflicts.empty();
|
m_rbf = !setConflicts.empty();
|
||||||
if (m_rbf) {
|
if (m_rbf) {
|
||||||
CFeeRate newFeeRate(nModifiedFees, nSize);
|
CFeeRate newFeeRate(nModifiedFees, ws.m_vsize);
|
||||||
// It's possible that the replacement pays more fees than its direct conflicts but not more
|
// It's possible that the replacement pays more fees than its direct conflicts but not more
|
||||||
// than all conflicts (i.e. the direct conflicts have high-fee descendants). However, if the
|
// than all conflicts (i.e. the direct conflicts have high-fee descendants). However, if the
|
||||||
// replacement doesn't pay more fees than its direct conflicts, then we can be sure it's not
|
// 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)
|
||||||
nConflictingFees += it->GetModifiedFee();
|
nConflictingFees += it->GetModifiedFee();
|
||||||
nConflictingSize += it->GetTxSize();
|
nConflictingSize += it->GetTxSize();
|
||||||
}
|
}
|
||||||
if (const auto err_string{PaysForRBF(nConflictingFees, nModifiedFees, nSize, ::incrementalRelayFee, hash)}) {
|
if (const auto err_string{PaysForRBF(nConflictingFees, nModifiedFees, ws.m_vsize,
|
||||||
|
::incrementalRelayFee, hash)}) {
|
||||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
|
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -967,14 +971,14 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
|
||||||
|
|
||||||
// Tx was accepted, but not added
|
// Tx was accepted, but not added
|
||||||
if (args.m_test_accept) {
|
if (args.m_test_accept) {
|
||||||
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_base_fees);
|
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Finalize(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
|
if (!Finalize(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
|
||||||
|
|
||||||
GetMainSignals().TransactionAddedToMempool(ptx, m_pool.GetAndIncrementSequence());
|
GetMainSignals().TransactionAddedToMempool(ptx, m_pool.GetAndIncrementSequence());
|
||||||
|
|
||||||
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_base_fees);
|
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees);
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::vector<CTransactionRef>& txns, ATMPArgs& args)
|
PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::vector<CTransactionRef>& txns, ATMPArgs& args)
|
||||||
|
@ -1033,7 +1037,8 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
|
||||||
// When test_accept=true, transactions that pass PolicyScriptChecks are valid because there are
|
// When test_accept=true, transactions that pass PolicyScriptChecks are valid because there are
|
||||||
// no further mempool checks (passing PolicyScriptChecks implies passing ConsensusScriptChecks).
|
// no further mempool checks (passing PolicyScriptChecks implies passing ConsensusScriptChecks).
|
||||||
results.emplace(ws.m_ptx->GetWitnessHash(),
|
results.emplace(ws.m_ptx->GetWitnessHash(),
|
||||||
MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_base_fees));
|
MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions),
|
||||||
|
ws.m_vsize, ws.m_base_fees));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,14 +158,16 @@ struct MempoolAcceptResult {
|
||||||
// The following fields are only present when m_result_type = ResultType::VALID
|
// The following fields are only present when m_result_type = ResultType::VALID
|
||||||
/** Mempool transactions replaced by the tx per BIP 125 rules. */
|
/** Mempool transactions replaced by the tx per BIP 125 rules. */
|
||||||
const std::optional<std::list<CTransactionRef>> m_replaced_transactions;
|
const std::optional<std::list<CTransactionRef>> m_replaced_transactions;
|
||||||
|
/** Virtual size as used by the mempool, calculated using serialized size and sigops. */
|
||||||
|
const std::optional<int64_t> m_vsize;
|
||||||
/** Raw base fees in satoshis. */
|
/** Raw base fees in satoshis. */
|
||||||
const std::optional<CAmount> m_base_fees;
|
const std::optional<CAmount> m_base_fees;
|
||||||
static MempoolAcceptResult Failure(TxValidationState state) {
|
static MempoolAcceptResult Failure(TxValidationState state) {
|
||||||
return MempoolAcceptResult(state);
|
return MempoolAcceptResult(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MempoolAcceptResult Success(std::list<CTransactionRef>&& replaced_txns, CAmount fees) {
|
static MempoolAcceptResult Success(std::list<CTransactionRef>&& replaced_txns, int64_t vsize, CAmount fees) {
|
||||||
return MempoolAcceptResult(std::move(replaced_txns), fees);
|
return MempoolAcceptResult(std::move(replaced_txns), vsize, fees);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private constructors. Use static methods MempoolAcceptResult::Success, etc. to construct.
|
// Private constructors. Use static methods MempoolAcceptResult::Success, etc. to construct.
|
||||||
|
@ -177,9 +179,9 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructor for success case */
|
/** Constructor for success case */
|
||||||
explicit MempoolAcceptResult(std::list<CTransactionRef>&& replaced_txns, CAmount fees)
|
explicit MempoolAcceptResult(std::list<CTransactionRef>&& replaced_txns, int64_t vsize, CAmount fees)
|
||||||
: m_result_type(ResultType::VALID),
|
: m_result_type(ResultType::VALID),
|
||||||
m_replaced_transactions(std::move(replaced_txns)), m_base_fees(fees) {}
|
m_replaced_transactions(std::move(replaced_txns)), m_vsize{vsize}, m_base_fees(fees) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue