Skip to content

Commit

Permalink
RPC: Accept "EXPLICIT", "BTC/kB", and "sat/B" estimate_modes for comp…
Browse files Browse the repository at this point in the history
…atibility with Knots 0.16-0.20
  • Loading branch information
luke-jr committed Jan 27, 2021
1 parent 95ea54b commit a26e3a7
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 5 deletions.
30 changes: 29 additions & 1 deletion src/wallet/rpcwallet.cpp
Expand Up @@ -207,8 +207,36 @@ static std::string LabelFromValue(const UniValue& value)
* verify only that fee_rate is greater than 0
* @throws a JSONRPCError if conf_target, estimate_mode, or fee_rate contain invalid values or are in conflict
*/
static void SetFeeEstimateMode(const CWallet& wallet, CCoinControl& cc, const UniValue& conf_target, const UniValue& estimate_mode, const UniValue& fee_rate, bool override_min_fee)
static void SetFeeEstimateMode(const CWallet& wallet, CCoinControl& cc, UniValue conf_target, UniValue estimate_mode, UniValue fee_rate, bool override_min_fee)
{
if (estimate_mode.isStr()) {
const auto estimate_mode_str = ToUpper(estimate_mode.get_str());
if (estimate_mode_str == "EXPLICIT" ||
estimate_mode_str == ToUpper(CURRENCY_UNIT + "/kB") ||
estimate_mode_str == ToUpper(CURRENCY_ATOM + "/B")) {
if (!fee_rate.isNull()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and fee_rate. For explicit fees, please use fee_rate.");
}
if (conf_target.isNull()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Selected estimate_mode is deprecated and requires a fee rate in conf_target. Better to upgrade to fee_rate.");
}
if (estimate_mode_str.at(estimate_mode_str.size() - 2) == '/') {
// "sat/B": pretty straightforward
fee_rate = conf_target;
} else {
// "BTC/kB" or "EXPLICIT": Need to convert to sat/vB
CAmount fee_rate_amount = AmountFromValue(conf_target);
// NOTE: AmountFromValue never allows negative
// AmountFromValue gives us satoshis per kvB, so to get sat/vB we just divide out the kilo
const int64_t quotient = fee_rate_amount / 1000;
const int64_t remainder = fee_rate_amount % 1000;
fee_rate.setNumStr(strprintf("%d.%03d", quotient, remainder));
}
estimate_mode.setNull();
conf_target.setNull();
override_min_fee = false;
}
}
if (!fee_rate.isNull()) {
if (!conf_target.isNull()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
Expand Down
4 changes: 2 additions & 2 deletions test/functional/wallet_basic.py
Expand Up @@ -273,7 +273,7 @@ def run_test(self):
for target, mode in product([-1, 0, 1009], ["economical", "conservative"]):
assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h
self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode)
for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
for target, mode in product([-1, 0], ["btc/kvb", "sat/vb"]):
assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode)

Expand Down Expand Up @@ -456,7 +456,7 @@ def run_test(self):
for target, mode in product([-1, 0, 1009], ["economical", "conservative"]):
assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h
self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode)
for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
for target, mode in product([-1, 0], ["btc/kvb", "sat/vb"]):
assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode)

Expand Down
2 changes: 1 addition & 1 deletion test/functional/wallet_bumpfee.py
Expand Up @@ -135,7 +135,7 @@ def test_invalid_parameters(self, rbf_node, peer_node, dest_address):
for k, v in {"number": 42, "object": {"foo": "bar"}}.items():
assert_raises_rpc_error(-3, "Expected type string for estimate_mode, got {}".format(k),
rbf_node.bumpfee, rbfid, {"estimate_mode": v})
for mode in ["foo", Decimal("3.1415"), "sat/B", "BTC/kB"]:
for mode in ["foo", Decimal("3.1415"), "sat/vB", "BTC/kvB"]:
assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
rbf_node.bumpfee, rbfid, {"estimate_mode": mode})

Expand Down
2 changes: 1 addition & 1 deletion test/functional/wallet_send.py
Expand Up @@ -289,7 +289,7 @@ def run_test(self):
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=target, estimate_mode=mode,
expect_error=(-8, "Invalid conf_target, must be between 1 and 1008")) # max value of 1008 per src/policy/fees.h
msg = 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"'
for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
for target, mode in product([-1, 0], ["btc/kvb", "sat/vb"]):
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=target, estimate_mode=mode, expect_error=(-8, msg))
for mode in ["", "foo", Decimal("3.141592")]:
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode=mode, expect_error=(-8, msg))
Expand Down

0 comments on commit a26e3a7

Please sign in to comment.