Skip to content

Commit 3979f1a

Browse files
committed
[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.
1 parent 5c786a0 commit 3979f1a

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

src/consensus/validation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ enum class TxValidationResult {
5454
TX_CONFLICT,
5555
TX_MEMPOOL_POLICY, //!< violated mempool's fee/size/descendant/RBF/etc limits
5656
TX_NO_MEMPOOL, //!< this node does not have a mempool so can't validate the transaction
57+
TX_RECONSIDERABLE, //!< fails some policy, but might be acceptable if submitted in a (different) package
58+
TX_UNKNOWN, //!< transaction was not validated because package failed
5759
};
5860

5961
/** A "reason" why a block was invalid, suitable for determining whether the

src/net_processing.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,8 @@ bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationStat
18201820
case TxValidationResult::TX_CONFLICT:
18211821
case TxValidationResult::TX_MEMPOOL_POLICY:
18221822
case TxValidationResult::TX_NO_MEMPOOL:
1823+
case TxValidationResult::TX_RECONSIDERABLE:
1824+
case TxValidationResult::TX_UNKNOWN:
18231825
break;
18241826
}
18251827
return false;

src/validation.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -670,11 +670,11 @@ class MemPoolAccept
670670
AssertLockHeld(m_pool.cs);
671671
CAmount mempoolRejectFee = m_pool.GetMinFee().GetFee(package_size);
672672
if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
673-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
673+
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
674674
}
675675

676676
if (package_fee < m_pool.m_min_relay_feerate.GetFee(package_size)) {
677-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
677+
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "min relay fee not met",
678678
strprintf("%d < %d", package_fee, m_pool.m_min_relay_feerate.GetFee(package_size)));
679679
}
680680
return true;
@@ -867,6 +867,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
867867
// method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
868868
// due to a replacement.
869869
if (!bypass_limits && ws.m_modified_fees < m_pool.m_min_relay_feerate.GetFee(ws.m_vsize)) {
870+
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
871+
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
870872
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
871873
strprintf("%d < %d", ws.m_modified_fees, m_pool.m_min_relay_feerate.GetFee(ws.m_vsize)));
872874
}
@@ -981,6 +983,9 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
981983
// descendant transaction of a direct conflict to pay a higher feerate than the transaction that
982984
// might replace them, under these rules.
983985
if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
986+
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
987+
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
988+
// This must be changed if package RBF is enabled.
984989
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
985990
}
986991

@@ -1002,6 +1007,9 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
10021007
}
10031008
if (const auto err_string{PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
10041009
m_pool.m_incremental_relay_feerate, hash)}) {
1010+
// Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
1011+
// TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
1012+
// This must be changed if package RBF is enabled.
10051013
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
10061014
}
10071015
return true;
@@ -1139,7 +1147,8 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
11391147
if (!args.m_package_submission && !bypass_limits) {
11401148
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
11411149
if (!m_pool.exists(GenTxid::Txid(hash)))
1142-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
1150+
// The tx no longer meets our (new) mempool minimum feerate but could be reconsidered in a package.
1151+
return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "mempool full");
11431152
}
11441153
return true;
11451154
}
@@ -1510,7 +1519,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
15101519
// in package validation, because its fees should only be "used" once.
15111520
assert(m_pool.exists(GenTxid::Wtxid(wtxid)));
15121521
results_final.emplace(wtxid, single_res);
1513-
} else if (single_res.m_state.GetResult() != TxValidationResult::TX_MEMPOOL_POLICY &&
1522+
} else if (single_res.m_state.GetResult() != TxValidationResult::TX_RECONSIDERABLE &&
15141523
single_res.m_state.GetResult() != TxValidationResult::TX_MISSING_INPUTS) {
15151524
// Package validation policy only differs from individual policy in its evaluation
15161525
// of feerate. For example, if a transaction fails here due to violation of a

0 commit comments

Comments
 (0)