Skip to content

Commit 8885b72

Browse files
committed
wallet: create FeeRateFromValueInSatB() util function
similar to AmountFromValue() with an additional check for non-representable CFeeRates in the exclusive range of 0 to 0.001 sat/vB as CFeeRate rounds these values down to CFeeRate(0)
1 parent 83fb610 commit 8885b72

File tree

4 files changed

+34
-3
lines changed

4 files changed

+34
-3
lines changed

src/rpc/util.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <key_io.h>
66
#include <outputtype.h>
7+
#include <policy/feerate.h>
78
#include <rpc/util.h>
89
#include <script/descriptor.h>
910
#include <script/signingprovider.h>
@@ -86,6 +87,17 @@ CAmount AmountFromValue(const UniValue& value)
8687
return amount;
8788
}
8889

90+
CFeeRate FeeRateFromValueInSatB(const UniValue& value)
91+
{
92+
const CAmount amount{AmountFromValue(value)};
93+
const CFeeRate fee_rate{CFeeRate::FromSatB(amount)};
94+
if (fee_rate.IsZero() && amount != 0) {
95+
// passed value is an unrepresentable fee rate between 0 and 0.001 sat/vB
96+
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
97+
}
98+
return fee_rate;
99+
}
100+
89101
uint256 ParseHashV(const UniValue& v, std::string strName)
90102
{
91103
std::string strHex(v.get_str());

src/rpc/util.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <node/coinstats.h>
99
#include <node/transaction.h>
1010
#include <outputtype.h>
11+
#include <policy/feerate.h>
1112
#include <protocol.h>
1213
#include <pubkey.h>
1314
#include <rpc/protocol.h>
@@ -81,6 +82,10 @@ extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKe
8182
CoinStatsHashType ParseHashType(const UniValue& param, const CoinStatsHashType default_type);
8283

8384
extern CAmount AmountFromValue(const UniValue& value);
85+
86+
/** Return a fee rate from a UniValue number or string in sat/vB */
87+
extern CFeeRate FeeRateFromValueInSatB(const UniValue& value);
88+
8489
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
8590
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
8691

src/test/rpc_tests.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
#include <rpc/server.h>
77
#include <rpc/util.h>
88

9+
#include <amount.h>
910
#include <core_io.h>
1011
#include <interfaces/chain.h>
1112
#include <node/context.h>
13+
#include <policy/feerate.h>
1214
#include <test/util/setup_common.h>
1315
#include <util/ref.h>
1416
#include <util/time.h>
@@ -185,6 +187,7 @@ static UniValue ValueFromString(const std::string &str)
185187

186188
BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
187189
{
190+
// Test AmountFromValue
188191
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("-0.00000001")), UniValue);
189192
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0")), 0LL);
190193
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000000")), 0LL);
@@ -206,6 +209,8 @@ BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
206209

207210
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e-9")), UniValue); //should fail
208211
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("0.000000019")), UniValue); //should fail
212+
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("0.000999999")), UniValue);
213+
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1.111111111")), UniValue);
209214
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001000000")), 1LL); //should pass, cut trailing 0
210215
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("19e-9")), UniValue); //should fail
211216
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.19e-6")), 19); //should pass, leading 0 is present
@@ -214,6 +219,15 @@ BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
214219
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e+11")), UniValue); //overflow error
215220
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e11")), UniValue); //overflow error signless
216221
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("93e+9")), UniValue); //overflow error
222+
223+
// Test FeeRateFromValueInSatB
224+
BOOST_CHECK(FeeRateFromValueInSatB(ValueFromString("0")) == CFeeRate{0});
225+
BOOST_CHECK(FeeRateFromValueInSatB(ValueFromString("0.00000000")) == CFeeRate{0});
226+
BOOST_CHECK(FeeRateFromValueInSatB(ValueFromString("0.001")) == CFeeRate{1});
227+
BOOST_CHECK(FeeRateFromValueInSatB(ValueFromString("0.00100000")) == CFeeRate{1});
228+
BOOST_CHECK(FeeRateFromValueInSatB(ValueFromString("1")) == CFeeRate{1000});
229+
BOOST_CHECK(FeeRateFromValueInSatB(ValueFromString("1.000")) == CFeeRate{1000});
230+
BOOST_CHECK(FeeRateFromValueInSatB(ValueFromString("1.2340000")) == CFeeRate{1234});
217231
}
218232

219233
BOOST_AUTO_TEST_CASE(json_parse_errors)

src/wallet/rpcwallet.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ static void SetFeeEstimateMode(const CWallet& wallet, CCoinControl& cc, const Un
216216
if (!estimate_mode.isNull() && estimate_mode.get_str() != "unset") {
217217
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and fee_rate");
218218
}
219-
cc.m_feerate = CFeeRate::FromSatB(AmountFromValue(fee_rate));
219+
cc.m_feerate = FeeRateFromValueInSatB(fee_rate);
220220
if (override_min_fee) cc.fOverrideFeeRate = true;
221221
// Default RBF to true for explicit fee_rate, if unset.
222222
if (cc.m_signal_bip125_rbf == nullopt) cc.m_signal_bip125_rbf = true;
@@ -3089,7 +3089,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
30893089
{"lockUnspents", UniValueType(UniValue::VBOOL)},
30903090
{"lock_unspents", UniValueType(UniValue::VBOOL)},
30913091
{"locktime", UniValueType(UniValue::VNUM)},
3092-
{"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode()
3092+
{"fee_rate", UniValueType()}, // will be checked by FeeRateFromValueInSatB() in SetFeeEstimateMode()
30933093
{"feeRate", UniValueType()}, // will be checked by AmountFromValue() below
30943094
{"psbt", UniValueType(UniValue::VBOOL)},
30953095
{"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
@@ -3470,7 +3470,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
34703470
{
34713471
{"confTarget", UniValueType(UniValue::VNUM)},
34723472
{"conf_target", UniValueType(UniValue::VNUM)},
3473-
{"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode()
3473+
{"fee_rate", UniValueType()}, // will be checked by FeeRateFromValueInSatB() in SetFeeEstimateMode()
34743474
{"replaceable", UniValueType(UniValue::VBOOL)},
34753475
{"estimate_mode", UniValueType(UniValue::VSTR)},
34763476
},

0 commit comments

Comments
 (0)