From 601bac88cb95404e7d38ac6348d959c0e06bd922 Mon Sep 17 00:00:00 2001 From: glozow Date: Wed, 28 Sep 2022 14:07:56 +0100 Subject: [PATCH] [rpc] return effective-includes in testmempoolaccept and submitpackage --- src/rpc/mempool.cpp | 16 ++++++++++++++++ test/functional/mempool_accept.py | 1 + test/functional/p2p_segwit.py | 2 ++ test/functional/rpc_packages.py | 5 +++++ 4 files changed, 24 insertions(+) diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 5a8724196a..e69088b76e 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -127,6 +127,9 @@ static RPCHelpMan testmempoolaccept() { {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT}, {RPCResult::Type::STR_AMOUNT, "effective-feerate", /*optional=*/false, "the effective feerate in " + CURRENCY_UNIT + " per KvB. May differ from the base feerate if, for example, there are modified fees from prioritisetransaction or a package feerate was used."}, + {RPCResult::Type::ARR, "effective-includes", /*optional=*/false, "transactions whose fees and vsizes are included in effective-feerate.", + {RPCResult{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"}, + }}, }}, {RPCResult::Type::STR, "reject-reason", /*optional=*/true, "Rejection string (only present when 'allowed' is false)"}, }}, @@ -219,6 +222,11 @@ static RPCHelpMan testmempoolaccept() UniValue fees(UniValue::VOBJ); fees.pushKV("base", ValueFromAmount(fee)); fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK())); + UniValue effective_includes_res(UniValue::VARR); + for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) { + effective_includes_res.push_back(wtxid.ToString()); + } + fees.pushKV("effective-includes", effective_includes_res); result_inner.pushKV("fees", fees); } } else { @@ -771,6 +779,9 @@ static RPCHelpMan submitpackage() {RPCResult::Type::OBJ, "fees", "Transaction fees", { {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT}, {RPCResult::Type::STR_AMOUNT, "effective-feerate", /*optional=*/true, "if the transaction was not already in the mempool, the effective feerate in " + CURRENCY_UNIT + " per KvB. For example, the package feerate and/or feerate with modified fees from prioritisetransaction."}, + {RPCResult::Type::ARR, "effective-includes", /*optional=*/true, "if effective-feerate is provided, the wtxids of the transactions whose fees and vsizes are included in effective-feerate.", + {{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"}, + }}, }}, }} }}, @@ -873,6 +884,11 @@ static RPCHelpMan submitpackage() // though modified fees is known, because it is unknown whether package // feerate was used when it was originally submitted. fees.pushKV("effective-feerate", ValueFromAmount(tx_result.m_effective_feerate.value().GetFeePerK())); + UniValue effective_includes_res(UniValue::VARR); + for (const auto& wtxid : tx_result.m_wtxids_fee_calculations.value()) { + effective_includes_res.push_back(wtxid.ToString()); + } + fees.pushKV("effective-includes", effective_includes_res); } result_inner.pushKV("fees", fees); if (it->second.m_replaced_transactions.has_value()) { diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py index 12ea7a00b1..19cb65be36 100755 --- a/test/functional/mempool_accept.py +++ b/test/functional/mempool_accept.py @@ -62,6 +62,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework): r.pop('wtxid') if "fees" in r: r["fees"].pop("effective-feerate") + r["fees"].pop("effective-includes") assert_equal(result_expected, result_test) assert_equal(self.nodes[0].getmempoolinfo()['size'], self.mempool_size) # Must not change mempool state diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index 0072478f1c..b0900e49b8 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -624,6 +624,7 @@ class SegWitTest(BitcoinTestFramework): # in blocks and the tx is impossible to mine right now. testres3 = self.nodes[0].testmempoolaccept([tx3.serialize_with_witness().hex()]) testres3[0]["fees"].pop("effective-feerate") + testres3[0]["fees"].pop("effective-includes") assert_equal(testres3, [{ 'txid': tx3.hash, @@ -642,6 +643,7 @@ class SegWitTest(BitcoinTestFramework): tx3.rehash() testres3_replaced = self.nodes[0].testmempoolaccept([tx3.serialize_with_witness().hex()]) testres3_replaced[0]["fees"].pop("effective-feerate") + testres3_replaced[0]["fees"].pop("effective-includes") assert_equal(testres3_replaced, [{ 'txid': tx3.hash, diff --git a/test/functional/rpc_packages.py b/test/functional/rpc_packages.py index f3b5f4d2dc..ba782c5bb9 100755 --- a/test/functional/rpc_packages.py +++ b/test/functional/rpc_packages.py @@ -247,6 +247,7 @@ class RPCPackagesTest(BitcoinTestFramework): assert_equal(testres_replaceable["vsize"], replaceable_tx["tx"].get_vsize()) assert_equal(testres_replaceable["fees"]["base"], fee) assert_fee_amount(fee, replaceable_tx["tx"].get_vsize(), testres_replaceable["fees"]["effective-feerate"]) + assert_equal(testres_replaceable["fees"]["effective-includes"], [replaceable_tx["wtxid"]]) # Replacement transaction is identical except has double the fee replacement_tx = self.wallet.create_self_transfer(utxo_to_spend=coin, sequence=MAX_BIP125_RBF_SEQUENCE, fee = 2 * fee) @@ -315,6 +316,7 @@ class RPCPackagesTest(BitcoinTestFramework): assert_equal(tx_result["fees"]["base"], DEFAULT_FEE) if wtxid not in presubmitted_wtxids: assert_fee_amount(DEFAULT_FEE, tx.get_vsize(), tx_result["fees"]["effective-feerate"]) + assert_equal(tx_result["fees"]["effective-includes"], [wtxid]) # submitpackage result should be consistent with testmempoolaccept and getmempoolentry self.assert_equal_package_results(node, testmempoolaccept_result, submitpackage_result) @@ -353,10 +355,13 @@ class RPCPackagesTest(BitcoinTestFramework): assert_equal(child_result["fees"]["base"], DEFAULT_FEE) # The "rich" parent does not require CPFP so its effective feerate. assert_fee_amount(DEFAULT_FEE, tx_rich["tx"].get_vsize(), rich_parent_result["fees"]["effective-feerate"]) + assert_equal(rich_parent_result["fees"]["effective-includes"], [tx_rich["wtxid"]]) # The "poor" parent and child's effective feerates are the same, composed of the child's fee # divided by their combined vsize. assert_fee_amount(DEFAULT_FEE, tx_poor["tx"].get_vsize() + tx_child["tx"].get_vsize(), poor_parent_result["fees"]["effective-feerate"]) assert_fee_amount(DEFAULT_FEE, tx_poor["tx"].get_vsize() + tx_child["tx"].get_vsize(), child_result["fees"]["effective-feerate"]) + assert_equal([tx_poor["wtxid"], tx_child["tx"].getwtxid()], poor_parent_result["fees"]["effective-includes"]) + assert_equal([tx_poor["wtxid"], tx_child["tx"].getwtxid()], child_result["fees"]["effective-includes"]) # Package feerate is calculated for the remaining transactions after deduplication and # individual submission. Since this package had a 0-fee parent, package feerate must have