- 
                Notifications
    You must be signed in to change notification settings 
- Fork 38.1k
rpc: deprecate top-level fee fields in getmempool RPCs #22689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|  | @@ -462,23 +462,23 @@ static RPCHelpMan getdifficulty() | |||||
| static std::vector<RPCResult> MempoolEntryDescription() { return { | ||||||
| RPCResult{RPCResult::Type::NUM, "vsize", "virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."}, | ||||||
| RPCResult{RPCResult::Type::NUM, "weight", "transaction weight as defined in BIP 141."}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "fee", "transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)"}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee", "transaction fee with fee deltas used for mining priority (DEPRECATED)"}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "fee", "transaction fee, denominated in " + CURRENCY_UNIT + " (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee", "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT + " (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"}, | ||||||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing optional. see #23694 | ||||||
| RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"}, | ||||||
| RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"}, | ||||||
| RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"}, | ||||||
| RPCResult{RPCResult::Type::NUM, "descendantsize", "virtual transaction size of in-mempool descendants (including this one)"}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees", "modified fees (see above) of in-mempool descendants (including this one) (DEPRECATED)"}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees", "transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_ATOM + "s (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"}, | ||||||
| RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"}, | ||||||
| RPCResult{RPCResult::Type::NUM, "ancestorsize", "virtual transaction size of in-mempool ancestors (including this one)"}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees", "modified fees (see above) of in-mempool ancestors (including this one) (DEPRECATED)"}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees", "transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_ATOM + "s (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"}, | ||||||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. only if you retouch, here and line 464 
        Suggested change
       
 | ||||||
| RPCResult{RPCResult::Type::STR_HEX, "wtxid", "hash of serialized transaction, including witness data"}, | ||||||
| RPCResult{RPCResult::Type::OBJ, "fees", "", | ||||||
| { | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee, denominated in " + CURRENCY_UNIT}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT}, | ||||||
| RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT}, | ||||||
| }}, | ||||||
| RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction", | ||||||
| {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}}, | ||||||
|  | @@ -492,26 +492,35 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool | |||||
| { | ||||||
| AssertLockHeld(pool.cs); | ||||||
|  | ||||||
| UniValue fees(UniValue::VOBJ); | ||||||
| fees.pushKV("base", ValueFromAmount(e.GetFee())); | ||||||
| fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee())); | ||||||
| fees.pushKV("ancestor", ValueFromAmount(e.GetModFeesWithAncestors())); | ||||||
| fees.pushKV("descendant", ValueFromAmount(e.GetModFeesWithDescendants())); | ||||||
| info.pushKV("fees", fees); | ||||||
|  | ||||||
| info.pushKV("vsize", (int)e.GetTxSize()); | ||||||
| info.pushKV("weight", (int)e.GetTxWeight()); | ||||||
| info.pushKV("fee", ValueFromAmount(e.GetFee())); | ||||||
| info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee())); | ||||||
| // TODO: top-level fee fields are deprecated. deprecated_fee_fields_enabled blocks should be removed in v24 | ||||||
| const bool deprecated_fee_fields_enabled{IsDeprecatedRPCEnabled("fees")}; | ||||||
| if (deprecated_fee_fields_enabled) { | ||||||
| info.pushKV("fee", ValueFromAmount(e.GetFee())); | ||||||
| info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee())); | ||||||
| } | ||||||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be more user-friendly to not alter the field order here so that it is the same as the help. E.g. insert the IsDeprecated... conditional (or cache the result of the call to a local bool variable) before the fields where they already are. (Sorry, I didn't notice this in my previous review.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code will go away soon, so I don't think this gives much benefit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i noticed that the current order doesn't match the help (fees object is listed after wtxid but is first in the returned object), so didn't worry about re-arranging fields, but i agree that it can be confusing for the user. i think grouping the fields makes it easier to deprecate them later, so maybe a better solution would be to re-arrange the help to match the actual ordering? or just leave it as is per @MarcoFalke 's comment, i dont have a strong opinion either way There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would say, please don't re-arrange the help to make up for something the code can easily do. Yes, I agree it's not of earth-shattering importance, but I also think it's a more important aspect than in which file to put the deprecation test or which way to check for deprecation. It affects users. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 
 good point, @jonatack , i'll update based on your suggestion There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Happy to re-review ASAP if you do (it's not a blocker). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 
 Oh, I see now what you meant. Hm, the fees output/help mismatch was done in 7de1de7. ISTM we usually place JSON objects after top-level fields? So your change ~seems correct, unless other reviewers think it's better to change the help to be like the output. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 
 that's the convention i'm used to (and much prefer) | ||||||
| info.pushKV("time", count_seconds(e.GetTime())); | ||||||
| info.pushKV("height", (int)e.GetHeight()); | ||||||
| info.pushKV("descendantcount", e.GetCountWithDescendants()); | ||||||
| info.pushKV("descendantsize", e.GetSizeWithDescendants()); | ||||||
| info.pushKV("descendantfees", e.GetModFeesWithDescendants()); | ||||||
| if (deprecated_fee_fields_enabled) { | ||||||
| info.pushKV("descendantfees", e.GetModFeesWithDescendants()); | ||||||
| } | ||||||
| info.pushKV("ancestorcount", e.GetCountWithAncestors()); | ||||||
| info.pushKV("ancestorsize", e.GetSizeWithAncestors()); | ||||||
| info.pushKV("ancestorfees", e.GetModFeesWithAncestors()); | ||||||
| if (deprecated_fee_fields_enabled) { | ||||||
| info.pushKV("ancestorfees", e.GetModFeesWithAncestors()); | ||||||
|         
                  josibake marked this conversation as resolved.
              Show resolved
            Hide resolved | ||||||
| } | ||||||
| info.pushKV("wtxid", pool.vTxHashes[e.vTxHashesIdx].first.ToString()); | ||||||
|  | ||||||
| UniValue fees(UniValue::VOBJ); | ||||||
| fees.pushKV("base", ValueFromAmount(e.GetFee())); | ||||||
| fees.pushKV("modified", ValueFromAmount(e.GetModifiedFee())); | ||||||
| fees.pushKV("ancestor", ValueFromAmount(e.GetModFeesWithAncestors())); | ||||||
| fees.pushKV("descendant", ValueFromAmount(e.GetModFeesWithDescendants())); | ||||||
| info.pushKV("fees", fees); | ||||||
|         
                  josibake marked this conversation as resolved.
              Show resolved
            Hide resolved | ||||||
|  | ||||||
| const CTransaction& tx = e.GetTx(); | ||||||
| std::set<std::string> setDepends; | ||||||
| for (const CTxIn& txin : tx.vin) | ||||||
|  | ||||||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| #!/usr/bin/env python3 | ||
| # Copyright (c) 2021 The Bitcoin Core developers | ||
| # Distributed under the MIT software license, see the accompanying | ||
| # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
| """Test deprecation of fee fields from top level mempool entry object""" | ||
|         
                  glozow marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
|  | ||
| from test_framework.blocktools import COIN | ||
| from test_framework.test_framework import BitcoinTestFramework | ||
| from test_framework.util import assert_equal | ||
| from test_framework.wallet import MiniWallet | ||
|  | ||
|  | ||
| def assertions_helper(new_object, deprecated_object, deprecated_fields): | ||
| for field in deprecated_fields: | ||
| assert field in deprecated_object | ||
| assert field not in new_object | ||
|  | ||
|  | ||
| class MempoolFeeFieldsDeprecationTest(BitcoinTestFramework): | ||
| def set_test_params(self): | ||
| self.num_nodes = 2 | ||
| self.extra_args = [[], ["-deprecatedrpc=fees"]] | ||
|  | ||
| def run_test(self): | ||
| # we get spendable outputs from the premined chain starting | ||
| # at block 76. see BitcoinTestFramework._initialize_chain() for details | ||
| self.wallet = MiniWallet(self.nodes[0]) | ||
| self.wallet.rescan_utxos() | ||
|  | ||
| # we create the tx on the first node and wait until it syncs to node_deprecated | ||
| # thus, any differences must be coming from getmempoolentry or getrawmempool | ||
| tx = self.wallet.send_self_transfer(from_node=self.nodes[0]) | ||
| self.nodes[1].sendrawtransaction(tx["hex"]) | ||
|  | ||
| deprecated_fields = ["ancestorfees", "descendantfees", "modifiedfee", "fee"] | ||
| self.test_getmempoolentry(tx["txid"], deprecated_fields) | ||
| self.test_getrawmempool(tx["txid"], deprecated_fields) | ||
| self.test_deprecated_fields_match(tx["txid"]) | ||
|  | ||
| def test_getmempoolentry(self, txid, deprecated_fields): | ||
|  | ||
| self.log.info("Test getmempoolentry rpc") | ||
| entry = self.nodes[0].getmempoolentry(txid) | ||
| deprecated_entry = self.nodes[1].getmempoolentry(txid) | ||
| assertions_helper(entry, deprecated_entry, deprecated_fields) | ||
|  | ||
| def test_getrawmempool(self, txid, deprecated_fields): | ||
|  | ||
| self.log.info("Test getrawmempool rpc") | ||
| entry = self.nodes[0].getrawmempool(verbose=True)[txid] | ||
| deprecated_entry = self.nodes[1].getrawmempool(verbose=True)[txid] | ||
| assertions_helper(entry, deprecated_entry, deprecated_fields) | ||
|  | ||
| def test_deprecated_fields_match(self, txid): | ||
|  | ||
|         
                  josibake marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| self.log.info("Test deprecated fee fields match new fees object") | ||
| entry = self.nodes[0].getmempoolentry(txid) | ||
| deprecated_entry = self.nodes[1].getmempoolentry(txid) | ||
|  | ||
| assert_equal(deprecated_entry["fee"], entry["fees"]["base"]) | ||
| assert_equal(deprecated_entry["modifiedfee"], entry["fees"]["modified"]) | ||
| assert_equal(deprecated_entry["descendantfees"], entry["fees"]["descendant"] * COIN) | ||
| assert_equal(deprecated_entry["ancestorfees"], entry["fees"]["ancestor"] * COIN) | ||
|  | ||
|  | ||
| if __name__ == "__main__": | ||
| MempoolFeeFieldsDeprecationTest().main() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.