mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-11 21:20:39 +02:00
Merge bitcoin/bitcoin#35303: policy: fix negative CFeeRate::ToString() formatting
4200f8163apolicy: fix negative CFeeRate::ToString() formatting (joaonevess) Pull request description: `CFeeRate` may represent modified/effective fee rates, for example after a negative `prioritisetransaction` fee delta. Previously, `CFeeRate::ToString()` formatted the quotient and remainder directly. For negative values, C++ `%` produces a negative remainder, which could result in malformed strings such as `0.-01 sat/vB`. This changes formatting to emit the sign once and format non-negative quotient/remainder parts. Positive fee rate formatting is unchanged. This is a display-only change and does not affect fee calculation or policy behavior. ACKs for top commit: polespinasa: ACK4200f8163awinterrdog: Re-ACK4200f8163asedited: ACK4200f8163aTree-SHA512: bf499078040154ac7828d0a58248b725156b7cfd763a8d6a2e48bcbd77f195a5e0ca9d3a973becdc7436e0bafb46a22cb49dd7ae947f98b434bed7d048d18397
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include <policy/feerate.h>
|
||||
#include <tinyformat.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
CFeeRate::CFeeRate(const CAmount& nFeePaid, int32_t virtual_bytes)
|
||||
{
|
||||
@@ -29,9 +30,16 @@ CAmount CFeeRate::GetFee(int32_t virtual_bytes) const
|
||||
std::string CFeeRate::ToString(FeeRateFormat fee_rate_format) const
|
||||
{
|
||||
const CAmount feerate_per_kvb{GetFeePerK()};
|
||||
const auto format_feerate = [](const CAmount fee_rate, const CAmount divisor, const int decimals, const std::string& currency_unit, const std::string& size_unit) {
|
||||
Assert(divisor > 0);
|
||||
const char* sign{fee_rate < 0 ? "-" : ""};
|
||||
const CAmount quotient{std::abs(fee_rate / divisor)};
|
||||
const CAmount remainder{std::abs(fee_rate % divisor)};
|
||||
return strprintf("%s%d.%0*d %s/%s", sign, quotient, decimals, remainder, currency_unit, size_unit);
|
||||
};
|
||||
switch (fee_rate_format) {
|
||||
case FeeRateFormat::BTC_KVB: return strprintf("%d.%08d %s/kvB", feerate_per_kvb / COIN, feerate_per_kvb % COIN, CURRENCY_UNIT);
|
||||
case FeeRateFormat::SAT_VB: return strprintf("%d.%03d %s/vB", feerate_per_kvb / 1000, feerate_per_kvb % 1000, CURRENCY_ATOM);
|
||||
case FeeRateFormat::BTC_KVB: return format_feerate(feerate_per_kvb, COIN, /*decimals=*/8, CURRENCY_UNIT, "kvB");
|
||||
case FeeRateFormat::SAT_VB: return format_feerate(feerate_per_kvb, 1000, /*decimals=*/3, CURRENCY_ATOM, "vB");
|
||||
} // no default case, so the compiler can warn about missing cases
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -144,6 +144,24 @@ BOOST_AUTO_TEST_CASE(ToStringTest)
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kvB");
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::BTC_KVB), "0.00000001 BTC/kvB");
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "0.001 sat/vB");
|
||||
|
||||
feeRate = CFeeRate(0);
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000000 BTC/kvB");
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::BTC_KVB), "0.00000000 BTC/kvB");
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "0.000 sat/vB");
|
||||
|
||||
feeRate = CFeeRate(-1);
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(), "-0.00000001 BTC/kvB");
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::BTC_KVB), "-0.00000001 BTC/kvB");
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "-0.001 sat/vB");
|
||||
|
||||
feeRate = CFeeRate(-1000);
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(), "-0.00001000 BTC/kvB");
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "-1.000 sat/vB");
|
||||
|
||||
feeRate = CFeeRate(-COIN - 1);
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(), "-1.00000001 BTC/kvB");
|
||||
BOOST_CHECK_EQUAL(feeRate.ToString(FeeRateFormat::SAT_VB), "-100000.001 sat/vB");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
Reference in New Issue
Block a user