mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
[validation] add TxValidationResult::TX_RECONSIDERABLE, TX_UNKNOWN
With package validation rules, transactions that fail individually may sometimes be eligible for reconsideration if submitted as part of a (different) package. For now, that includes trasactions that failed for being too low feerate. Add a new TxValidationResult type to distinguish these failures from others. In the next commits, we will abort package validation if a tx fails for any other reason. In the future, we will also decide whether to cache failures in recent_rejects based on this result (we won't want to reject a package containing a transaction that was rejected previously for being low feerate). Package validation also sometimes elects to skip some transactions when it knows the package will not be submitted in order to quit sooner. Add a result to specify this situation; we also don't want to cache these as rejections.
This commit is contained in:
parent
5c786a026a
commit
3979f1afcb
@ -54,6 +54,8 @@ enum class TxValidationResult {
|
||||
TX_CONFLICT,
|
||||
TX_MEMPOOL_POLICY, //!< violated mempool's fee/size/descendant/RBF/etc limits
|
||||
TX_NO_MEMPOOL, //!< this node does not have a mempool so can't validate the transaction
|
||||
TX_RECONSIDERABLE, //!< fails some policy, but might be acceptable if submitted in a (different) package
|
||||
TX_UNKNOWN, //!< transaction was not validated because package failed
|
||||
};
|
||||
|
||||
/** A "reason" why a block was invalid, suitable for determining whether the
|
||||
|
@ -1820,6 +1820,8 @@ bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationStat
|
||||
case TxValidationResult::TX_CONFLICT:
|
||||
case TxValidationResult::TX_MEMPOOL_POLICY:
|
||||
case TxValidationResult::TX_NO_MEMPOOL:
|
||||
case TxValidationResult::TX_RECONSIDERABLE:
|
||||
case TxValidationResult::TX_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
@ -670,11 +670,11 @@ private:
|
||||
AssertLockHeld(m_pool.cs);
|
||||
CAmount mempoolRejectFee = m_pool.GetMinFee().GetFee(package_size);
|
||||
if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
|
||||
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
|
||||
}
|
||||
|
||||
if (package_fee < m_pool.m_min_relay_feerate.GetFee(package_size)) {
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
|
||||
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "min relay fee not met",
|
||||
strprintf("%d < %d", package_fee, m_pool.m_min_relay_feerate.GetFee(package_size)));
|
||||
}
|
||||
return true;
|
||||
@ -867,6 +867,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
||||
// method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
|
||||
// due to a replacement.
|
||||
if (!bypass_limits && ws.m_modified_fees < m_pool.m_min_relay_feerate.GetFee(ws.m_vsize)) {
|
||||
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
|
||||
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
|
||||
strprintf("%d < %d", ws.m_modified_fees, m_pool.m_min_relay_feerate.GetFee(ws.m_vsize)));
|
||||
}
|
||||
@ -981,6 +983,9 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
||||
// descendant transaction of a direct conflict to pay a higher feerate than the transaction that
|
||||
// might replace them, under these rules.
|
||||
if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
|
||||
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
|
||||
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
|
||||
// This must be changed if package RBF is enabled.
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
|
||||
}
|
||||
|
||||
@ -1002,6 +1007,9 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
|
||||
}
|
||||
if (const auto err_string{PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
|
||||
m_pool.m_incremental_relay_feerate, hash)}) {
|
||||
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
|
||||
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
|
||||
// This must be changed if package RBF is enabled.
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
|
||||
}
|
||||
return true;
|
||||
@ -1139,7 +1147,8 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
|
||||
if (!args.m_package_submission && !bypass_limits) {
|
||||
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
|
||||
if (!m_pool.exists(GenTxid::Txid(hash)))
|
||||
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
|
||||
// The tx no longer meets our (new) mempool minimum feerate but could be reconsidered in a package.
|
||||
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "mempool full");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1510,7 +1519,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
|
||||
// in package validation, because its fees should only be "used" once.
|
||||
assert(m_pool.exists(GenTxid::Wtxid(wtxid)));
|
||||
results_final.emplace(wtxid, single_res);
|
||||
} else if (single_res.m_state.GetResult() != TxValidationResult::TX_MEMPOOL_POLICY &&
|
||||
} else if (single_res.m_state.GetResult() != TxValidationResult::TX_RECONSIDERABLE &&
|
||||
single_res.m_state.GetResult() != TxValidationResult::TX_MISSING_INPUTS) {
|
||||
// Package validation policy only differs from individual policy in its evaluation
|
||||
// of feerate. For example, if a transaction fails here due to violation of a
|
||||
|
Loading…
Reference in New Issue
Block a user