[wallet] [rpc] sendtoaddress/sendmany: Add explicit feerate option #11413

pull kallewoof wants to merge 8 commits into bitcoin:master from kallewoof:explicit-fee changing 9 files +285 −91
  1. kallewoof commented at 6:44 am on September 28, 2017: member
    This lets users pick their own fees when using sendtoaddress/sendmany if they prefer this over the estimators.
  2. fanquake added the label RPC/REST/ZMQ on Sep 28, 2017
  3. fanquake added the label Wallet on Sep 28, 2017
  4. jonasschnelli commented at 2:19 pm on September 28, 2017: contributor

    Not opposed to add that. Though IMO the more experience users (which are those who may use explicit fee-rates) should use create/fund/sendrawtx.

    Concept ACK

  5. in src/policy/fees.cpp:55 in 973f9a88ac outdated
    53@@ -54,6 +54,7 @@ bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_esti
    54         {"UNSET", FeeEstimateMode::UNSET},
    55         {"ECONOMICAL", FeeEstimateMode::ECONOMICAL},
    56         {"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE},
    57+        {"EXPLICIT", FeeEstimateMode::EXPLICIT},
    


    promag commented at 2:43 pm on September 28, 2017:
    The intent sounds more like no estimation so {"NONE", FeeEstimateMode::NONE}?

    kallewoof commented at 0:39 am on September 29, 2017:
    I don’t know. People could mistake that to mean “no fee”.
  6. in src/wallet/rpcwallet.cpp:449 in 973f9a88ac outdated
    444@@ -445,12 +445,15 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
    445             "       \"UNSET\"\n"
    446             "       \"ECONOMICAL\"\n"
    447             "       \"CONSERVATIVE\"\n"
    448+            "       \"EXPLICIT\"\n"
    449+            "9. feerate                (numeric, optional) Fee rate (sat/kb) to use for EXPLICIT mode.\n"
    


    promag commented at 2:44 pm on September 28, 2017:
    Mention that estimate_mode must be set to (currenlty) EXPLICIT to use this value?

    kallewoof commented at 0:40 am on September 29, 2017:
    to use for EXPLICIT mode is not enough?
  7. in src/wallet/rpcwallet.cpp:502 in 973f9a88ac outdated
    496@@ -494,6 +497,12 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
    497         }
    498     }
    499 
    500+    if (!request.params[8].isNull()) {
    501+        if (coin_control.m_fee_mode != FeeEstimateMode::EXPLICIT) {
    502+            throw JSONRPCError(RPC_INVALID_PARAMETER, "Explicit fee rate can only be used when estimate mode is set to EXPLICIT");
    


    promag commented at 2:45 pm on September 28, 2017:
    Add test for error.
  8. promag commented at 2:45 pm on September 28, 2017: member
    Please add tests.
  9. esotericnonsense commented at 4:29 pm on September 28, 2017: contributor

    Concept ACK. I don’t like that this results in sendtoaddress having 8 parameters but I don’t see an immediately obvious way to avoid that.

    Sendmany could get it too?

  10. kallewoof commented at 2:22 am on September 29, 2017: member
    Can’t fix people putting too high fees in, but if they put too low, they should be able to bump the fee unless they specifically disable it. As such, RBF is default-on when fees are explicit (3d14d35). @promag Added tests (1768936). @esotericnonsense I don’t know how frequently this will be used. I suggest it for sendtoaddress because I see a lot of people asking how to fire off a tx with a given fee. There’s also settxfee.
  11. meshcollider commented at 12:45 pm on September 29, 2017: contributor
    Re: the 8 parameter issue @esotericnonsense mentioned, it would be cleaner to convert most parameters to a JSON object input like bumpfee, listunspent, etc. use since most are independent of each other and optional
  12. in src/rpc/client.cpp:42 in 1768936ee2 outdated
    38@@ -39,6 +39,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
    39     { "sendtoaddress", 4, "subtractfeefromamount" },
    40     { "sendtoaddress", 5 , "replaceable" },
    41     { "sendtoaddress", 6 , "conf_target" },
    42+    { "sendtoaddress", 8, "feerate"},
    


    kallewoof commented at 6:17 am on October 1, 2017:
    Self-nit: space after "feerate"
  13. kallewoof force-pushed on Oct 10, 2017
  14. kallewoof force-pushed on Oct 10, 2017
  15. kallewoof force-pushed on Oct 10, 2017
  16. kallewoof force-pushed on Oct 10, 2017
  17. luke-jr changes_requested
  18. luke-jr commented at 12:00 pm on November 10, 2017: member
    Concept ACK, but sendmany should get it too.
  19. in src/wallet/rpcwallet.cpp:449 in 78bf08b658 outdated
    444@@ -445,12 +445,15 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
    445             "       \"UNSET\"\n"
    446             "       \"ECONOMICAL\"\n"
    447             "       \"CONSERVATIVE\"\n"
    448+            "       \"EXPLICIT\"\n"
    449+            "9. feerate                (numeric, optional) Fee rate (sat/kb) to use for EXPLICIT mode. (Note: replaceable defaults to true when used)\n"
    


    luke-jr commented at 1:57 pm on November 10, 2017:
    This isn’t in the argument list above.
  20. in src/wallet/rpcwallet.cpp:500 in 78bf08b658 outdated
    496@@ -494,6 +497,14 @@ UniValue sendtoaddress(const JSONRPCRequest& request)
    497         }
    498     }
    499 
    500+    if (!request.params[8].isNull()) {
    


    luke-jr commented at 1:58 pm on November 10, 2017:
    It doesn’t make sense to add a new param for this. Instead, make params[6] be conf target or feerate…
  21. luke-jr changes_requested
  22. kallewoof force-pushed on Nov 13, 2017
  23. kallewoof commented at 1:58 am on November 13, 2017: member
    Addressed @luke-jr requests (double-use conf_target and add feature to sendmany).
  24. kallewoof force-pushed on Nov 13, 2017
  25. kallewoof force-pushed on Dec 8, 2017
  26. kallewoof force-pushed on Dec 8, 2017
  27. kallewoof renamed this:
    [wallet] [rpc] sendtoaddress: Add explicit feerate option to sendtoaddress
    [wallet] [rpc] sendtoaddress/sendmany: Add explicit feerate option
    on Dec 21, 2017
  28. kallewoof force-pushed on Feb 20, 2018
  29. kallewoof force-pushed on Feb 20, 2018
  30. kallewoof force-pushed on Feb 21, 2018
  31. kallewoof force-pushed on May 22, 2018
  32. kallewoof force-pushed on May 22, 2018
  33. kallewoof force-pushed on May 22, 2018
  34. kallewoof force-pushed on May 22, 2018
  35. kallewoof force-pushed on Jul 12, 2018
  36. DrahtBot added the label Needs rebase on Aug 27, 2018
  37. kallewoof force-pushed on Sep 10, 2018
  38. kallewoof force-pushed on Sep 10, 2018
  39. DrahtBot removed the label Needs rebase on Sep 10, 2018
  40. in src/wallet/rpcwallet.cpp:420 in 60a141a3c8 outdated
    419+        if (coin_control.m_fee_mode != FeeEstimateMode::EXPLICIT) {
    420+            coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]);
    421+        } else {
    422+            coin_control.m_feerate = CFeeRate(request.params[6].get_int());
    423+            // default RBF to true for explicit fee rate mode
    424+            coin_control.m_signal_bip125_rbf = (coin_control.m_signal_bip125_rbf ? *coin_control.m_signal_bip125_rbf : false) | request.params[5].isNull();
    


    practicalswift commented at 7:52 am on September 21, 2018:
    02018-09-19 13:23:27 clang-tidy(pr=11413): src/wallet/rpcwallet.cpp:420:48: warning: implicit conversion bool -> 'int' [readability-implicit-bool-conversion]
    12018-09-19 13:23:27 clang-tidy(pr=11413): src/wallet/rpcwallet.cpp:420:129: warning: implicit conversion bool -> 'int' [readability-implicit-bool-conversion]
    

    kallewoof commented at 0:28 am on October 6, 2018:
    Thanks. I assume this is referring to the |?
  41. in src/wallet/rpcwallet.cpp:857 in 60a141a3c8 outdated
    856+        if (coin_control.m_fee_mode != FeeEstimateMode::EXPLICIT) {
    857+            coin_control.m_confirm_target = ParseConfirmTarget(request.params[6]);
    858+        } else {
    859+            coin_control.m_feerate = CFeeRate(request.params[6].get_int());
    860+            // default RBF to true for explicit fee rate mode
    861+            coin_control.m_signal_bip125_rbf = (coin_control.m_signal_bip125_rbf ? *coin_control.m_signal_bip125_rbf : false) | request.params[5].isNull();
    


    practicalswift commented at 7:53 am on September 21, 2018:
    02018-09-19 13:23:27 clang-tidy(pr=11413): src/wallet/rpcwallet.cpp:857:48: warning: implicit conversion bool -> 'int' [readability-implicit-bool-conversion]
    12018-09-19 13:23:27 clang-tidy(pr=11413): src/wallet/rpcwallet.cpp:857:129: warning: implicit conversion bool -> 'int' [readability-implicit-bool-conversion]
    
  42. DrahtBot commented at 1:31 pm on September 21, 2018: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #19349 (doc: Include wallet path to relevant RPC calls by D4nte)
    • #18654 (rpc: separate bumpfee’s psbt creation function into psbtbumpfee by achow101)
    • #18531 (rpc: Assert that RPCArg names are equal to CRPCCommand ones by MarcoFalke)
    • #14641 (rpc: Add min_conf option to fund transaction calls by promag)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  43. DrahtBot added the label Needs rebase on Oct 1, 2018
  44. kallewoof force-pushed on Oct 6, 2018
  45. kallewoof force-pushed on Oct 6, 2018
  46. DrahtBot removed the label Needs rebase on Oct 6, 2018
  47. sipa commented at 3:45 am on November 11, 2018: member
    Concept ACK
  48. meshcollider commented at 7:38 am on November 11, 2018: contributor
    utACK https://github.com/bitcoin/bitcoin/pull/11413/commits/d9b1c428486b8f0acb92825a01d7dc5c0994ca24, my earlier concern about adding another parameter is no longer relevant :)
  49. in src/wallet/rpcwallet.cpp:359 in d9b1c42848 outdated
    354@@ -355,17 +355,20 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
    355             "5. subtractfeefromamount  (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
    356             "                             The recipient will receive less bitcoins than you enter in the amount field.\n"
    357             "6. replaceable            (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
    358-            "7. conf_target            (numeric, optional) Confirmation target (in blocks)\n"
    359+            "                             Defaults to false unless explicit estimate mode is used, in which case it defaults to true\n"
    360+            "7. conf_target            (numeric, optional) Confirmation target (in blocks), or fee rate (sat/kb) if explicit estimate mode is used\n"
    


    MarcoFalke commented at 6:19 pm on November 11, 2018:
    Fee rates are passed in as BTC/kB (see settxfee for example) and amounts can be passed in as either num or string.

    kallewoof commented at 7:45 am on November 12, 2018:
    Fixed.
  50. kallewoof force-pushed on Nov 12, 2018
  51. kallewoof force-pushed on Nov 12, 2018
  52. kallewoof force-pushed on Nov 12, 2018
  53. promag commented at 9:43 am on November 12, 2018: member
    utACK, needs squash and could add release notes.
  54. in doc/release-notes-11413.md:1 in f6cc4a97e5 outdated
    0@@ -0,0 +1,5 @@
    1+Low-level RPC changes
    


    promag commented at 12:06 pm on November 12, 2018:
    nit, I may be wrong but I think you could increment doc/release-notes-14454.md?

    kallewoof commented at 12:13 pm on November 12, 2018:
    Hm. Does it matter? I assume the files are merged together at the end anyway.
  55. kallewoof force-pushed on Nov 12, 2018
  56. kallewoof commented at 12:11 pm on November 12, 2018: member
    @promag Added release notes & squashed. Also fixed sendmany, which I had forgotten.
  57. kallewoof force-pushed on Nov 12, 2018
  58. kallewoof force-pushed on Nov 12, 2018
  59. DrahtBot added the label Needs rebase on Nov 23, 2018
  60. in src/wallet/rpcwallet.cpp:386 in 584e946bd2 outdated
    356@@ -357,17 +357,20 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
    357             "5. subtractfeefromamount  (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
    358             "                             The recipient will receive less bitcoins than you enter in the amount field.\n"
    359             "6. replaceable            (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n"
    360-            "7. conf_target            (numeric, optional) Confirmation target (in blocks)\n"
    361+            "                             Defaults to false unless explicit estimate mode is used, in which case it defaults to true\n"
    362+            "7. conf_target            (numeric, optional) Confirmation target (in blocks), or fee rate (BTC/kb) if explicit estimate mode is used\n"
    


    luke-jr commented at 8:00 pm on November 24, 2018:
    Per kB, not per kb[it].

    luke-jr commented at 8:02 pm on November 24, 2018:
    Also should use CURRENCY_UNIT here.
  61. kallewoof force-pushed on Nov 26, 2018
  62. kallewoof commented at 3:20 am on November 26, 2018: member
    @luke-jr Thanks for review! I switched to " + CURRENCY_UNIT + "/kB as suggested.
  63. DrahtBot removed the label Needs rebase on Nov 26, 2018
  64. MarcoFalke deleted a comment on Nov 26, 2018
  65. DrahtBot added the label Needs rebase on Dec 5, 2018
  66. kallewoof force-pushed on Dec 10, 2018
  67. DrahtBot removed the label Needs rebase on Dec 10, 2018
  68. DrahtBot added the label Needs rebase on Dec 10, 2018
  69. kallewoof force-pushed on Dec 11, 2018
  70. DrahtBot removed the label Needs rebase on Dec 11, 2018
  71. in src/wallet/rpcwallet.cpp:381 in 271cb65a48 outdated
    377@@ -377,6 +378,7 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
    378             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
    379             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
    380             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
    381+            + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" false true 2000 EXPLICIT")
    


    meshcollider commented at 4:39 am on December 12, 2018:
    This example feerate needs updating now to be BTC/kB, 2000 BTC/kB is probably a bit high 😄
  72. kallewoof force-pushed on Dec 12, 2018
  73. DrahtBot added the label Needs rebase on Jan 29, 2019
  74. kallewoof force-pushed on Jan 30, 2019
  75. DrahtBot removed the label Needs rebase on Jan 30, 2019
  76. DrahtBot added the label Needs rebase on Feb 12, 2019
  77. kallewoof force-pushed on Feb 13, 2019
  78. DrahtBot removed the label Needs rebase on Feb 13, 2019
  79. DrahtBot added the label Needs rebase on Mar 4, 2019
  80. kallewoof force-pushed on Mar 5, 2019
  81. DrahtBot removed the label Needs rebase on Mar 5, 2019
  82. kallewoof force-pushed on Mar 5, 2019
  83. DrahtBot added the label Needs rebase on Apr 2, 2019
  84. kallewoof force-pushed on Apr 3, 2019
  85. DrahtBot removed the label Needs rebase on Apr 3, 2019
  86. in test/functional/wallet_basic.py:26 in 22a4bf730d outdated
    21@@ -22,6 +22,8 @@ class WalletTest(BitcoinTestFramework):
    22     def set_test_params(self):
    23         self.num_nodes = 4
    24         self.setup_clean_chain = True
    25+        # node 2 needs a txindex to look up raw transactions
    26+        self.extra_args = [[], [], ["-txindex"], []]
    


    luke-jr commented at 8:38 am on April 4, 2019:

    This is part of the wrong commit. The sendtoaddress test only calls getrawtransaction on a transaction in the mempool, which doesn’t need a tx index.

    Also, the sendmany test that relies on this could just pass the block hash explicitly to avoid building the tx index.


    luke-jr commented at 8:41 am on April 4, 2019:
    Actually, you already removed the getrawtransaction from sendmany, so this seems completely unnecessary?

    kallewoof commented at 2:46 am on April 5, 2019:
    Didn’t realize that, thanks. Removed these 2 lines!
  87. kallewoof force-pushed on Apr 5, 2019
  88. kallewoof force-pushed on Apr 5, 2019
  89. DrahtBot added the label Needs rebase on Apr 10, 2019
  90. kallewoof force-pushed on Apr 11, 2019
  91. DrahtBot removed the label Needs rebase on Apr 11, 2019
  92. in test/functional/wallet_basic.py:424 in b91af41525 outdated
    363+            conf_target=0.00002500,
    364+            estimate_mode='EXPLICIT',
    365+        )
    366+        tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
    367+        self.sync_all([self.nodes[0:3]])
    368+        self.nodes[0].generate(1)
    


    luke-jr commented at 6:27 am on April 27, 2019:
    Since the block is mined by node 0, and the balance is on node 2, you need another sync_all here or else there’s a race condition.

    kallewoof commented at 4:36 am on May 7, 2019:
    @luke-jr Thanks, fixed!
  93. kallewoof force-pushed on May 7, 2019
  94. kallewoof force-pushed on May 7, 2019
  95. DrahtBot added the label Needs rebase on Jun 19, 2019
  96. kallewoof force-pushed on Jun 19, 2019
  97. DrahtBot removed the label Needs rebase on Jun 19, 2019
  98. DrahtBot added the label Needs rebase on Jun 22, 2019
  99. kallewoof force-pushed on Jun 24, 2019
  100. DrahtBot removed the label Needs rebase on Jun 24, 2019
  101. DrahtBot added the label Needs rebase on Aug 2, 2019
  102. kallewoof force-pushed on Aug 3, 2019
  103. DrahtBot removed the label Needs rebase on Aug 3, 2019
  104. Sjors commented at 12:48 pm on August 6, 2019: member
    Concept ACK. Alernatively you could replace EXPLICIT with btc/kb. That’s more readable, prevents accidents when people forget the unit account isn’t satoshi per byte (see #16257) and makes it easy to add sat/b as a unit a later.
  105. kallewoof commented at 1:04 pm on August 6, 2019: member
    @Sjors I love it. Will definitely do, thanks!
  106. kallewoof force-pushed on Aug 6, 2019
  107. kallewoof commented at 1:22 pm on August 6, 2019: member

    Done. Also squashed things.

    For shitcoiners, this is a drawback as a new hard-coded coin name (“btc” in “btc/kb”) is introduced, but don’t think anyone cares about that.

  108. Sjors commented at 1:43 pm on August 6, 2019: member
    Ah, I missed this update, here was my stab at the same, plus satoshi per byte: https://github.com/Sjors/bitcoin/commit/a0996c125d59e9809306818533eba5cc6e512eb8
  109. in src/util/fees.cpp:34 in 7d1238f91a outdated
    30@@ -31,6 +31,7 @@ bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_esti
    31         {"UNSET", FeeEstimateMode::UNSET},
    32         {"ECONOMICAL", FeeEstimateMode::ECONOMICAL},
    33         {"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE},
    34+        {"btc/kb", FeeEstimateMode::BTC_KB},
    


    MarcoFalke commented at 1:45 pm on August 6, 2019:

    I think we use upper case. See also

    0src/policy/feerate.cpp:const std::string CURRENCY_UNIT = "BTC";
    

    which you can use to express your love of shitcoins.


    kallewoof commented at 1:55 pm on August 6, 2019:
    I am very tempted to make the parser case insensitive and use CURRENCY_UNIT as you say. Otherwise it’s a bit of a pain to require users to type “BTC/kb” every time (as opposed to just “btc/kb”)

    MarcoFalke commented at 2:20 pm on August 6, 2019:
    Also, there is a difference between kilobit (kb) and kilobyte (kB)

    Sjors commented at 3:06 pm on August 6, 2019:

    +1 for case insensitive

    Also fine with CURRENCY_UNIT

    I don’t care about the kB vs kb distinction as far as the parser goes, because nobody uses bits in the context of fees, but documentation wise we should do it correctly. Users will out by themselves it’s case insensitive :-)


    luke-jr commented at 11:25 pm on August 6, 2019:
    RPC is for software, not users…

    kallewoof commented at 5:00 am on August 7, 2019:
    It’s for any entity that doesn’t use the GUI, which includes non-software me.
  110. kallewoof force-pushed on Aug 7, 2019
  111. kallewoof commented at 4:46 am on August 7, 2019: member

    I ended up refactoring the uppercase/lowercase code quite heavily, which may deserve its own PR. Feedback on this welcome.

    Edit: @Sjors Your commit inspired the resulting code, FWIW :)

  112. kallewoof force-pushed on Aug 7, 2019
  113. kallewoof force-pushed on Aug 7, 2019
  114. kallewoof force-pushed on Aug 7, 2019
  115. kallewoof force-pushed on Aug 7, 2019
  116. kallewoof force-pushed on Aug 7, 2019
  117. kallewoof force-pushed on Aug 7, 2019
  118. in src/policy/fees.h:54 in 78356e5dee outdated
    49@@ -50,6 +50,8 @@ enum class FeeEstimateMode {
    50     UNSET,        //!< Use default settings based on other criteria
    51     ECONOMICAL,   //!< Force estimateSmartFee to use non-conservative estimates
    52     CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
    53+    BTC_KB,       //!< Use explicit BTC/kB fee given in coin control
    54+    SAT_B,        //!< Use explicit SAT/b fee given in coin control
    


    Sjors commented at 2:32 pm on August 7, 2019:
    Should be upper case B.
  119. in src/wallet/rpcwallet.cpp:379 in 78356e5dee outdated
    375@@ -360,11 +376,13 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
    376                     {"subtractfeefromamount", RPCArg::Type::BOOL, /* default */ "false", "The fee will be deducted from the amount being sent.\n"
    377             "                             The recipient will receive less bitcoins than you enter in the amount field."},
    378                     {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
    379-                    {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
    380-                    {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
    381+                    {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (" + CURRENCY_UNIT + "/kB) if " + (CURRENCY_UNIT + "/kB") + " estimate mode is used"},
    


    Sjors commented at 2:34 pm on August 7, 2019:
    The second one should be CURRENCY_ATOM + “/B”

    kallewoof commented at 2:30 am on August 8, 2019:
    Hm? No it is literally saying “fee rate (BTC/kB) if BTC/kB estimate mode is used”. Though since we now have two, maybe it should be “fee rate (for BTC/KB or SAT/B estimate modes)” instead.
  120. in src/wallet/rpcwallet.cpp:840 in 78356e5dee outdated
    836@@ -816,11 +837,13 @@ static UniValue sendmany(const JSONRPCRequest& request)
    837                         },
    838                     },
    839                     {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
    840-                    {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
    841-                    {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
    842+                    {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (" + CURRENCY_UNIT + "/kB) if " + (CURRENCY_UNIT + "/kB") + " estimate mode is used"},
    


    Sjors commented at 2:36 pm on August 7, 2019:
    Same issue as above
  121. Sjors commented at 2:38 pm on August 7, 2019: member

    A separate PR for the uppercase/lowercase makes sense. It looks simple enough, but it does touch networking code.

    utACK 626d26c modulo documentation bug.

  122. kallewoof force-pushed on Aug 8, 2019
  123. kallewoof force-pushed on Aug 8, 2019
  124. kallewoof commented at 2:39 am on August 8, 2019: member
    Addressed @Sjors nits. Note there is #16566 which contains the case function refactor commit only.
  125. Sjors commented at 8:30 am on August 8, 2019: member
    utACK 601da0f981078a99b3eb5d689f42c7937199a375
  126. in src/util/system.cpp:391 in 601da0f981 outdated
    387@@ -388,7 +388,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
    388             key.erase(is_index);
    389         }
    390 #ifdef WIN32
    391-        std::transform(key.begin(), key.end(), key.begin(), ToLower);
    


    luke-jr commented at 3:24 pm on August 8, 2019:
    This seems to clearly perform worse. Is there a reason not to keep the current way? (A std::string ToLower overload could be in addition to this.)

    Sjors commented at 3:32 pm on August 8, 2019:
    @luke-jr this bit is moved to #16566 (including discussion about whether performance matters)

    kallewoof commented at 1:01 am on August 9, 2019:
    I could keep the in-place transform, but seriously, this is called a couple of dozen times once at startup and not again. I think we want to aim for readability on this one.
  127. in src/policy/fees.h:54 in 601da0f981 outdated
    49@@ -50,6 +50,8 @@ enum class FeeEstimateMode {
    50     UNSET,        //!< Use default settings based on other criteria
    51     ECONOMICAL,   //!< Force estimateSmartFee to use non-conservative estimates
    52     CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
    53+    BTC_KB,       //!< Use explicit BTC/kB fee given in coin control
    54+    SAT_B,        //!< Use explicit SAT/B fee given in coin control
    


    luke-jr commented at 4:11 pm on August 8, 2019:
    It seems pretty ugly to pass the various units into fee estimate mode here. Can’t we convert to EXPLICIT for internal stuff?

    kallewoof commented at 1:02 am on August 9, 2019:
    I don’t understand what you are suggesting.

    luke-jr commented at 2:08 am on August 9, 2019:
    BTC/kB and sat/B should be limited to the RPC interface. Once it gets to CCoinControl, it should just be EXPLICIT.

    kallewoof commented at 2:19 am on August 9, 2019:
    Ahh, but that complicates the parser part though. Right now, it can take a string and output a FeeEstimateMode. With your suggestion that wouldn’t be sufficient.

    luke-jr commented at 3:34 am on August 9, 2019:
    It may actually simplify it. There’s only a single call that can be inlined here.
  128. in src/wallet/rpcwallet.cpp:437 in 601da0f981 outdated
    432@@ -413,10 +433,6 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
    433         coin_control.m_signal_bip125_rbf = request.params[5].get_bool();
    434     }
    435 
    436-    if (!request.params[6].isNull()) {
    437-        coin_control.m_confirm_target = ParseConfirmTarget(request.params[6], pwallet->chain().estimateMaxBlocks());
    438-    }
    439-
    440     if (!request.params[7].isNull()) {
    441         if (!FeeModeFromString(request.params[7].get_str(), coin_control.m_fee_mode)) {
    


    luke-jr commented at 4:13 pm on August 8, 2019:
    Let’s move this into SetFeeEstimateParam…?

    kallewoof commented at 1:07 am on August 9, 2019:
    Done!
  129. luke-jr changes_requested
  130. in src/wallet/rpcwallet.cpp:387 in 601da0f981 outdated
    375@@ -360,11 +376,13 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
    376                     {"subtractfeefromamount", RPCArg::Type::BOOL, /* default */ "false", "The fee will be deducted from the amount being sent.\n"
    377             "                             The recipient will receive less bitcoins than you enter in the amount field."},
    378                     {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
    379-                    {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
    380-                    {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
    381+                    {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/KB or " + CURRENCY_ATOM + "/B estimate modes)"},
    


    luke-jr commented at 4:15 pm on August 8, 2019:
    “KB” is 1024 bytes; we should at least document it as “kB”

    kallewoof commented at 1:08 am on August 9, 2019:
    Estimate modes are all uppercase, so I don’t think the convention applies here.

    luke-jr commented at 2:19 am on August 9, 2019:
    Since we’re making them case-insensitive, it seems like a good opportunity to introduce mixed case here.

    kallewoof commented at 2:27 am on August 9, 2019:
    I’m not opposed to that, though it would make the PR unnecessarily bigger.
  131. in src/policy/feerate.cpp:11 in 601da0f981 outdated
     7@@ -8,6 +8,7 @@
     8 #include <tinyformat.h>
     9 
    10 const std::string CURRENCY_UNIT = "BTC";
    11+const std::string CURRENCY_ATOM = "SAT";
    


    luke-jr commented at 4:19 pm on August 8, 2019:
    Isn’t “sat” usually lowercase?

    kallewoof commented at 1:09 am on August 9, 2019:
    Yeah, hrm. The one place it’s used right now is uppercase, though, so it may make sense to just do ToLower(CURRENCY_ATOM) in future uses. Or alternatively I use ToUpper(CURRENCY_ATOM) here…

    luke-jr commented at 2:10 am on August 9, 2019:
    IMO ToUpper(CURRENCY_ATOM) makes more sense, since it could just as well be “cXBT” or such in some hypothetical sidechain or future hardfork.

    kallewoof commented at 2:23 am on August 9, 2019:
    I am inclined to agree, but a lot of ToUpper was necessary: 4b304fefc517404bb109041cfcfa2a2c576c9a42

    luke-jr commented at 3:35 am on August 9, 2019:
    IMO only the one case in FeeModeFromString is actually necessary.

    kallewoof commented at 4:12 am on August 9, 2019:
    You mean if we mix-case the estimate modes? Yeah.
  132. in src/wallet/rpcwallet.cpp:397 in 601da0f981 outdated
    392@@ -375,6 +393,8 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
    393                     HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
    394             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
    395             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
    396+            + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" false true 0.00002 " + (CURRENCY_UNIT + "/kB"))
    397+            + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" false true 2 " + (CURRENCY_ATOM + "/b"))
    


    luke-jr commented at 4:19 pm on August 8, 2019:
    Should be an uppercase B here.
  133. kallewoof force-pushed on Aug 9, 2019
  134. kallewoof force-pushed on Aug 9, 2019
  135. kallewoof force-pushed on Aug 9, 2019
  136. kallewoof force-pushed on Aug 9, 2019
  137. kallewoof force-pushed on Aug 9, 2019
  138. kallewoof force-pushed on Aug 9, 2019
  139. kallewoof force-pushed on Aug 9, 2019
  140. kallewoof force-pushed on Aug 9, 2019
  141. kallewoof force-pushed on Aug 9, 2019
  142. kallewoof force-pushed on Aug 9, 2019
  143. kallewoof force-pushed on Aug 10, 2019
  144. kallewoof force-pushed on Aug 10, 2019
  145. in src/util/fees.cpp:31 in 3e77cbb780 outdated
    27@@ -26,15 +28,31 @@ std::string StringForFeeReason(FeeReason reason) {
    28     return reason_string->second;
    29 }
    30 
    31-bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
    32+const std::map<std::string, FeeEstimateMode>& FeeModeMap() {
    


    luke-jr commented at 2:13 pm on August 10, 2019:
    Is there any benefit to the function? (As opposed to a global map)

    kallewoof commented at 2:58 pm on August 10, 2019:
    The windows build (AppVeyor) fails to generate the map if I don’t use a function. :/
  146. fanquake referenced this in commit b799ebcc17 on Aug 13, 2019
  147. sidhujag referenced this in commit 206e3a5511 on Aug 13, 2019
  148. kallewoof force-pushed on Aug 13, 2019
  149. kallewoof force-pushed on Aug 13, 2019
  150. kallewoof force-pushed on Aug 13, 2019
  151. in src/util/fees.cpp:49 in da9c7c1113 outdated
    42+}
    43+
    44+std::string FeeModes(const std::string& delimiter = ", ") {
    45+    std::ostringstream r;
    46+    bool first = true;
    47+    for (const auto& i : FeeModeMap()) {
    


    luke-jr commented at 3:10 pm on August 14, 2019:
    This ends up with the uppercased strings in docs rather than the correct “BTC/kB” and “sat/B”

    kallewoof commented at 3:20 pm on August 14, 2019:
    Everything is uppercase right now. I’m honestly not sure if changing that is the right approach.

    kallewoof commented at 6:30 am on August 28, 2019:
    Code has been updated to show correct capitalization.
  152. in src/wallet/rpcwallet.cpp:3003 in da9c7c1113 outdated
    3049-            }
    3050-            coinControl.m_confirm_target = ParseConfirmTarget(options["conf_target"], pwallet->chain().estimateMaxBlocks());
    3051-        }
    3052-        if (options.exists("estimate_mode")) {
    3053-            if (options.exists("feeRate")) {
    3054-                throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate");
    


    luke-jr commented at 3:10 pm on August 14, 2019:
    This error seems to be lost?

    kallewoof commented at 3:26 pm on August 14, 2019:
    Good catch; re-added into the feeRate block above.
  153. kallewoof force-pushed on Aug 14, 2019
  154. in src/wallet/rpcwallet.cpp:3333 in a887501b52 outdated
    3329@@ -3329,10 +3330,11 @@ static UniValue bumpfee(const JSONRPCRequest& request)
    3330             },
    3331             true, true);
    3332 
    3333-        if (options.exists("confTarget") && options.exists("totalFee")) {
    3334+        auto conf_target_exists = options.exists("confTarget") || options.exists("conf_target");
    


    luke-jr commented at 3:32 pm on August 14, 2019:
    It might be better to replace this with !conf_target.IsNull()

    luke-jr commented at 3:33 pm on August 14, 2019:
    There’s a type check above that needs to be updated for the alias. (Prefer the alias being a separate commit.)

    kallewoof commented at 3:49 pm on August 14, 2019:
    Split alias part into separate commit and added type check.
  155. kallewoof force-pushed on Aug 14, 2019
  156. kallewoof force-pushed on Aug 15, 2019
  157. kallewoof commented at 7:15 am on August 15, 2019: member

    Split into 6 commits:

    • CURRENCY_ATOM addition
    • conf_target alias in bumpfee
    • FeeMode doc helper function
    • make fee estimate modes case insensitive
    • add BTC/KB and SAT/B modes (all caps, like other modes)
    • release notes
  158. in src/util/fees.cpp:31 in 3279ca3e73 outdated
    26@@ -26,15 +27,29 @@ std::string StringForFeeReason(FeeReason reason) {
    27     return reason_string->second;
    28 }
    29 
    30-bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
    31+const std::map<std::string, FeeEstimateMode>& FeeModeMap() {
    32     static const std::map<std::string, FeeEstimateMode> fee_modes = {
    


    Sjors commented at 3:45 pm on August 15, 2019:
    Maybe use <std::vector<std::pair<std::string, FeeEstimateMode>> so you can control the display order?

    luke-jr commented at 12:00 pm on August 16, 2019:
    … but std::map is ordered, isn’t it? That’s why C++ added std::unordered_map?

    kallewoof commented at 12:05 pm on August 16, 2019:
    @luke-jr I believe it std::set orders, which for std::string I think means they become ordered alphabetically.

    luke-jr commented at 12:27 pm on August 16, 2019:
    If we really care about the order, std::map lets you specify that.

    kallewoof commented at 12:50 pm on August 16, 2019:
    @luke-jr We want them in the order they are added. It looks like std::map is not trivial to do this?
  159. in src/wallet/rpcwallet.cpp:179 in 0d251368b7 outdated
    174+        if (cc.m_fee_mode == FeeEstimateMode::SAT_B) {
    175+            fee_rate /= 100000; // 1 sat / B = 0.00001 BTC / kB
    176+        }
    177+        cc.m_feerate = CFeeRate(fee_rate);
    178+        // default RBF to true for explicit fee rate mode
    179+        cc.m_signal_bip125_rbf = (cc.m_signal_bip125_rbf ? *cc.m_signal_bip125_rbf : false) || may_set_rbf;
    


    Sjors commented at 4:04 pm on August 15, 2019:
    This seems unnecessary (or you need another test case). You can drop may_set_rbf and use if(cc.m_signal_bip125_rbf) {*cc.m_signal_bip125_rbf = true}. See 4594923046585453beef83e833e6a422a78b66b2

    kallewoof commented at 2:34 am on August 16, 2019:
    Shouldn’t that be if (!cc.m_signal_bip125_rbf)? I thought optionals returned 0 when unset, and we only wanna set it if it’s not been set already, right?

    kallewoof commented at 2:39 am on August 16, 2019:

    Wading through the slugfest that is boost, it seems that the most correct way to determine if an optional is uninitialized is to do == boost::none. I.e.

    0if (cc.m_signal_bip125_rbf == boost::none) { ... }
    

    Sjors commented at 8:30 am on August 16, 2019:
    +1 for using boost::none
  160. Sjors commented at 4:06 pm on August 15, 2019: member
    ACK 81a42039e0664682ec8a35bbb9327acfce1837e2 modulo RBF code.
  161. kallewoof force-pushed on Aug 16, 2019
  162. Sjors commented at 8:36 am on August 16, 2019: member
    ACK c9971be689aab3242f35447ad20e187915f59418
  163. kallewoof commented at 9:02 am on August 16, 2019: member
    @Sjors Apologies, I missed your preserve-ordering suggestion. How does fa09386 look?
  164. Sjors commented at 9:20 am on August 16, 2019: member
    Looks better:
  165. kallewoof force-pushed on Aug 16, 2019
  166. kallewoof commented at 11:44 am on August 16, 2019: member
    Cool! I realized looking at your output that “unset” should be “UNSET”. Fixup’d.
  167. in src/wallet/rpcwallet.cpp:384 in c0df066dc8 outdated
    384-                    {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", "The fee estimate mode, must be one of:\n"
    385-            "       \"UNSET\"\n"
    386-            "       \"ECONOMICAL\"\n"
    387-            "       \"CONSERVATIVE\""},
    388+                    {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/KB or " + ToUpper(CURRENCY_ATOM) + "/B estimate modes)"},
    389+                    {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
    


    luke-jr commented at 1:46 pm on August 19, 2019:
    The " (case insensitive)" addition is part of the wrong commit.

    kallewoof commented at 6:04 am on August 20, 2019:
    Moved to ‘make case insensitive’ commit.

    promag commented at 2:53 pm on August 27, 2019:

    874b40cea1644812a416a517c3a4a3ab1db89144

    What’s the motivation to support case insensitive?

  168. in src/util/fees.cpp:44 in c0df066dc8 outdated
    43-    auto mode = fee_modes.find(mode_string);
    44+    return fee_modes;
    45+}
    46 
    47-    if (mode == fee_modes.end()) return false;
    48+std::string FeeModes(const std::string& delimiter = ", ") {
    


    luke-jr commented at 1:48 pm on August 19, 2019:
    Commit message calls this FeeMode - probably should be FeeModes, so fix commit message

    MarcoFalke commented at 2:37 pm on August 21, 2019:
    Sorry to keep nit-picking this, but you set a delimiter every time this function is called. But then you set a default value in the header, as well as in the cpp file. At the very least the default should be removed from the cpp file. I’d argue to remove it in all places.

    kallewoof commented at 3:14 am on August 22, 2019:

    A default ", " seemed like a sensible thing, but you’re right that I don’t use the default anywhere.

    Also, huh. I thought re-declaring the defaults in the .cpp file would result in a compiler error. Regardless, removed both.

  169. kallewoof force-pushed on Aug 20, 2019
  170. kallewoof force-pushed on Aug 20, 2019
  171. kallewoof commented at 6:05 am on August 20, 2019: member
    @luke-jr Thanks for feedback, addressed!
  172. Sjors commented at 9:03 am on August 21, 2019: member
    reACK eda3439
  173. in src/wallet/rpcwallet.cpp:3306 in 320c13550e outdated
    3322@@ -3323,16 +3323,20 @@ static UniValue bumpfee(const JSONRPCRequest& request)
    3323         RPCTypeCheckObj(options,
    3324             {
    3325                 {"confTarget", UniValueType(UniValue::VNUM)},
    3326+                {"conf_target", UniValueType(UniValue::VNUM)},
    


    MarcoFalke commented at 12:01 pm on August 21, 2019:
    Why is this adding a new key without documentation and whose value is silently ignored if confTarget is given? Doesn’t make any sense to me and seems completely unrelated to this pull request anyway.

    Sjors commented at 12:32 pm on August 21, 2019:
    Looks like this could be avoided entirely, though it’s nice to get rid of the last remaining intsance of confTarget. But at least there should be a throw if both are set. You could also rename the documented options to conf_target, but keep confTarget as an undocumented alias for backwards compatibility. That should be in the release note though.

    kallewoof commented at 2:00 pm on August 21, 2019:
    Documentation updated/release notes added. Also throws if both are given.
  174. in doc/release-notes-11413.md:1 in 1241c094f5 outdated
    0@@ -0,0 +1,8 @@
    1+Low-level RPC changes
    


    MarcoFalke commented at 12:02 pm on August 21, 2019:
    Should be “updated or changed RPC”, as low level changes are meant for things that are irrelevant to users

    kallewoof commented at 2:02 pm on August 21, 2019:
    Switched to “Updated or changed RPC”.
  175. in src/wallet/rpcwallet.cpp:835 in ec8e2a5b12 outdated
    816-            "       \"UNSET\"\n"
    817-            "       \"ECONOMICAL\"\n"
    818-            "       \"CONSERVATIVE\""},
    819+                    {"estimate_mode", RPCArg::Type::STR, /* default */ "UNSET", std::string() + "The fee estimate mode, must be one of:\n"
    820+            "       \"" + FeeModes("\"\n"
    821+            "       \"") + "\""},
    


    MarcoFalke commented at 12:05 pm on August 21, 2019:
    You don’t need to pass in any whitespace here. Whitespace is done by RPCHelpMan

    kallewoof commented at 2:19 pm on August 21, 2019:
    Point. Fixed.
  176. in src/util/fees.cpp:35 in eda34393d5 outdated
    29@@ -28,8 +30,8 @@ std::string StringForFeeReason(FeeReason reason) {
    30     return reason_string->second;
    31 }
    32 
    33-const std::map<std::string, FeeEstimateMode>& FeeModeMap() {
    34-    static const std::map<std::string, FeeEstimateMode> fee_modes = {
    35+const std::vector<std::pair<std::string, FeeEstimateMode>>& FeeModeMap() {
    36+    static const std::vector<std::pair<std::string, FeeEstimateMode>> fee_modes = {
    


    MarcoFalke commented at 12:06 pm on August 21, 2019:
    could squash this commit (eda34393d51c59ace68e08df2d6e00870fe5d797)?

    kallewoof commented at 2:23 pm on August 21, 2019:
    Squashed.
  177. in src/wallet/rpcwallet.cpp:188 in 8e37fc83e7 outdated
    157@@ -158,6 +158,30 @@ static std::string LabelFromValue(const UniValue& value)
    158     return label;
    159 }
    160 
    161+static void SetFeeEstimateMode(CWallet* const pwallet, CCoinControl& cc, const UniValue& estimate_mode, const UniValue& estimate_param)
    


    MarcoFalke commented at 12:10 pm on August 21, 2019:
    style-nit: pwallet can be a reference, since it is non-nullable?

    kallewoof commented at 2:26 pm on August 21, 2019:
    You mean const CWallet& wallet instead? I don’t see that used very often anywhere, and it seems this thing is usually a std::shared_ptr.

    MarcoFalke commented at 2:39 pm on August 21, 2019:
    Heh, I’ll just link to #15922
  178. MarcoFalke commented at 12:11 pm on August 21, 2019: member
    Concept ACK. Some questions, which you are free to ignore.
  179. kallewoof force-pushed on Aug 21, 2019
  180. kallewoof force-pushed on Aug 21, 2019
  181. kallewoof force-pushed on Aug 21, 2019
  182. kallewoof force-pushed on Aug 22, 2019
  183. Sjors commented at 10:52 am on August 26, 2019: member
    Code review re-ACK c109001c9bb486eff3112d095a4639626273becc (and help text still looks correct)
  184. instagibbs commented at 1:46 pm on August 27, 2019: member
    concept ACK
  185. in src/wallet/rpcwallet.cpp:3352 in 1c0d97daa0 outdated
    3329                 {"estimate_mode", UniValueType(UniValue::VSTR)},
    3330             },
    3331             true, true);
    3332 
    3333-        if (options.exists("confTarget") && options.exists("totalFee")) {
    3334-            throw JSONRPCError(RPC_INVALID_PARAMETER, "confTarget and totalFee options should not both be set. Please provide either a confirmation target for fee estimation or an explicit total fee for the transaction.");
    


    promag commented at 2:46 pm on August 27, 2019:

    1c0d97daa09f2fc792b8675ea535ba03c8a7b86f

    There was no test for this 😞 And the new errors don’t have tests either. Care to add?


    kallewoof commented at 3:42 am on August 28, 2019:
    Added tests for invalid parameters.
  186. in src/util/fees.cpp:59 in 457396a409 outdated
    53+}
    54 
    55-    fee_estimate_mode = mode->second;
    56-    return true;
    57+bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
    58+    auto vector = FeeModeMap();
    


    promag commented at 3:02 pm on August 27, 2019:

    457396a4091bb3c27b1e982fb7e08442120b15df

    Why?


    kallewoof commented at 6:30 am on August 28, 2019:
    You mean why not just do : FeeModeMap() directly? Good point.
  187. in src/util/fees.cpp:32 in 457396a409 outdated
    28@@ -26,16 +29,32 @@ std::string StringForFeeReason(FeeReason reason) {
    29     return reason_string->second;
    30 }
    31 
    32-bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
    33-    static const std::map<std::string, FeeEstimateMode> fee_modes = {
    34+const std::vector<std::pair<std::string, FeeEstimateMode>>& FeeModeMap() {
    


    promag commented at 3:05 pm on August 27, 2019:

    457396a4091bb3c27b1e982fb7e08442120b15df

    Why have this as a function? Could be a static variable in this translation unit, like

    0static const std::vector<std::pair<std::string, FeeEstimateMode>> FEE_MODES{
    1    {"UNSET", FeeEstimateMode::UNSET},
    2    {"ECONOMICAL", FeeEstimateMode::ECONOMICAL},
    3    {"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE},
    4    {(CURRENCY_UNIT + "/KB"), FeeEstimateMode::BTC_KB},
    5    {(ToUpper(CURRENCY_ATOM) + "/B"), FeeEstimateMode::SAT_B},
    6};
    

    kallewoof commented at 3:44 am on August 28, 2019:
    Windows build breaks if I do this, unfortunately.

    kallewoof commented at 6:40 am on August 28, 2019:
    Now that ToUpper is no longer used, this may actually work in Windows; tentatively removing the function wrapper.
  188. in src/util/fees.cpp:42 in 457396a409 outdated
    41+    return fee_modes;
    42+}
    43 
    44-    if (mode == fee_modes.end()) return false;
    45+std::string FeeModes(const std::string& delimiter) {
    46+    std::ostringstream r;
    


    promag commented at 3:07 pm on August 27, 2019:

    457396a4091bb3c27b1e982fb7e08442120b15df

    Is it really necessary to #include <sstream> just to concat a couple of strings? Could just do

    0for (i : ...) {
    1    if (!res.empty()) res += delimiter;
    2    res += i.first
    3}
    

    kallewoof commented at 3:47 am on August 28, 2019:

    I don’t really see the harm in including it (it won’t make the binary bigger or anything) but it’s such a trivial set of operations that I doubt it’ll matter in the long run.

    I.e. removing the include and just stacking onto an std::string.

  189. in src/util/fees.cpp:43 in 457396a409 outdated
    40-    auto mode = fee_modes.find(mode_string);
    41+    return fee_modes;
    42+}
    43 
    44-    if (mode == fee_modes.end()) return false;
    45+std::string FeeModes(const std::string& delimiter) {
    


    promag commented at 3:09 pm on August 27, 2019:

    457396a4091bb3c27b1e982fb7e08442120b15df

    This is a utility function for the RPC help, I’d move to rpcwallet.cpp and make it static there.

    BTW, according to dev notes

    Braces on new lines for classes, functions, methods.


    kallewoof commented at 4:04 am on August 28, 2019:
    Fixed style.

    kallewoof commented at 6:43 am on August 28, 2019:
    Forgot to respond to the first point; I could move FeeModes, but it would mean having to make fee_modes available to the public, which doesn’t seem worth it.
  190. Sjors commented at 3:31 pm on August 27, 2019: member
    @promag it’s case insensitive to avoid bike-shedding “sat/B” vs. “SAT/B” and “BTC/kB” vs “BTC/KB”, and lower case is easier to type.
  191. in src/util/fees.cpp:61 in c109001c9b outdated
    59-    return true;
    60+bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
    61+    auto searchkey = ToUpper(mode_string);
    62+    auto vector = FeeModeMap();
    63+    for (const auto& pair : vector) {
    64+        if (pair.first == searchkey) {
    


    promag commented at 3:35 pm on August 27, 2019:

    Regarding https://github.com/bitcoin/bitcoin/pull/11413/files#r313929142

    Then I’d do ToUpper(pair.first) == searchkey) and display the right casing.


    kallewoof commented at 6:26 am on August 28, 2019:
    Done.
  192. kallewoof force-pushed on Aug 28, 2019
  193. kallewoof force-pushed on Aug 28, 2019
  194. kallewoof force-pushed on Aug 28, 2019
  195. kallewoof force-pushed on Aug 28, 2019
  196. kallewoof force-pushed on Aug 28, 2019
  197. Sjors commented at 8:02 am on August 28, 2019: member
    Mysterious Windows failure:
  198. kallewoof commented at 8:57 am on August 28, 2019: member
    @Sjors Ah.. yeah, I think I got that before as well. For some reason it fails to up-case..
  199. kallewoof force-pushed on Aug 28, 2019
  200. in src/util/fees.cpp:33 in aed101cf1c outdated
    37-        {"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE},
    38-    };
    39-    auto mode = fee_modes.find(mode_string);
    40-
    41-    if (mode == fee_modes.end()) return false;
    42+static const std::vector<std::pair<std::string, FeeEstimateMode>> fee_modes = {
    


    promag commented at 9:54 am on August 28, 2019:
    Should be FEE_MODES.
  201. in test/functional/wallet_bumpfee.py:99 in aed101cf1c outdated
    87@@ -87,6 +88,38 @@ def run_test(self):
    88         test_no_more_inputs_fails(rbf_node, dest_address)
    89         self.log.info("Success")
    90 
    91+def test_invalid_parameters(node, dest_address):
    92+    txid = spend_one_input(node, dest_address)
    93+    # invalid estimate mode
    94+    assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", node.bumpfee, txid, {
    


    promag commented at 11:55 am on August 28, 2019:
    nit, space after : here and below.
  202. in doc/release-notes-11413.md:5 in aed101cf1c outdated
    0@@ -0,0 +1,10 @@
    1+Updated or changed RPC
    2+----------------------
    3+
    4+The `bumpfee`, `fundrawtransaction`, `sendmany`, `sendtoaddress`, and `walletcreatefundedpsbt`
    5+RPC commands have been updated to include two new fee estimation methods "BTC/KB" and "SAT/B".
    


    promag commented at 11:55 am on August 28, 2019:
    fix case.
  203. in doc/release-notes-11413.md:11 in aed101cf1c outdated
     5+RPC commands have been updated to include two new fee estimation methods "BTC/KB" and "SAT/B".
     6+The target is the fee expressed explicitly in the given form.
     7+
     8+In addition, the estimate_mode parameter is now case insensitive for all of the above RPC commands.
     9+
    10+The `bumpfee` command now uses `conf_target` rather than `confTarget` in the options.
    


    promag commented at 11:56 am on August 28, 2019:
    Should mention that confTarget is still supported but clients should transition to conf_target.

    kallewoof commented at 1:06 pm on August 28, 2019:
    I don’t really see the point. Literally nobody will be affected by this (i.e. they will either see the release notes and switch, or not see them and not notice the change).
  204. in src/util/fees.cpp:45 in aed101cf1c outdated
    49+
    50+std::string FeeModes(const std::string& delimiter)
    51+{
    52+    std::string r;
    53+    std::string prefix = "";
    54+    for (const auto& i : fee_modes) {
    


    promag commented at 11:58 am on August 28, 2019:
    s/i/pair like below?
  205. kallewoof force-pushed on Aug 28, 2019
  206. kallewoof commented at 2:50 pm on August 28, 2019: member

    Yikes… turning back into a function. @promag

    Actually gonna see if adding const strings for the two fee rates fixes it.

    Edit: const strings did not help.

  207. kallewoof force-pushed on Aug 28, 2019
  208. kallewoof force-pushed on Aug 28, 2019
  209. kallewoof force-pushed on Aug 28, 2019
  210. promag commented at 6:44 pm on August 28, 2019: member
    @kallewoof well..
  211. kallewoof force-pushed on Aug 29, 2019
  212. kallewoof force-pushed on Aug 29, 2019
  213. kallewoof commented at 4:19 am on August 29, 2019: member
    @promag Sorry, screwed up rebase; reverted now.
  214. kallewoof force-pushed on Aug 29, 2019
  215. kallewoof commented at 6:40 am on August 29, 2019: member
    I found a different workaround; apparently MSVC does not bug out if you put the const std::strings in the .h file. We do that elsewhere so I assume nobody will complain about moving CURRENCY_UNIT into feerate.h from feerate.cpp.
  216. kallewoof force-pushed on Aug 29, 2019
  217. kallewoof force-pushed on Aug 29, 2019
  218. promag commented at 10:25 am on August 29, 2019: member
    Shouldn’t conf_target be required when using an explicit estimate mode?
  219. kallewoof force-pushed on Aug 29, 2019
  220. kallewoof commented at 11:51 am on August 29, 2019: member
    @promag It should indeed. I added tests and fixed this.
  221. in src/wallet/rpcwallet.cpp:182 in a69cb01737 outdated
    177+            fee_rate /= 100000; // 1 sat / B = 0.00001 BTC / kB
    178+        }
    179+        cc.m_feerate = CFeeRate(fee_rate);
    180+        // default RBF to true for explicit fee rate modes
    181+        if (cc.m_signal_bip125_rbf == boost::none) cc.m_signal_bip125_rbf = true;
    182+    } else {
    


    promag commented at 11:55 am on August 29, 2019:
    else if (! estimate_param.isNull()) {?

    kallewoof commented at 2:21 pm on August 29, 2019:
    Done
  222. kallewoof force-pushed on Aug 29, 2019
  223. instagibbs commented at 6:42 pm on August 30, 2019: member

    concept ACK, but I am really wary of the implementation of the arguments.

    The meaning of conf_target basically inverts with this new argument. Consider: sendtoaddress 2N7GTLzhS9n3FzwAQohAgnk2kGvt8eE9nng 1 "" "" false true 1008

    and

    sendtoaddress 2N7GTLzhS9n3FzwAQohAgnk2kGvt8eE9nng 1 "" "" false true 1008 sat/B

    and the opposite way: 1 vs 1 sat/B is likely considerable.

    I’d rather we “overload” the conf_target and parse 30sat/B directly, disallowing estimate mode to be specified maybe other than unset.

  224. in test/functional/wallet_basic.py:469 in 3a29129e86 outdated
    416+        self.nodes[0].generate(1)
    417+        self.sync_all(self.nodes[0:3])
    418+        postbalance = self.nodes[2].getbalance()
    419+        fee = prebalance - postbalance - Decimal('1')
    420+        assert_fee_amount(fee, tx_size, Decimal('0.00002000'))
    421+
    


    instagibbs commented at 6:45 pm on August 30, 2019:
    Add a test for negative/too low feerates?

    kallewoof commented at 4:35 am on September 2, 2019:
    Done
  225. Sjors commented at 6:47 pm on August 30, 2019: member

    I’d rather we “overload” the conf_target and parse 30sat/B directly, disallowing estimate mode to be specified maybe other than unset.

    If that’s easy to implement I also think it’s significantly more clear.

  226. instagibbs commented at 6:57 pm on August 30, 2019: member
    The issue still remains for someone who types 1 and forgets to write sat/B. I’m not sure if there’s a backwards compatible way to solve this.
  227. luke-jr commented at 8:26 pm on August 30, 2019: member

    Specifying an amount as a string like that is completely foreign to all existing RPC interfaces.

    The number is already interpreted differently based on the mode string.

  228. luke-jr commented at 8:28 pm on August 30, 2019: member

    Maybe conf_target as a named param should reject explicit modes, and it should be specified as another named param for explicit?

    That might require #11660

  229. kallewoof force-pushed on Sep 2, 2019
  230. kallewoof commented at 4:48 am on September 2, 2019: member

    @instagibbs Yeah, typing ‘1’ would mean ‘confirm within 1 block’ which is directly opposite of ‘1 sat/b’.

    Adding number suffixes only partially solves the problem. Someone who accidentally hits enter forgetting the ‘sat/b’ suffix will have exactly the same issue.

    Perhaps the explicit modes should not overload conf_target but instead use a new argument entirely. Alternatively we make the estimate_mode include the actual number, so people will do

    0[...]conf_target=null estimate_mode=1sat/b [...]
    

    which means the ambiguity is removed. If they do estimate_mode=1 it will error. And conf_target no longer both means “low value = high priority = potentially high fees” and “low value = low fees” at the same time, depending on which estimate mode is used at the time.

  231. kallewoof force-pushed on Sep 2, 2019
  232. kallewoof commented at 5:32 am on September 2, 2019: member
    Another alternative is to actually require suffixes for all conf_targets, but that is a compatibility breach (1 block, 1 sat/b, 1 btc/kb).
  233. Sjors commented at 11:26 am on September 2, 2019: member

    I don’t like including the string in the same param (without a space). Nor do I like the verboseness of named params.

    Making a breaking change might be worth it for the extra safety. It would fail quite gracefully, i.e. it just stops sending. The impact can be reduced by not requiring estimate_mode when using named parameters.

  234. luke-jr referenced this in commit 5f1be949ae on Sep 3, 2019
  235. DrahtBot added the label Needs rebase on Oct 2, 2019
  236. laanwj added the label Feature on Oct 2, 2019
  237. kallewoof force-pushed on Oct 3, 2019
  238. DrahtBot removed the label Needs rebase on Oct 3, 2019
  239. in src/wallet/rpcwallet.cpp:198 in 97636cd371 outdated
    193+        if (cc.m_fee_mode == FeeEstimateMode::SAT_B) {
    194+            fee_rate /= 100000; // 1 sat / B = 0.00001 BTC / kB
    195+        }
    196+        cc.m_feerate = CFeeRate(fee_rate);
    197+        // if feerate < 0.1 sat/b, throw
    198+        if (fee_rate < 100) {
    


    luke-jr commented at 4:45 pm on October 17, 2019:
    This shouldn’t be hard-coded

    kallewoof commented at 7:07 am on October 18, 2019:
    Turned into constant. Also did same for the conversion a few lines above.
  240. kallewoof force-pushed on Oct 18, 2019
  241. kallewoof force-pushed on Oct 18, 2019
  242. in src/wallet/rpcwallet.cpp:44 in 8a7882a91f outdated
    38@@ -39,6 +39,10 @@
    39 
    40 static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
    41 
    42+static const uint32_t WALLET_MIN_FEERATE = 100; // sat/b
    43+
    44+static const uint32_t WALLET_BTC_KB_TO_SAT_B = 100000; // 1 sat / B = 0.00001 BTC / kB
    


    luke-jr commented at 4:45 pm on October 21, 2019:
    Please use the COIN const for this…

    kallewoof commented at 3:25 am on October 24, 2019:
    Changed to COIN / 1000.
  243. in src/wallet/rpcwallet.cpp:42 in 8a7882a91f outdated
    38@@ -39,6 +39,10 @@
    39 
    40 static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
    41 
    42+static const uint32_t WALLET_MIN_FEERATE = 100; // sat/b
    


    luke-jr commented at 4:46 pm on October 21, 2019:
    This is wrong. Relay min feerate is already defined elsewhere, and user-configurable.

    kallewoof commented at 3:30 am on October 24, 2019:
    Using DEFAULT_MIN_RELAY_TX_FEE instead.

    kallewoof commented at 3:32 am on October 24, 2019:
    Actually, I would have to include validation.h to access that, and I can’t access it via extern because it’s static. I’m just doing 1000 /* DEFAULT_MIN_RELAY_TX_FEE */ for now.

    luke-jr commented at 3:43 am on October 24, 2019:
    Using the default would be wrong too. It should use the configured policy or current mempool limit…

    kallewoof commented at 3:57 am on October 24, 2019:
    I don’t see a problem with someone making a tx that is not relayable at this point in time (but relayable when tx traffic drops). In fact, I’m not even sure this check is necessary in the first place.

    luke-jr commented at 12:09 pm on October 24, 2019:
    In that case, it should be the configured relay minimum policy (or no check at all).

    kallewoof commented at 2:30 am on October 25, 2019:
    I’m honestly leaning towards removing this check. Thanks for the nudge.
  244. kallewoof force-pushed on Oct 24, 2019
  245. kallewoof force-pushed on Oct 25, 2019
  246. kallewoof force-pushed on Oct 29, 2019
  247. kallewoof force-pushed on Nov 1, 2019
  248. Sjors commented at 4:41 pm on November 1, 2019: member

    Tested ACK 398be1c modulo squash.

    Positional arguments are nigh-impossible to use, but let’s worry about that later…

    0bitcoin-cli sendtoaddress bc... 1 "" "" false true 1 sat/b
    1bitcoin-cli sendmany "" '{"bc...": 1}' 0 "" '[]' true 1 sat/b
    

    A mix of positional and named kind of works:

    0sendtoaddress bcrt1qgr3zfmvqzl4uv3utz6h849x0fu5a8mvg695jde 1 -conf_target=1 estimate_mode=sat/b
    
  249. luke-jr referenced this in commit 3cea15ad1d on Nov 15, 2019
  250. luke-jr referenced this in commit 9cd046568a on Nov 15, 2019
  251. luke-jr referenced this in commit c2f29682ee on Nov 15, 2019
  252. luke-jr referenced this in commit 399dc09052 on Jan 12, 2020
  253. luke-jr referenced this in commit 6c40dcb3dd on Jan 12, 2020
  254. luke-jr referenced this in commit 4c6e72a068 on Jan 12, 2020
  255. in test/functional/wallet_basic.py:398 in 398be1c0f3 outdated
    390@@ -338,6 +391,74 @@ def run_test(self):
    391         # This will raise an exception for importing an invalid pubkey
    392         assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f")
    393 
    394+        # send with explicit btc/kb fee
    395+        self.sync_all(self.nodes[0:3])
    396+        self.log.info("test explicit fee (sendtoaddress as btc/kb)")
    397+        self.nodes[0].generate(1)
    


    luke-jr commented at 4:33 am on January 16, 2020:
    The sync_all needs to be moved after generate, or prebalance could end up with a stale balance and cause the check below (line 426) to fail.

    kallewoof commented at 4:44 am on January 16, 2020:
    Moved.
  256. kallewoof force-pushed on Jan 16, 2020
  257. kallewoof force-pushed on Jan 16, 2020
  258. Sjors commented at 12:43 pm on January 16, 2020: member
    Code review re-ACK 9721534f1c929ce275ac0516d5777bc1063f7495
  259. luke-jr referenced this in commit 296f665983 on Jan 16, 2020
  260. luke-jr referenced this in commit ee7255ddc8 on Jan 16, 2020
  261. Sjors commented at 3:44 pm on February 20, 2020: member
    Still works when rebased. @achow101 @instagibbs maybe you can (re-)review?
  262. in src/wallet/rpcwallet.cpp:3255 in c7d20ff95a outdated
    3340@@ -3341,7 +3341,7 @@ static UniValue bumpfee(const JSONRPCRequest& request)
    3341                     {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid to be bumped"},
    3342                     {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
    3343                         {
    3344-                            {"confTarget", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
    3345+                            {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
    


    instagibbs commented at 3:20 pm on February 26, 2020:
    convert tests for coverage?

    kallewoof commented at 4:43 am on March 2, 2020:
    I thought I did – which one did I miss?

    instagibbs commented at 2:52 pm on March 2, 2020:
    For that commit I didn’t see any changes… I’ll look again
  263. in src/wallet/rpcwallet.cpp:198 in bca8d502f5 outdated
    193+        }
    194+    }
    195+
    196+    if (cc.m_fee_mode == FeeEstimateMode::BTC_KB || cc.m_fee_mode == FeeEstimateMode::SAT_B) {
    197+        if (estimate_param.isNull()) {
    198+            throw JSONRPCError(RPC_INVALID_PARAMETER, "Selected estimate_mode requires a confirmation target");
    


    instagibbs commented at 3:30 pm on February 26, 2020:
    s/confirmation target/fee rate/ ?

    kallewoof commented at 4:45 am on March 2, 2020:
    Right! Thanks.
  264. in src/wallet/rpcwallet.cpp:188 in bca8d502f5 outdated
    184@@ -183,6 +185,33 @@ static std::string LabelFromValue(const UniValue& value)
    185     return label;
    186 }
    187 
    188+static void SetFeeEstimateMode(CWallet* const pwallet, CCoinControl& cc, const UniValue& estimate_mode, const UniValue& estimate_param)
    


    instagibbs commented at 3:30 pm on February 26, 2020:
    A bit of documentation would go a long way for function declaration.

    kallewoof commented at 8:36 am on March 2, 2020:
    Added documentation!
  265. in doc/release-notes-11413.md:4 in 986075dcdd outdated
    0@@ -0,0 +1,10 @@
    1+Updated or changed RPC
    2+----------------------
    3+
    4+The `bumpfee`, `fundrawtransaction`, `sendmany`, `sendtoaddress`, and `walletcreatefundedpsbt`
    


    instagibbs commented at 3:39 pm on February 26, 2020:
    Note that this will also trigger bip125 opt-in.

    kallewoof commented at 8:35 am on March 2, 2020:
    Added note.
  266. instagibbs commented at 3:41 pm on February 26, 2020: member
    looks good, couple of notes
  267. kallewoof force-pushed on Mar 2, 2020
  268. kallewoof force-pushed on Mar 2, 2020
  269. kallewoof commented at 8:37 am on March 2, 2020: member
    @instagibbs Thanks for the review! Addressed everything except the coverage part which I am hoping you’ll clarify.
  270. Sjors commented at 8:39 am on March 2, 2020: member

    ~Code review re-ACK 74f9d2797bd199fcd4cfc30e490bbac6224424f9~

    Actually there’s a problem the user tries to set the fee rate to 0.1 sat/b. It silently rounds up to 1. This should throw an error or work (setting the fee slightly below the min relay fee, e.g. 1.2 sat/b can be useful).

    To reproduce, add this to wallet_basic_py

     0        txid = self.nodes[2].sendtoaddress(
     1            address=address,
     2            amount=1.0,
     3            conf_target=0.2,
     4            estimate_mode='SAT/B',
     5        )
     6        tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
     7        self.sync_all(self.nodes[0:3])
     8        self.nodes[0].generate(1)
     9        self.sync_all(self.nodes[0:3])
    10        postbalance = self.nodes[2].getbalance()
    11        fee = prebalance - postbalance - Decimal('1')
    12        assert_fee_amount(fee, tx_size, Decimal('0.00000200'))
    

    Result:

    0  File "test/functional/wallet_basic.py", line 476, in run_test
    1    assert_fee_amount(fee, tx_size, Decimal('0.00000200'))
    2  File "/Users/sjors/dev/bitcoin/test/functional/test_framework/util.py", line 42, in assert_fee_amount
    3    raise AssertionError("Fee of %s BTC too high! (Should be %s BTC)" % (str(fee), str(target_fee)))
    4AssertionError: Fee of 1.00000423 BTC too high! (Should be 2.8E-7 BTC)
    
  271. kallewoof commented at 3:15 pm on March 2, 2020: member
    @Sjors Nice, good catch! Where in wallet_basic did you add that test, btw?
  272. kallewoof commented at 5:10 am on March 3, 2020: member

    Updated code to now return an error when creating a transaction if the requested explicit fee rate differs from the required fee rate. This prevents silently ignoring the user when they want a fee rate < ~1 sat/b~ the current minimum fee rate (which may change due to mempool state, and/or future changes to the current 1 sat/b minimum policy default) – it now gives an error, as you would expect.

    Edit: changed from “1 sat/b” to a more accurate description.

  273. in src/wallet/wallet.cpp:2666 in 77d73422b0 outdated
    2659@@ -2660,6 +2660,12 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
    2660 
    2661             // Get the fee rate to use effective values in coin selection
    2662             CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, &feeCalc);
    2663+            // Do not, ever, assume that it's fine to change the fee rate if the user has explicitly
    2664+            // provided one
    2665+            if (coin_control.m_feerate && nFeeRateNeeded != *coin_control.m_feerate) {
    2666+                strFailReason = "Fee rate needed differs from explicitly provided fee rate";
    


    Sjors commented at 5:24 pm on March 3, 2020:
    “needed” is rather vague. I assume this is based on the mempool relay fee? So maybe: Fee rate is too low for the current mempool. Increase it to %f sat/b or modify -maxmempool

    kallewoof commented at 2:11 am on March 4, 2020:

    That’s a bit weird, though, for the case when the relay fee is at the minimum. We can’t really ask people to change minrelaytxfee either, as that would mean their node ends up with non-relayable (to most other nodes) transactions. I don’t really see a better alternative though, so I’m going with your version with some tweaks:

    I built on this a tiny bit, adding a new optional FeeEstimateMode parameter to CFeeRate::ToString(), which returns sat/b formatted fee rate if estimate mode is sat/b, otherwise the (pre-existing) btc/kb fee rate. So if a user provides an explicit fee rate using sat/b, they get the needed one back in sat/b, otherwise it is expressed in btc/kb.


    Sjors commented at 9:19 am on March 4, 2020:
    There have been occasional rumblings of allowing a lower relay fee than 1 sat/byte, so it’s nice to future proof. It’s not an ideal message, but definitely better than silently changing the input.

    kallewoof commented at 9:23 am on March 4, 2020:
    This should cover for the <1sat/b case as well. All the way down to 0.001 sat/b.

    kallewoof commented at 9:52 am on March 4, 2020:
    I updated #11413 (comment) a bit to clarify that 1 sat/b is not a hardcoded thing.

    Sjors commented at 10:10 am on March 4, 2020:

    IIUC coin selection uses nFeeRateNeeded here:

    0coin_selection_params.effective_fee = nFeeRateNeeded;
    

    This doesn’t make sense for transaction with a future nLockTime, and with PSBTs it’s debatable, since we don’t know when the user intends to broadcast. For sendmany and sendtoaddress the current behavior is fine, because those RPCs don’t support nLockTime and PSBT.

    For PSBT I’m inclined to think that effective_fee should be set to the manual fee. In #16378 I plan to do the same for the new send RPC. It returns the hex in that case (as it does with nLockTime).


    kallewoof commented at 10:19 am on March 4, 2020:

    So basically, you’d prefer if I could force a transaction using a fee rate that is currently not actually accepted by the mempool? I initially did that, but the result is that the tx goes into the mempool but is rejected by the node’s peers, so it is never mined (unless the node itself generates a block). That seems awfully confusing.

    Perhaps there should be an exception for the locktime>now case, where a warning is produced but the tx is created since it can’t go into the mempool anyway, due to locktime not unfulfilled.

    This can be achieved by setting the fOverrideFeeRate to true, btw.


    Sjors commented at 10:22 am on March 4, 2020:
    I think the current error is fine when the user intends to broadcast immediately. Only when that’s not clearly the case, e.g. for the PSBT methods, we should still allow transaction creation.

    Sjors commented at 10:24 am on March 4, 2020:
    fOverrideFeeRate could do the trick, but it’s pretty ugly: it basically “sabotages” GetMinimumFeeRate. It seems more readable to skip GetMinimumFeeRate altogether when you want to ignore it.
  274. kallewoof force-pushed on Mar 4, 2020
  275. kallewoof force-pushed on Mar 4, 2020
  276. kallewoof force-pushed on Mar 4, 2020
  277. in src/policy/feerate.cpp:41 in 5febd8a183 outdated
    34@@ -37,7 +35,10 @@ CAmount CFeeRate::GetFee(size_t nBytes_) const
    35     return nFee;
    36 }
    37 
    38-std::string CFeeRate::ToString() const
    39+std::string CFeeRate::ToString(const FeeEstimateMode& fee_estimate_mode) const
    40 {
    41-    return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT);
    42+    switch (fee_estimate_mode) {
    43+    case FeeEstimateMode::SAT_B:  return strprintf("%d.%03d %s/b", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM);
    


    luke-jr commented at 11:22 pm on March 4, 2020:
    Satoshis per bit?

    kallewoof commented at 1:35 am on March 5, 2020:
    Good catch, fixed!
  278. kallewoof force-pushed on Mar 5, 2020
  279. kallewoof force-pushed on Mar 5, 2020
  280. in src/wallet/wallet.cpp:2724 in 7c4efefab2 outdated
    2582@@ -2583,6 +2583,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
    2583                          int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign)
    2584 {
    2585     CAmount nValue = 0;
    2586+    nFeeRet = 0;
    


    instagibbs commented at 2:19 pm on March 5, 2020:
    is this valuable by itself?

    kallewoof commented at 3:17 am on March 6, 2020:

    Probably. I had a garbage value being returned and it ended up telling me “you need at least 4587368374.13587638 bitcoin in fees!” here:

    https://github.com/bitcoin/bitcoin/blob/3f826598a42dcc707b58224e94c394e30a42ceee/src/wallet/rpcwallet.cpp#L353-L357


    kallewoof commented at 5:06 am on March 6, 2020:
    PR-ified as #18274.
  281. in src/wallet/wallet.cpp:2744 in 2f13183751 outdated
    2659@@ -2660,6 +2660,12 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
    2660 
    2661             // Get the fee rate to use effective values in coin selection
    2662             CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, &feeCalc);
    2663+            // Do not, ever, assume that it's fine to change the fee rate if the user has explicitly
    


    instagibbs commented at 2:19 pm on March 5, 2020:
    same question: this seems good irrespective of this PR

    kallewoof commented at 3:18 am on March 6, 2020:
    Yeah, it could be its own PR. Maybe I should split these out..

    kallewoof commented at 5:13 am on March 6, 2020:
    PR-ified in #18275.
  282. instagibbs approved
  283. instagibbs commented at 3:23 pm on March 5, 2020: member
  284. luke-jr referenced this in commit 781e816cf1 on Mar 5, 2020
  285. luke-jr referenced this in commit 4e9be35e87 on Mar 5, 2020
  286. luke-jr referenced this in commit 5725c9c605 on Mar 5, 2020
  287. luke-jr referenced this in commit 940408c72a on Mar 5, 2020
  288. instagibbs commented at 4:40 pm on March 5, 2020: member
    something to think about out loud for the future: If we want to support implicit CPFP, this new mode would probably turn that off, at least by default.
  289. in src/wallet/wallet.cpp:2803 in 2f13183751 outdated
    2659@@ -2660,6 +2660,12 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
    2660 
    2661             // Get the fee rate to use effective values in coin selection
    2662             CFeeRate nFeeRateNeeded = GetMinimumFeeRate(*this, coin_control, &feeCalc);
    2663+            // Do not, ever, assume that it's fine to change the fee rate if the user has explicitly
    2664+            // provided one
    2665+            if (coin_control.m_feerate && nFeeRateNeeded > *coin_control.m_feerate) {
    2666+                strFailReason = strprintf("Fee rate is too low for the current mempool. Increase it to %s or modify -maxmempool", nFeeRateNeeded.ToString(coin_control.m_fee_mode));
    


    instagibbs commented at 4:44 pm on March 5, 2020:
    Actually I find this -maxmempool advice pretty dangerous for users. It’s going to simply result in stuck transactions, no?

    kallewoof commented at 3:22 am on March 6, 2020:
    I think it might get stuck for the user themselves, but unless their peers also increase their mempool sizes, it won’t propagate very far. But I’m now a bit hesitant to suggest using it as it’ll probably not do what people expect. (As you say, it will get stuck in the sense that it won’t get mined or propagate properly..)

    Sjors commented at 5:26 pm on March 6, 2020:
    That’s something we can point out in -maxmempool documentation. Once #18038 lands the mempool will at least hold on to the transaction if you unload a wallet.

    sipa commented at 3:01 am on March 13, 2020:
    Agree that we shouldn’t mention -maxmempool here; it indeed likely will not do what users expect it to do.

    kallewoof commented at 4:19 am on March 13, 2020:
    Changed to “Fee rate is too low for the current mempool. Increase it to %s or wait.”
  290. kallewoof force-pushed on Mar 6, 2020
  291. DrahtBot added the label Needs rebase on Mar 7, 2020
  292. kallewoof force-pushed on Mar 7, 2020
  293. DrahtBot removed the label Needs rebase on Mar 7, 2020
  294. DrahtBot added the label Needs rebase on Mar 11, 2020
  295. kallewoof force-pushed on Mar 12, 2020
  296. DrahtBot removed the label Needs rebase on Mar 12, 2020
  297. Sjors commented at 12:15 pm on March 12, 2020: member
    re-ACK 8326a544b7839e362c7e530bebfffb02ba1ddb34 modulo rebase for #18274 (which contains 7864c1f)
  298. kallewoof force-pushed on Mar 12, 2020
  299. kallewoof commented at 12:45 pm on March 12, 2020: member
    Good catch; dropped 7864c1f.
  300. Sjors commented at 1:41 pm on March 12, 2020: member
    utACK 04e94beb1d9f22809b64bda2c7e92c1e911d2227
  301. fanquake requested review from meshcollider on Mar 13, 2020
  302. in doc/release-notes-11413.md:7 in 04e94beb1d outdated
    0@@ -0,0 +1,11 @@
    1+Updated or changed RPC
    2+----------------------
    3+
    4+The `bumpfee`, `fundrawtransaction`, `sendmany`, `sendtoaddress`, and `walletcreatefundedpsbt`
    5+RPC commands have been updated to include two new fee estimation methods "BTC/kB" and "sat/B".
    6+The target is the fee expressed explicitly in the given form. Note that use of this feature
    7+will trigger bip125 (replace-by-fee) opt-in.
    


    sipa commented at 2:58 am on March 13, 2020:
    Nit: BIP is usually capitalized.
  303. sipa commented at 3:03 am on March 13, 2020: member
    utACK 04e94beb1d9f22809b64bda2c7e92c1e911d2227, apart from the -maxmempool nit below.
  304. kallewoof force-pushed on Mar 13, 2020
  305. kallewoof commented at 5:03 am on March 13, 2020: member
    Addressed @sipa comments. Please re-review! :)
  306. fanquake requested review from Sjors on Mar 13, 2020
  307. fanquake requested review from sipa on Mar 13, 2020
  308. fanquake requested review from instagibbs on Mar 13, 2020
  309. kallewoof force-pushed on Mar 13, 2020
  310. Sjors approved
  311. Sjors commented at 4:58 pm on March 13, 2020: member
    re-utACK 6fef8dcd771f1a628d2c4bee2682a98312bcd80b: recommending patience can’t hurt :-)
  312. DrahtBot added the label Needs rebase on Mar 26, 2020
  313. kallewoof force-pushed on Mar 30, 2020
  314. kallewoof commented at 7:55 am on March 30, 2020: member
    Rebased
  315. DrahtBot removed the label Needs rebase on Mar 30, 2020
  316. Sjors commented at 9:23 am on March 30, 2020: member
    re-utACK a29b9939b6537e60a9dd47e0ae49968851cac251
  317. DrahtBot added the label Needs rebase on Apr 27, 2020
  318. kallewoof force-pushed on Apr 28, 2020
  319. kallewoof force-pushed on Apr 28, 2020
  320. DrahtBot removed the label Needs rebase on Apr 28, 2020
  321. Sjors commented at 6:36 pm on April 28, 2020: member
    re-utACK 9afd897, just a rebase and some tests have moved.
  322. in test/functional/wallet_basic.py:486 in 9afd897104 outdated
    481+            # 1. Send some coins to generate new UTXO
    482+            address_to_import = self.nodes[2].getnewaddress()
    483+            txid = self.nodes[0].sendtoaddress(address_to_import, 1)
    484+            self.nodes[0].generate(1)
    485+            self.sync_all(self.nodes[0:3])
    486+
    


    luke-jr commented at 2:19 am on May 9, 2020:
    I believe this was a mis-rebase. This test goes back to 2016, and is above the added tests (prior to the rebase, it was here, below the added tests)

    kallewoof commented at 4:47 am on May 9, 2020:
    Yes, that is correct! Good catch. Fixed.
  323. kallewoof force-pushed on May 9, 2020
  324. kallewoof force-pushed on May 9, 2020
  325. kallewoof commented at 5:03 am on May 9, 2020: member
    Dropped ‘fee rate changed’ commit, as it is its own PR now (#18275).
  326. kallewoof force-pushed on May 10, 2020
  327. luke-jr referenced this in commit 27c462a3fa on Jun 9, 2020
  328. luke-jr referenced this in commit f68ea7c542 on Jun 9, 2020
  329. luke-jr referenced this in commit 2612e4808d on Jun 9, 2020
  330. luke-jr referenced this in commit dace8ef7b7 on Jun 9, 2020
  331. luke-jr referenced this in commit e08e516d89 on Jun 9, 2020
  332. luke-jr referenced this in commit 56bd8c3404 on Jun 9, 2020
  333. in src/util/fees.cpp:41 in 53342290f4 outdated
    43+static const std::vector<std::pair<std::string, FeeEstimateMode>> FEE_MODES = {
    44+    {"unset", FeeEstimateMode::UNSET},
    45+    {"economical", FeeEstimateMode::ECONOMICAL},
    46+    {"conservative", FeeEstimateMode::CONSERVATIVE},
    47+    {(CURRENCY_UNIT + "/kB"), FeeEstimateMode::BTC_KB},
    48+    {(CURRENCY_ATOM + "/B"), FeeEstimateMode::SAT_B},
    


    luke-jr commented at 7:15 am on June 14, 2020:
    We can’t use CURRENCY_* here in global scope, since the initialisation order is undefined. A simple static function wrapper should work.

    kallewoof commented at 6:01 am on June 16, 2020:
    Odd that no compiler warning or anything was emitted about it. I’ve updated the code to wrap the map.

    Sjors commented at 9:58 am on June 16, 2020:
    For future reference, the original: 3bad9a438769c6749063ab5ab405a62f6efea8cc
  334. jonatack commented at 4:07 pm on June 15, 2020: member
    Concept ACK
  335. kallewoof force-pushed on Jun 16, 2020
  336. Sjors commented at 10:05 am on June 16, 2020: member
    re-tACK a9ad35d3016d9d912472861895b8f5160e24cc12
  337. MarcoFalke referenced this in commit 23b2a68df5 on Jun 16, 2020
  338. meshcollider added this to the "PRs" column in a project

  339. added CURRENCY_ATOM to express minimum indivisible unit
    also moved CURRENCY_* into feerate.h file to work around MSVC bug
    69158b41fc
  340. rpc/wallet: add conf_target as alias to confTarget in bumpfee 91f6d2bc8f
  341. kallewoof force-pushed on Jun 20, 2020
  342. kallewoof commented at 6:36 am on June 20, 2020: member
    Rebased to see if weird FreeBSD error would go away. No changes since a9ad35d
  343. in src/util/fees.cpp:51 in 5ee0e46b93 outdated
    53 
    54-    if (mode == fee_modes.end()) return false;
    55+std::string FeeModes(const std::string& delimiter)
    56+{
    57+    std::string r;
    58+    std::string prefix = "";
    


    jonatack commented at 10:00 am on June 20, 2020:
    0ebb85b perhaps use Join() in util/string.h
  344. in src/util/fees.cpp:49 in 5ee0e46b93 outdated
    50-    auto mode = fee_modes.find(mode_string);
    51+    return FEE_MODES;
    52+}
    53 
    54-    if (mode == fee_modes.end()) return false;
    55+std::string FeeModes(const std::string& delimiter)
    


    jonatack commented at 8:34 am on June 21, 2020:
    0ebb85b8c39668f314d7cc8a2108ec6012bdd3d1 perhaps add "\"\n\"" as a default value for delimiter

    kallewoof commented at 6:55 am on June 24, 2020:
    Seems like an odd default, tbh, even though it would reduce code elsewhere.
  345. in test/functional/wallet_basic.py:244 in 5ee0e46b93 outdated
    239+            estimate_mode='bTc/kB',
    240+        )
    241+        self.nodes[2].generate(1)
    242+        self.sync_all(self.nodes[0:3])
    243+        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
    244+        assert_equal(self.nodes[2].getbalance(), node_2_bal)
    


    jonatack commented at 8:59 am on June 21, 2020:

    69823cc nit (feel free to ignore) if you retouch, can avoid a getbalance call here and also lines 270-271 below

    0-        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
    1-        assert_equal(self.nodes[2].getbalance(), node_2_bal)
    2+        balance = self.nodes[2].getbalance()
    3+        node_2_bal = self.check_fee_amount(balance, node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
    4+        assert_equal(balance, node_2_bal)
    

    kallewoof commented at 6:57 am on June 24, 2020:
    Done.
  346. in test/functional/wallet_bumpfee.py:127 in 5ee0e46b93 outdated
    122+    })
    123+    # conf_target and totalFee (depends on -deprecatedrpc=totalFee)
    124+    assert_raises_rpc_error(-3, "Unexpected key totalFee", node.bumpfee, txid, {
    125+        "conf_target": 123,
    126+        "totalFee": 456,
    127+    })
    


    jonatack commented at 9:26 am on June 21, 2020:
    69823cc can omit lines 118-127 as the totalFee argument is now removed

    kallewoof commented at 6:58 am on June 24, 2020:
    Thanks, done!
  347. in doc/release-notes-11413.md:9 in 5ee0e46b93 outdated
    0@@ -0,0 +1,11 @@
    1+Updated or changed RPC
    2+----------------------
    3+
    4+The `bumpfee`, `fundrawtransaction`, `sendmany`, `sendtoaddress`, and `walletcreatefundedpsbt`
    5+RPC commands have been updated to include two new fee estimation methods "BTC/kB" and "sat/B".
    6+The target is the fee expressed explicitly in the given form. Note that use of this feature
    7+will trigger BIP 125 (replace-by-fee) opt-in.
    8+
    9+In addition, the estimate_mode parameter is now case insensitive for all of the above RPC commands.
    


    jonatack commented at 9:34 am on June 21, 2020:
    5ee0e46 nit: s/estimate_mode/estimate_mode/
  348. in doc/release-notes-11413.md:5 in 5ee0e46b93 outdated
    0@@ -0,0 +1,11 @@
    1+Updated or changed RPC
    2+----------------------
    3+
    4+The `bumpfee`, `fundrawtransaction`, `sendmany`, `sendtoaddress`, and `walletcreatefundedpsbt`
    5+RPC commands have been updated to include two new fee estimation methods "BTC/kB" and "sat/B".
    


    jonatack commented at 9:35 am on June 21, 2020:
    5ee0e46 nit: missing comma after “methods”

    kallewoof commented at 6:59 am on June 24, 2020:
    I think it’s okay as it is. The methods a and b were added.
  349. in src/wallet/rpcwallet.cpp:424 in 5ee0e46b93 outdated
    420@@ -385,6 +421,8 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
    421             + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"seans outpost\"")
    422             + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" true")
    423             + HelpExampleRpc("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 0.1, \"donation\", \"seans outpost\"")
    424+            + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" false true 0.00002 " + (CURRENCY_UNIT + "/kB"))
    425+            + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" false true 2 " + (CURRENCY_ATOM + "/B"))
    


    jonatack commented at 9:43 am on June 21, 2020:

    0fb63f0 these two lines should be placed before the HelpExampleRpc in line 423, as currently the help prints:

    0Examples:
    1> bitcoin-cli sendtoaddress "bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl" 0.1
    2> bitcoin-cli sendtoaddress "bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl" 0.1 "donation" "seans outpost"
    3> bitcoin-cli sendtoaddress "bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl" 0.1 "" "" true
    4> curl --user myusername --data-binary '{"jsonrpc": "1.0", "id": "curltest", "method": "sendtoaddress", "params": ["bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl", 0.1, "donation", "seans outpost"]}' -H 'content-type: text/plain;' http://127.0.0.1:8332/
    5> bitcoin-cli sendtoaddress "bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl" 0.1 "" "" false true 0.00002 BTC/kB
    6> bitcoin-cli sendtoaddress "bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl" 0.1 "" "" false true 2 sat/B
    

    kallewoof commented at 7:01 am on June 24, 2020:
    Good catch, fixed
  350. jonatack commented at 9:52 am on June 21, 2020: member

    ACK 5ee0e46b93b2ca41eda9ee46fa59c6834689f0d5

    Kudos on your patience on this useful feature. Feel free to ignore the comments below. The RPC examples could be updated (as you’ve done for sendtoaddress) and the tests could use some cleanup and refactoring, but nothing that can’t be done in a follow-up. Happy to re-ACK if you retouch.

  351. fees: add FeeModes doc helper function 5d1a411eb1
  352. MOVEONLY: Make FeeEstimateMode available to CFeeRate
    Can verify move-only with:
    
        git log -p -n1 --color-moved
    
    This commit is move-only and doesn't change code or affect behavior.
    b188d80c2d
  353. rpc/wallet: add two explicit modes to estimate_mode 6fcf448430
  354. policy: optional FeeEstimateMode param to CFeeRate::ToString 3404c1b753
  355. tests for bumpfee / estimate_modes
    * invalid parameter tests for bumpfee
    * add tests for no conf_target explicit estimate_modes
    05227a3554
  356. doc: add release notes for explicit fee estimators and bumpfee change 25dac9fa65
  357. kallewoof force-pushed on Jun 24, 2020
  358. jonatack commented at 3:53 pm on June 24, 2020: member

    ACK 25dac9fa65243ca8db02df2 I think this should be merged after all this time, even though it looks to me like there are needed follow-ups, fixes and test coverage to be added (see further down), which I don’t mind helping out with, if wanted.


    Summary of the documentation of the changed RPCs:

    bumpfee

    • fee_rate option: “feerate (NOT total fee) to pay, in BTC per kB”

    fundrawtransaction

    • feeRate option: “Set a specific fee rate in BTC/kB”
    • fee rate set in conf_target (for BTC/kB or sat/B modes)

    sendmany

    • fee rate set in conf_target: “fee rate (for BTC/kB or sat/B estimate modes)”

    sendtoaddress

    • fee rate set in conf_target: “fee rate (for BTC/kB or sat/B estimate modes)”

    walletcreatefundedpsbt

    • feeRate option: “Set a specific fee rate in BTC/kB”

    Thoughts:

    • I find this pretty confusing and worth harmonizing.

    • walletcreatefundedpsbt does not work with feeRate + an explicit estimate mode. Not a surprise given the logic in FundTransaction, wallet/rpcwallet.cpp::3005. Here are added tests in rpc_psbt.py from line 154:

     0        # Existing test.
     1        # feeRate of 0.1 BTC / KB produces a total fee slightly below -maxtxfee (~0.05280000):
     2        res = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0, {"feeRate": 0.1})
     3        assert_greater_than(res["fee"], 0.05)
     4        assert_greater_than(0.06, res["fee"])
     5
     6        # Same test using conf_target and estimate_mode btc/kb is green.
     7        res = self.nodes[1].walletcreatefundedpsbt(
     8            [{"txid":txid,"vout":p2wpkh_pos}, {"txid":txid,"vout":p2sh_p2wpkh_pos}, {"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0,
     9            {
    10                "conf_target": 0.1,
    11                "estimate_mode": 'btc/kb',
    12            }
    13        )
    14        assert_greater_than(res["fee"], 0.05)
    15        assert_greater_than(0.06, res["fee"])
    16
    17        # Same test using conf_target and estimate_mode sat/b is green.
    18        res = self.nodes[1].walletcreatefundedpsbt(
    19            [{"txid":txid,"vout":p2wpkh_pos}, {"txid":txid,"vout":p2sh_p2wpkh_pos}, {"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0,
    20            {
    21                "conf_target": 10000,
    22                "estimate_mode": 'sat/b',
    23            }
    24        )
    25        assert_greater_than(res["fee"], 0.05)
    26        assert_greater_than(0.06, res["fee"])
    27
    28        # But the same test using feeRate and estimate_mode btc/kb or
    29        # sat/b fails with "Cannot specify both estimate_mode and feeRate".
    30        res = self.nodes[1].walletcreatefundedpsbt(
    31            [{"txid":txid,"vout":p2wpkh_pos}, {"txid":txid,"vout":p2sh_p2wpkh_pos}, {"txid":txid,"vout":p2pkh_pos}],
    32            [{"txid":txid,"vout":p2wpkh_pos}, {"txid":txid,"vout":p2sh_p2wpkh_pos}, {"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0,
    33            {
    34                "feeRate": 10000,
    35                "estimate_mode": 'sat/b',
    36            }
    37        )
    
    • We need tests for fundrawtransaction, walletcreatefundedpsbt and bumpfee.

    • We probably need to update the docs or code for fundrawtransaction and walletcreatefundedpsbt so that feeRate with an explicit estimation mode either works or is stated as not permitted.

  359. jonatack commented at 7:09 am on June 25, 2020: member
    If helpful, some notes I took while reviewing this PR: https://gist.github.com/jonatack/f16e51274d4254c01f682063b0f89e04
  360. kallewoof commented at 11:08 am on June 25, 2020: member
    Thanks for the detailed review @jonatack! It looks like bumpfee is suffering from the same issue as walletcreatefundedpsbt. I’m totally for merging this and doing a follow-up PR to address those, if this gets enough momentum to finally be merged after all this time. Otherwise I’ll look into fixing those two.
  361. in src/wallet/rpcwallet.cpp:3297 in 91f6d2bc8f outdated
    3293@@ -3294,15 +3294,24 @@ static UniValue bumpfee(const JSONRPCRequest& request)
    3294         RPCTypeCheckObj(options,
    3295             {
    3296                 {"confTarget", UniValueType(UniValue::VNUM)},
    3297+                {"conf_target", UniValueType(UniValue::VNUM)},
    


    fjahr commented at 2:06 pm on June 25, 2020:

    nit: Adding a comment here or below somewhere that this is acting as an alias to confTarget would be helpful as well. I have not seen this pattern before and I am pretty sure it would confuse me. maybe in the line above:

    0{"confTarget", UniValueType(UniValue::VNUM)}, // deprecated alias for conf_target
    
  362. in test/functional/wallet_bumpfee.py:153 in 05227a3554 outdated
    149@@ -127,9 +150,10 @@ def test_feerate_args(self, rbf_node, peer_node, dest_address):
    150     self.sync_mempools((rbf_node, peer_node))
    151     assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
    152 
    153-    assert_raises_rpc_error(-8, "confTarget can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL, "confTarget": 1})
    154+    assert_raises_rpc_error(-8, "conf_target can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL, "confTarget": 1})
    


    fjahr commented at 3:13 pm on June 25, 2020:

    same below.

    0    assert_raises_rpc_error(-8, "conf_target can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL, "conf_target": 1})
    
  363. fjahr approved
  364. fjahr commented at 3:39 pm on June 25, 2020: member

    Code review ACK 25dac9fa65243ca8db02df22f484039c08114401

    Just found two additional nits that can be ignored or kept for the follow-up.

  365. Sjors commented at 4:40 pm on June 25, 2020: member

    re-utACK 25dac9fa65: rebased, more fancy C++,

    Strong preference for merging this and improving the rest in followups. This has been blocking #16378 for a while and rebasing/tweaking a big change can be a lot of work, also on reviewers.

  366. jonatack commented at 4:47 pm on June 25, 2020: member

    Ouch, that image with the flashy white background hitting the eyes in dark mode :smile:

    Strong preference for merging this and improving the rest in followups. This has been blocking #16378 for a while and rebasing/tweaking a big change can be a lot of work, also on reviewers.

    :100:… @kallewoof has the patience of a sphinx. We’re still early enough in the release cycle to do the follow-ups.

  367. MarcoFalke commented at 5:55 pm on June 25, 2020: member

    Sorry to be so late with this review, but it seems that this overloads the conf_target which used to be an integer (number of blocks) to also accept floats or strings. Then, if a float or string is passed, its unit is taken from the estimate mode (which used to be an enum string).

    I believe, in the past all amounts (with a few exceptions) were passed as BTC and all feerates were passed as BTC/kB. If we start making feerates more type safe by forcing unit to be passed, then we should come up with a method that works for the whole code base and the whole RPC interface, not only for the few RPCs that happen to have two RPCArgs that can be recycled into passing a new type. For example, in the future one could imagine an RPC to set the feefilter of a peer or to set the mempool min fee or simply settxfee would be updated to allow passing a type-safe feerate. Then having multiple ways to pass a feerate would be confusing and added complexity at the call site.

    Also, passing the feerate (float) as an argument that used to be an integer is going to ask for mishaps, no?

    While this is obviously an improvement, and I don’t want to block it, I also think that we should aim to get the RPC interface right the very first time, since it is impossible to change after release and hard to change in future releases.

  368. laanwj merged this on Jun 25, 2020
  369. laanwj closed this on Jun 25, 2020

  370. MarcoFalke commented at 6:00 pm on June 25, 2020: member

    Oh, looks like this got merged before I left my comment.

    Anyway, I’d like to hear what the reviewers think of adding a new feerate argument that simply passed the feerate (with unit) in one string. Then, parsing code could be shared among all places in the RPC code that use the new feerate type.

  371. instagibbs commented at 6:13 pm on June 25, 2020: member

    I suggested that a long time ago but iirc people didn’t like that idea…

    On Thu, Jun 25, 2020, 2:00 PM MarcoFalke notifications@github.com wrote:

    Oh, looks like this got merged before I left my comment.

    Anyway, I’d like to hear what the reviewers think of adding a new feerate argument that simply passed the feerate (with unit) in one string. Then, parsing code could be shared among all places in the RPC code that use the new feerate type.

    — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/bitcoin/bitcoin/pull/11413#issuecomment-649733071, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABMAFU3BKIFRU27KYLBKMELRYOGDXANCNFSM4D43FZIA .

  372. laanwj commented at 6:18 pm on June 25, 2020: member

    Anyway, I’d like to hear what the reviewers think of adding a new feerate argument that simply passed the feerate (with unit) in one string. Then, parsing code could be shared among all places in the RPC code that use the new feerate type.

    I do agree that this would be better defined. Overloading an argument on type seems somewhat brittle, and could lead to serious accidents. Sorry for merging I thought there was agreement.

  373. MarcoFalke commented at 6:20 pm on June 25, 2020: member
    Yeah, no worries. I was about to merge this myself just now when I realized that this might not play out well long-term.
  374. jonatack commented at 8:16 pm on June 25, 2020: member
    I also prefer not overloading the argument. From reading the years of discussion I thought the discussion had been settled and that ship had sailed. In any case, there’s work to do before it is release-ready and I’m happy to help.
  375. MarcoFalke commented at 11:58 pm on June 25, 2020: member
    I am happy to review any follow-ups, so please ping me if I don’t show up on my own
  376. kallewoof deleted the branch on Jun 26, 2020
  377. kallewoof commented at 5:18 am on June 26, 2020: member
    @jonatack Are you up for doing a follow-up PR? I’ll gladly review it if so.
  378. jonatack commented at 7:20 am on June 26, 2020: member
    @kallewoof SGTM. Fixups + tests now, then propose a universal feerate arg unless you want to jump on that.
  379. kallewoof commented at 7:55 am on June 26, 2020: member
    Go for it! :) Let me know if it becomes overwhelming and I’ll see if I can pick up a part of it.
  380. sidhujag referenced this in commit 437a0f8e4c on Jul 7, 2020
  381. meshcollider moved this from the "PRs" to the "Done" column in a project

  382. meshcollider referenced this in commit ffaac6e614 on Sep 15, 2020
  383. sidhujag referenced this in commit 2d9d86f6b8 on Sep 15, 2020
  384. jonatack commented at 6:28 pm on October 22, 2020: member
    First follow-up is #20220.
  385. meshcollider referenced this in commit 5d32009f1a on Nov 4, 2020
  386. MarcoFalke referenced this in commit 80e32e120e on Nov 17, 2020
  387. luke-jr referenced this in commit b42abc5205 on Jan 28, 2021
  388. luke-jr referenced this in commit 150cf3a221 on Jan 28, 2021
  389. luke-jr referenced this in commit d495224d9d on Jan 28, 2021
  390. luke-jr referenced this in commit 486ab46c65 on Oct 10, 2021
  391. luke-jr referenced this in commit cbb22a4c92 on Oct 10, 2021
  392. luke-jr referenced this in commit 56553e0d43 on Oct 10, 2021
  393. DrahtBot locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-11-21 12:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me