[packages] return DIFFERENT_WITNESS for same-txid-different-witness tx

The previous interface required callers to guess that the tx had been
swapped and look up the tx again by txid to find a `MEMPOOL_ENTRY`
result. This is a confusing interface.

Instead, explicitly tell the caller that this transaction was
`DIFFERENT_WITNESS` in the result linked to the mempool entry's wtxid.
This gives the caller all the information they need in 1 lookup, and
they can query the mempool for the other transaction if needed.
This commit is contained in:
glozow 2021-12-17 14:06:16 +00:00
parent 38146a4bd2
commit 83d4fb7126
2 changed files with 20 additions and 3 deletions

View File

@ -1274,9 +1274,10 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
// transaction for the mempool one. Note that we are ignoring the validity of the // transaction for the mempool one. Note that we are ignoring the validity of the
// package transaction passed in. // package transaction passed in.
// TODO: allow witness replacement in packages. // TODO: allow witness replacement in packages.
auto iter = m_pool.GetIter(wtxid); auto iter = m_pool.GetIter(txid);
assert(iter != std::nullopt); assert(iter != std::nullopt);
results.emplace(txid, MempoolAcceptResult::MempoolTx(iter.value()->GetTxSize(), iter.value()->GetFee())); // Provide the wtxid of the mempool tx so that the caller can look it up in the mempool.
results.emplace(wtxid, MempoolAcceptResult::MempoolTxDifferentWitness(iter.value()->GetTx().GetWitnessHash()));
} else { } else {
// Transaction does not already exist in the mempool. // Transaction does not already exist in the mempool.
txns_new.push_back(tx); txns_new.push_back(tx);

View File

@ -161,8 +161,12 @@ struct MempoolAcceptResult {
VALID, //!> Fully validated, valid. VALID, //!> Fully validated, valid.
INVALID, //!> Invalid. INVALID, //!> Invalid.
MEMPOOL_ENTRY, //!> Valid, transaction was already in the mempool. MEMPOOL_ENTRY, //!> Valid, transaction was already in the mempool.
DIFFERENT_WITNESS, //!> Not validated. A same-txid-different-witness tx (see m_other_wtxid) already exists in the mempool and was not replaced.
}; };
/** Result type. Present in all MempoolAcceptResults. */
const ResultType m_result_type; const ResultType m_result_type;
/** Contains information about why the transaction failed. */
const TxValidationState m_state; const TxValidationState m_state;
// The following fields are only present when m_result_type = ResultType::VALID or MEMPOOL_ENTRY // The following fields are only present when m_result_type = ResultType::VALID or MEMPOOL_ENTRY
@ -173,6 +177,10 @@ struct MempoolAcceptResult {
/** Raw base fees in satoshis. */ /** Raw base fees in satoshis. */
const std::optional<CAmount> m_base_fees; const std::optional<CAmount> m_base_fees;
// The following field is only present when m_result_type = ResultType::DIFFERENT_WITNESS
/** The wtxid of the transaction in the mempool which has the same txid but different witness. */
const std::optional<uint256> m_other_wtxid;
static MempoolAcceptResult Failure(TxValidationState state) { static MempoolAcceptResult Failure(TxValidationState state) {
return MempoolAcceptResult(state); return MempoolAcceptResult(state);
} }
@ -185,6 +193,10 @@ struct MempoolAcceptResult {
return MempoolAcceptResult(vsize, fees); return MempoolAcceptResult(vsize, fees);
} }
static MempoolAcceptResult MempoolTxDifferentWitness(const uint256& other_wtxid) {
return MempoolAcceptResult(other_wtxid);
}
// Private constructors. Use static methods MempoolAcceptResult::Success, etc. to construct. // Private constructors. Use static methods MempoolAcceptResult::Success, etc. to construct.
private: private:
/** Constructor for failure case */ /** Constructor for failure case */
@ -201,6 +213,10 @@ private:
/** Constructor for already-in-mempool case. It wouldn't replace any transactions. */ /** Constructor for already-in-mempool case. It wouldn't replace any transactions. */
explicit MempoolAcceptResult(int64_t vsize, CAmount fees) explicit MempoolAcceptResult(int64_t vsize, CAmount fees)
: m_result_type(ResultType::MEMPOOL_ENTRY), m_vsize{vsize}, m_base_fees(fees) {} : m_result_type(ResultType::MEMPOOL_ENTRY), m_vsize{vsize}, m_base_fees(fees) {}
/** Constructor for witness-swapped case. */
explicit MempoolAcceptResult(const uint256& other_wtxid)
: m_result_type(ResultType::DIFFERENT_WITNESS), m_other_wtxid(other_wtxid) {}
}; };
/** /**
@ -210,7 +226,7 @@ struct PackageMempoolAcceptResult
{ {
const PackageValidationState m_state; const PackageValidationState m_state;
/** /**
* Map from (w)txid to finished MempoolAcceptResults. The client is responsible * Map from wtxid to finished MempoolAcceptResults. The client is responsible
* for keeping track of the transaction objects themselves. If a result is not * for keeping track of the transaction objects themselves. If a result is not
* present, it means validation was unfinished for that transaction. If there * 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. * was a package-wide error (see result in m_state), m_tx_results will be empty.