Skip to content

Commit d6c7b78

Browse files
committed
[validation] return wtxids of other transactions whose fees were used
1 parent 1605886 commit d6c7b78

File tree

3 files changed

+55
-11
lines changed

3 files changed

+55
-11
lines changed

src/test/txpackage_tests.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,17 @@ BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100Setup)
9696
BOOST_CHECK_MESSAGE(it_parent->second.m_state.IsValid(),
9797
"Package validation unexpectedly failed: " << it_parent->second.m_state.GetRejectReason());
9898
BOOST_CHECK(it_parent->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_parent)) == COIN);
99+
BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().size(), 1);
100+
BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().front(), tx_parent->GetWitnessHash());
99101
BOOST_CHECK(it_child != result_parent_child.m_tx_results.end());
100102
BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(),
101103
"Package validation unexpectedly failed: " << it_child->second.m_state.GetRejectReason());
102104
BOOST_CHECK(result_parent_child.m_package_feerate.has_value());
103105
BOOST_CHECK(result_parent_child.m_package_feerate.value() ==
104106
CFeeRate(2 * COIN, GetVirtualTransactionSize(*tx_parent) + GetVirtualTransactionSize(*tx_child)));
105107
BOOST_CHECK(it_child->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_child)) == COIN);
108+
BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().size(), 1);
109+
BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().front(), tx_child->GetWitnessHash());
106110

107111
// A single, giant transaction submitted through ProcessNewPackage fails on single tx policy.
108112
CTransactionRef giant_ptx = create_placeholder_tx(999, 999);
@@ -326,9 +330,13 @@ BOOST_FIXTURE_TEST_CASE(package_submission_tests, TestChain100Setup)
326330
BOOST_CHECK(it_parent != submit_parent_child.m_tx_results.end());
327331
BOOST_CHECK(it_parent->second.m_state.IsValid());
328332
BOOST_CHECK(it_parent->second.m_effective_feerate == CFeeRate(1 * COIN, GetVirtualTransactionSize(*tx_parent)));
333+
BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().size(), 1);
334+
BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().front(), tx_parent->GetWitnessHash());
329335
BOOST_CHECK(it_child != submit_parent_child.m_tx_results.end());
330336
BOOST_CHECK(it_child->second.m_state.IsValid());
331337
BOOST_CHECK(it_child->second.m_effective_feerate == CFeeRate(1 * COIN, GetVirtualTransactionSize(*tx_child)));
338+
BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().size(), 1);
339+
BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().front(), tx_child->GetWitnessHash());
332340

333341
BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size);
334342
BOOST_CHECK(m_node.mempool->exists(GenTxid::Txid(tx_parent->GetHash())));
@@ -619,6 +627,9 @@ BOOST_FIXTURE_TEST_CASE(package_witness_swap_tests, TestChain100Setup)
619627
mixed_result.m_package_feerate.value().ToString()));
620628
BOOST_CHECK(it_parent3->second.m_effective_feerate.value() == expected_feerate);
621629
BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate);
630+
std::vector<uint256> expected_wtxids({ptx_parent3->GetWitnessHash(), ptx_mixed_child->GetWitnessHash()});
631+
BOOST_CHECK(it_parent3->second.m_wtxids_fee_calculations.value() == expected_wtxids);
632+
BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids);
622633
}
623634
}
624635

@@ -703,6 +714,9 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
703714
GetVirtualTransactionSize(*tx_parent) + GetVirtualTransactionSize(*tx_child));
704715
BOOST_CHECK(it_parent->second.m_effective_feerate.value() == expected_feerate);
705716
BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate);
717+
std::vector<uint256> expected_wtxids({tx_parent->GetWitnessHash(), tx_child->GetWitnessHash()});
718+
BOOST_CHECK(it_parent->second.m_wtxids_fee_calculations.value() == expected_wtxids);
719+
BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids);
706720
BOOST_CHECK(expected_feerate.GetFeePerK() > 1000);
707721
BOOST_CHECK(submit_cpfp.m_package_feerate.has_value());
708722
BOOST_CHECK_MESSAGE(submit_cpfp.m_package_feerate.value() == expected_feerate,
@@ -774,6 +788,9 @@ BOOST_FIXTURE_TEST_CASE(package_cpfp_tests, TestChain100Setup)
774788
BOOST_CHECK(it_child->second.m_result_type == MempoolAcceptResult::ResultType::VALID);
775789
BOOST_CHECK(it_child->second.m_base_fees.value() == 200);
776790
BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate);
791+
std::vector<uint256> expected_wtxids({tx_parent_cheap->GetWitnessHash(), tx_child_cheap->GetWitnessHash()});
792+
BOOST_CHECK(it_parent->second.m_wtxids_fee_calculations.value() == expected_wtxids);
793+
BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids);
777794
}
778795

779796
// Package feerate is calculated without topology in mind; it's just aggregating fees and sizes.

src/validation.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,14 +1149,21 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
11491149
// make sure we haven't exceeded max mempool size.
11501150
LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
11511151

1152+
std::vector<uint256> all_package_wtxids;
1153+
all_package_wtxids.reserve(workspaces.size());
1154+
std::transform(workspaces.cbegin(), workspaces.cend(), std::back_inserter(all_package_wtxids),
1155+
[](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
11521156
// Find the wtxids of the transactions that made it into the mempool. Allow partial submission,
11531157
// but don't report success unless they all made it into the mempool.
11541158
for (Workspace& ws : workspaces) {
11551159
const auto effective_feerate = args.m_package_feerates ? ws.m_package_feerate :
11561160
CFeeRate{ws.m_modified_fees, static_cast<uint32_t>(ws.m_vsize)};
1161+
const auto effective_feerate_wtxids = args.m_package_feerates ? all_package_wtxids :
1162+
std::vector<uint256>({ws.m_ptx->GetWitnessHash()});
11571163
if (m_pool.exists(GenTxid::Wtxid(ws.m_ptx->GetWitnessHash()))) {
11581164
results.emplace(ws.m_ptx->GetWitnessHash(),
1159-
MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees, effective_feerate));
1165+
MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize,
1166+
ws.m_base_fees, effective_feerate, effective_feerate_wtxids));
11601167
GetMainSignals().TransactionAddedToMempool(ws.m_ptx, m_pool.GetAndIncrementSequence());
11611168
} else {
11621169
all_submitted = false;
@@ -1185,16 +1192,19 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
11851192
if (!ConsensusScriptChecks(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
11861193

11871194
const CFeeRate effective_feerate{ws.m_modified_fees, static_cast<uint32_t>(ws.m_vsize)};
1195+
const std::vector<uint256> single_wtxid{ws.m_ptx->GetWitnessHash()};
11881196
// Tx was accepted, but not added
11891197
if (args.m_test_accept) {
1190-
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees, effective_feerate);
1198+
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize,
1199+
ws.m_base_fees, effective_feerate, single_wtxid);
11911200
}
11921201

11931202
if (!Finalize(args, ws)) return MempoolAcceptResult::Failure(ws.m_state);
11941203

11951204
GetMainSignals().TransactionAddedToMempool(ptx, m_pool.GetAndIncrementSequence());
11961205

1197-
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees, effective_feerate);
1206+
return MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions), ws.m_vsize, ws.m_base_fees,
1207+
effective_feerate, single_wtxid);
11981208
}
11991209

12001210
PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::vector<CTransactionRef>& txns, ATMPArgs& args)
@@ -1252,6 +1262,10 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
12521262
return PackageMempoolAcceptResult(package_state, package_feerate, std::move(results));
12531263
}
12541264

1265+
std::vector<uint256> all_package_wtxids;
1266+
all_package_wtxids.reserve(workspaces.size());
1267+
std::transform(workspaces.cbegin(), workspaces.cend(), std::back_inserter(all_package_wtxids),
1268+
[](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
12551269
for (Workspace& ws : workspaces) {
12561270
ws.m_package_feerate = package_feerate;
12571271
if (!PolicyScriptChecks(args, ws)) {
@@ -1263,11 +1277,12 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
12631277
if (args.m_test_accept) {
12641278
const auto effective_feerate = args.m_package_feerates ? ws.m_package_feerate :
12651279
CFeeRate{ws.m_modified_fees, static_cast<uint32_t>(ws.m_vsize)};
1266-
// When test_accept=true, transactions that pass PolicyScriptChecks are valid because there are
1267-
// no further mempool checks (passing PolicyScriptChecks implies passing ConsensusScriptChecks).
1280+
const auto effective_feerate_wtxids = args.m_package_feerates ? all_package_wtxids :
1281+
std::vector<uint256>{ws.m_ptx->GetWitnessHash()};
12681282
results.emplace(ws.m_ptx->GetWitnessHash(),
12691283
MempoolAcceptResult::Success(std::move(ws.m_replaced_transactions),
1270-
ws.m_vsize, ws.m_base_fees, effective_feerate));
1284+
ws.m_vsize, ws.m_base_fees, effective_feerate,
1285+
effective_feerate_wtxids));
12711286
}
12721287
}
12731288

src/validation.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,16 @@ struct MempoolAcceptResult {
137137
/** The feerate at which this transaction was considered. This includes any fee delta added
138138
* using prioritisetransaction (i.e. modified fees). If this transaction was submitted as a
139139
* package, this is the package feerate, which may also include its descendants and/or
140-
* ancestors. Only present when m_result_type = ResultType::VALID. */
140+
* ancestors (see m_wtxids_fee_calculations below).
141+
* Only present when m_result_type = ResultType::VALID.
142+
*/
141143
const std::optional<CFeeRate> m_effective_feerate;
144+
/** Contains the wtxids of the transactions used for fee-related checks. Includes this
145+
* transaction's wtxid and may include others if this transaction was validated as part of a
146+
* package. This is not necessarily equivalent to the list of transactions passed to
147+
* ProcessNewPackage().
148+
* Only present when m_result_type = ResultType::VALID. */
149+
const std::optional<std::vector<uint256>> m_wtxids_fee_calculations;
142150

143151
// The following field is only present when m_result_type = ResultType::DIFFERENT_WITNESS
144152
/** The wtxid of the transaction in the mempool which has the same txid but different witness. */
@@ -151,8 +159,10 @@ struct MempoolAcceptResult {
151159
static MempoolAcceptResult Success(std::list<CTransactionRef>&& replaced_txns,
152160
int64_t vsize,
153161
CAmount fees,
154-
CFeeRate effective_feerate) {
155-
return MempoolAcceptResult(std::move(replaced_txns), vsize, fees, effective_feerate);
162+
CFeeRate effective_feerate,
163+
const std::vector<uint256>& wtxids_fee_calculations) {
164+
return MempoolAcceptResult(std::move(replaced_txns), vsize, fees,
165+
effective_feerate, wtxids_fee_calculations);
156166
}
157167

158168
static MempoolAcceptResult MempoolTx(int64_t vsize, CAmount fees) {
@@ -175,12 +185,14 @@ struct MempoolAcceptResult {
175185
explicit MempoolAcceptResult(std::list<CTransactionRef>&& replaced_txns,
176186
int64_t vsize,
177187
CAmount fees,
178-
CFeeRate effective_feerate)
188+
CFeeRate effective_feerate,
189+
const std::vector<uint256>& wtxids_fee_calculations)
179190
: m_result_type(ResultType::VALID),
180191
m_replaced_transactions(std::move(replaced_txns)),
181192
m_vsize{vsize},
182193
m_base_fees(fees),
183-
m_effective_feerate(effective_feerate) {}
194+
m_effective_feerate(effective_feerate),
195+
m_wtxids_fee_calculations(wtxids_fee_calculations) {}
184196

185197
/** Constructor for already-in-mempool case. It wouldn't replace any transactions. */
186198
explicit MempoolAcceptResult(int64_t vsize, CAmount fees)

0 commit comments

Comments
 (0)