wallet: update fee rate units, use sat/vB for fee_rate error messages

and BTC/kvB for feeRate error messages.
This commit is contained in:
Jon Atack 2020-11-08 19:57:35 +01:00
parent 7f9835a05a
commit 173b5b5fe0
No known key found for this signature in database
GPG key ID: 4F5721B3D0E3921D
9 changed files with 22 additions and 21 deletions

View file

@ -38,7 +38,7 @@ CAmount CFeeRate::GetFee(size_t nBytes_) const
std::string CFeeRate::ToString(const FeeEstimateMode& fee_estimate_mode) const std::string CFeeRate::ToString(const FeeEstimateMode& fee_estimate_mode) const
{ {
switch (fee_estimate_mode) { switch (fee_estimate_mode) {
case FeeEstimateMode::SAT_B: return strprintf("%d.%03d %s/B", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM); case FeeEstimateMode::SAT_VB: return strprintf("%d.%03d %s/vB", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM);
default: return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT); default: return strprintf("%d.%08d %s/kvB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT);
} }
} }

View file

@ -19,8 +19,8 @@ enum class FeeEstimateMode {
UNSET, //!< Use default settings based on other criteria UNSET, //!< Use default settings based on other criteria
ECONOMICAL, //!< Force estimateSmartFee to use non-conservative estimates ECONOMICAL, //!< Force estimateSmartFee to use non-conservative estimates
CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
BTC_KB, //!< Use explicit BTC/kB fee given in coin control BTC_KVB, //!< Use BTC/kvB fee rate unit
SAT_B, //!< Use explicit sat/B fee given in coin control SAT_VB, //!< Use sat/vB fee rate unit
}; };
/** /**
@ -65,7 +65,7 @@ public:
friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
friend bool operator!=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK != b.nSatoshisPerK; } friend bool operator!=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK != b.nSatoshisPerK; }
CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; } CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BTC_KB) const; std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BTC_KVB) const;
SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); } SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); }
}; };

View file

@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(BinaryOperatorTest)
BOOST_CHECK(a <= a); BOOST_CHECK(a <= a);
BOOST_CHECK(b >= a); BOOST_CHECK(b >= a);
BOOST_CHECK(b >= b); BOOST_CHECK(b >= b);
// a should be 0.00000002 BTC/kB now // a should be 0.00000002 BTC/kvB now
a += a; a += a;
BOOST_CHECK(a == b); BOOST_CHECK(a == b);
} }
@ -107,7 +107,9 @@ BOOST_AUTO_TEST_CASE(ToStringTest)
{ {
CFeeRate feeRate; CFeeRate feeRate;
feeRate = CFeeRate(1); feeRate = CFeeRate(1);
BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kB"); BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kvB");
BOOST_CHECK_EQUAL(feeRate.ToString(FeeEstimateMode::BTC_KVB), "0.00000001 BTC/kvB");
BOOST_CHECK_EQUAL(feeRate.ToString(FeeEstimateMode::SAT_VB), "0.001 sat/vB");
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View file

@ -3136,7 +3136,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
} }
CFeeRate fee_rate(AmountFromValue(options["feeRate"])); CFeeRate fee_rate(AmountFromValue(options["feeRate"]));
if (fee_rate <= CFeeRate(0)) { if (fee_rate <= CFeeRate(0)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid feeRate %s (must be greater than 0)", fee_rate.ToString())); throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid feeRate %s (must be greater than 0)", fee_rate.ToString(FeeEstimateMode::BTC_KVB)));
} }
coinControl.m_feerate = fee_rate; coinControl.m_feerate = fee_rate;
coinControl.fOverrideFeeRate = true; coinControl.fOverrideFeeRate = true;

View file

@ -2834,7 +2834,7 @@ bool CWallet::CreateTransactionInternal(
// Do not, ever, assume that it's fine to change the fee rate if the user has explicitly // Do not, ever, assume that it's fine to change the fee rate if the user has explicitly
// provided one // provided one
if (coin_control.m_feerate && nFeeRateNeeded > *coin_control.m_feerate) { if (coin_control.m_feerate && nFeeRateNeeded > *coin_control.m_feerate) {
error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(), nFeeRateNeeded.ToString()); error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), nFeeRateNeeded.ToString(FeeEstimateMode::SAT_VB));
return false; return false;
} }

View file

@ -752,9 +752,9 @@ class RawTransactionsTest(BitcoinTestFramework):
node.fundrawtransaction, rawtx, {"estimate_mode": mode, "conf_target": n, "add_inputs": True}) node.fundrawtransaction, rawtx, {"estimate_mode": mode, "conf_target": n, "add_inputs": True})
self.log.info("Test invalid fee rate settings") self.log.info("Test invalid fee rate settings")
assert_raises_rpc_error(-4, "Fee rate (0.00000000 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", assert_raises_rpc_error(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
node.fundrawtransaction, rawtx, {"fee_rate": 0, "add_inputs": True}) node.fundrawtransaction, rawtx, {"fee_rate": 0, "add_inputs": True})
assert_raises_rpc_error(-8, "Invalid feeRate 0.00000000 BTC/kB (must be greater than 0)", assert_raises_rpc_error(-8, "Invalid feeRate 0.00000000 BTC/kvB (must be greater than 0)",
node.fundrawtransaction, rawtx, {"feeRate": 0, "add_inputs": True}) node.fundrawtransaction, rawtx, {"feeRate": 0, "add_inputs": True})
for param, value in {("fee_rate", 100000), ("feeRate", 1.000)}: for param, value in {("fee_rate", 100000), ("feeRate", 1.000)}:
assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)",
@ -768,7 +768,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Test setting explicit fee rate just below the minimum. # Test setting explicit fee rate just below the minimum.
self.log.info("- raises RPC error 'fee rate too low' if fee_rate of 0.99999999 sat/vB is passed") self.log.info("- raises RPC error 'fee rate too low' if fee_rate of 0.99999999 sat/vB is passed")
msg = "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)" msg = "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"
assert_raises_rpc_error(-4, msg, node.fundrawtransaction, rawtx, {"fee_rate": 0.99999999, "add_inputs": True}) assert_raises_rpc_error(-4, msg, node.fundrawtransaction, rawtx, {"fee_rate": 0.99999999, "add_inputs": True})
# This feeRate test only passes if `coinControl.fOverrideFeeRate = true` in wallet/rpcwallet.cpp::FundTransaction is removed. # This feeRate test only passes if `coinControl.fOverrideFeeRate = true` in wallet/rpcwallet.cpp::FundTransaction is removed.
# assert_raises_rpc_error(-4, msg, node.fundrawtransaction, rawtx, {"feeRate": 0.00000999, "add_inputs": True}) # assert_raises_rpc_error(-4, msg, node.fundrawtransaction, rawtx, {"feeRate": 0.00000999, "add_inputs": True})

View file

@ -194,9 +194,9 @@ class PSBTTest(BitcoinTestFramework):
assert_approx(res2["fee"], 0.055, 0.005) assert_approx(res2["fee"], 0.055, 0.005)
self.log.info("Test invalid fee rate settings") self.log.info("Test invalid fee rate settings")
assert_raises_rpc_error(-4, "Fee rate (0.00000000 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", assert_raises_rpc_error(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0, "add_inputs": True}) self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0, "add_inputs": True})
assert_raises_rpc_error(-8, "Invalid feeRate 0.00000000 BTC/kB (must be greater than 0)", assert_raises_rpc_error(-8, "Invalid feeRate 0.00000000 BTC/kvB (must be greater than 0)",
self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"feeRate": 0, "add_inputs": True}) self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"feeRate": 0, "add_inputs": True})
for param, value in {("fee_rate", 100000), ("feeRate", 1)}: for param, value in {("fee_rate", 100000), ("feeRate", 1)}:
assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)",
@ -246,7 +246,7 @@ class PSBTTest(BitcoinTestFramework):
# Test setting explicit fee rate just below the minimum. # Test setting explicit fee rate just below the minimum.
self.log.info("- raises RPC error 'fee rate too low' if feerate_sat_vb of 0.99999999 is passed") self.log.info("- raises RPC error 'fee rate too low' if feerate_sat_vb of 0.99999999 is passed")
assert_raises_rpc_error(-4, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", assert_raises_rpc_error(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0.99999999, "add_inputs": True}) self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0.99999999, "add_inputs": True})
self.log.info("Test walletcreatefundedpsbt with too-high fee rate produces total fee well above -maxtxfee and raises RPC error") self.log.info("Test walletcreatefundedpsbt with too-high fee rate produces total fee well above -maxtxfee and raises RPC error")

View file

@ -250,11 +250,11 @@ class WalletTest(BitcoinTestFramework):
# Test setting explicit fee rate just below the minimum. # Test setting explicit fee rate just below the minimum.
self.log.info("Test sendmany raises 'fee rate too low' if fee_rate of 0.99999999 is passed") self.log.info("Test sendmany raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
assert_raises_rpc_error(-6, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0.99999999) self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0.99999999)
self.log.info("Test sendmany raises if fee_rate of 0 or -1 is passed") self.log.info("Test sendmany raises if fee_rate of 0 or -1 is passed")
assert_raises_rpc_error(-6, "Fee rate (0.00000000 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0) self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0)
assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=-1) assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=-1)
@ -421,11 +421,11 @@ class WalletTest(BitcoinTestFramework):
# Test setting explicit fee rate just below the minimum. # Test setting explicit fee rate just below the minimum.
self.log.info("Test sendtoaddress raises 'fee rate too low' if fee_rate of 0.99999999 is passed") self.log.info("Test sendtoaddress raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
assert_raises_rpc_error(-6, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=0.99999999) self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=0.99999999)
self.log.info("Test sendtoaddress raises if fee_rate of 0 or -1 is passed") self.log.info("Test sendtoaddress raises if fee_rate of 0 or -1 is passed")
assert_raises_rpc_error(-6, "Fee rate (0.00000000 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)", assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
self.nodes[2].sendtoaddress, address=address, amount=10, fee_rate=0) self.nodes[2].sendtoaddress, address=address, amount=10, fee_rate=0)
assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=-1) assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=-1)

View file

@ -306,11 +306,10 @@ class WalletSendTest(BitcoinTestFramework):
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=v, estimate_mode=mode, self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=v, estimate_mode=mode,
expect_error=(-3, "Expected type number for conf_target, got {}".format(k))) expect_error=(-3, "Expected type number for conf_target, got {}".format(k)))
# TODO: The error message should use sat/vB units instead of BTC/kB.
# Test setting explicit fee rate just below the minimum. # Test setting explicit fee rate just below the minimum.
self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if fee_rate of 0.99999999 is passed") self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if fee_rate of 0.99999999 is passed")
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0.99999999, self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0.99999999,
expect_error=(-4, "Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)")) expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"))
# TODO: Return hex if fee rate is below -maxmempool # TODO: Return hex if fee rate is below -maxmempool
# res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", add_to_wallet=False) # res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", add_to_wallet=False)