aboutsummaryrefslogtreecommitdiff
path: root/src/validation.h
diff options
context:
space:
mode:
authorglozow <gloriajzhao@gmail.com>2021-08-23 16:57:10 +0100
committerglozow <gloriajzhao@gmail.com>2021-11-29 15:46:48 +0000
commite12fafda2dfbbdf63f125e5af797ecfaa6488f66 (patch)
tree35bb2be46723a36f0cd474e53cc74c887c623447 /src/validation.h
parent8310d942e046c5a9b6bd90afdcd3af68dd91e081 (diff)
downloadbitcoin-e12fafda2dfbbdf63f125e5af797ecfaa6488f66.tar.xz
[validation] de-duplicate package transactions already in mempool
As node operators are free to set their mempool policies however they please, it's possible for package transaction(s) to already be in the mempool. We definitely don't want to reject the entire package in that case (as that could be a censorship vector). We should still return the successful result to the caller, so add another result type to MempoolAcceptResult.
Diffstat (limited to 'src/validation.h')
-rw-r--r--src/validation.h14
1 files changed, 12 insertions, 2 deletions
diff --git a/src/validation.h b/src/validation.h
index e3ad5f2e9f..e53ef53b07 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -161,17 +161,19 @@ struct MempoolAcceptResult {
enum class ResultType {
VALID, //!> Fully validated, valid.
INVALID, //!> Invalid.
+ MEMPOOL_ENTRY, //!> Valid, transaction was already in the mempool.
};
const ResultType m_result_type;
const TxValidationState m_state;
- // The following fields are only present when m_result_type = ResultType::VALID
+ // The following fields are only present when m_result_type = ResultType::VALID or MEMPOOL_ENTRY
/** Mempool transactions replaced by the tx per BIP 125 rules. */
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. */
const std::optional<CAmount> m_base_fees;
+
static MempoolAcceptResult Failure(TxValidationState state) {
return MempoolAcceptResult(state);
}
@@ -180,6 +182,10 @@ struct MempoolAcceptResult {
return MempoolAcceptResult(std::move(replaced_txns), vsize, fees);
}
+ static MempoolAcceptResult MempoolTx(int64_t vsize, CAmount fees) {
+ return MempoolAcceptResult(vsize, fees);
+ }
+
// Private constructors. Use static methods MempoolAcceptResult::Success, etc. to construct.
private:
/** Constructor for failure case */
@@ -192,6 +198,10 @@ private:
explicit MempoolAcceptResult(std::list<CTransactionRef>&& replaced_txns, int64_t vsize, CAmount fees)
: m_result_type(ResultType::VALID),
m_replaced_transactions(std::move(replaced_txns)), m_vsize{vsize}, m_base_fees(fees) {}
+
+ /** Constructor for already-in-mempool case. It wouldn't replace any transactions. */
+ explicit MempoolAcceptResult(int64_t vsize, CAmount fees)
+ : m_result_type(ResultType::MEMPOOL_ENTRY), m_vsize{vsize}, m_base_fees(fees) {}
};
/**
@@ -201,7 +211,7 @@ struct PackageMempoolAcceptResult
{
const PackageValidationState m_state;
/**
- * Map from wtxid to finished MempoolAcceptResults. The client is responsible
+ * Map from (w)txid to finished MempoolAcceptResults. The client is responsible
* for keeping track of the transaction objects themselves. If a result is not
* present, it means validation was unfinished for that transaction. If there
* was a package-wide error (see result in m_state), m_tx_results will be empty.