Merge bitcoin/bitcoin#21848: refactor: Make CFeeRate constructor architecture-independent

fafd121026 refactor: Make CFeeRate constructor architecture-independent (MarcoFalke)

Pull request description:

  Currently the constructor is architecture dependent. This is confusing for several reasons:

  * It is impossible to create a transaction larger than the max value of `uint32_t`, so a 64-bit `size_t` is not needed
  * Policy (and consensus) code should be arch-independent
  * The current code will print spurious compile errors when compiled on 32-bit systems:

  ```
  policy/feerate.cpp:23:22: warning: result of comparison of constant 9223372036854775807 with expression of type 'size_t' (aka 'unsigned int') is always true [-Wtautological-constant-out-of-range-compare]
      assert(nBytes_ <= uint64_t(std::numeric_limits<int64_t>::max()));
  ```

  Fix all issues by making it arch-independent. Also, fix `{}` style according to dev notes.

ACKs for top commit:
  theStack:
    re-ACK fafd121026
  promag:
    Code review ACK fafd121026.

Tree-SHA512: e16f75bad9ee8088b87e873906d9b5633449417a6996a226a2f37d33a2b7d4f2fd91df68998a77e52163de20b40c57fadabe7fe3502e599cbb98494178591833
This commit is contained in:
MarcoFalke 2021-05-24 11:11:55 +02:00
commit ce4a852475
No known key found for this signature in database
GPG Key ID: CE2B75697E69A548
4 changed files with 16 additions and 22 deletions

View File

@ -7,29 +7,26 @@
#include <tinyformat.h>
CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nBytes_)
CFeeRate::CFeeRate(const CAmount& nFeePaid, uint32_t num_bytes)
{
assert(nBytes_ <= uint64_t(std::numeric_limits<int64_t>::max()));
int64_t nSize = int64_t(nBytes_);
const int64_t nSize{num_bytes};
if (nSize > 0)
if (nSize > 0) {
nSatoshisPerK = nFeePaid * 1000 / nSize;
else
} else {
nSatoshisPerK = 0;
}
}
CAmount CFeeRate::GetFee(size_t nBytes_) const
CAmount CFeeRate::GetFee(uint32_t num_bytes) const
{
assert(nBytes_ <= uint64_t(std::numeric_limits<int64_t>::max()));
int64_t nSize = int64_t(nBytes_);
const int64_t nSize{num_bytes};
CAmount nFee = nSatoshisPerK * nSize / 1000;
if (nFee == 0 && nSize != 0) {
if (nSatoshisPerK > 0)
nFee = CAmount(1);
if (nSatoshisPerK < 0)
nFee = CAmount(-1);
if (nSatoshisPerK > 0) nFee = CAmount(1);
if (nSatoshisPerK < 0) nFee = CAmount(-1);
}
return nFee;

View File

@ -39,20 +39,17 @@ public:
// We've previously had bugs creep in from silent double->int conversion...
static_assert(std::is_integral<I>::value, "CFeeRate should be used without floats");
}
/** Constructor for a fee rate in satoshis per kvB (sat/kvB). The size in bytes must not exceed (2^63 - 1).
/** Constructor for a fee rate in satoshis per kvB (sat/kvB).
*
* Passing an nBytes value of COIN (1e8) returns a fee rate in satoshis per vB (sat/vB),
* Passing a num_bytes value of COIN (1e8) returns a fee rate in satoshis per vB (sat/vB),
* e.g. (nFeePaid * 1e8 / 1e3) == (nFeePaid / 1e5),
* where 1e5 is the ratio to convert from BTC/kvB to sat/vB.
*
* @param[in] nFeePaid CAmount fee rate to construct with
* @param[in] nBytes size_t bytes (units) to construct with
*/
CFeeRate(const CAmount& nFeePaid, size_t nBytes);
CFeeRate(const CAmount& nFeePaid, uint32_t num_bytes);
/**
* Return the fee in satoshis for the given size in bytes.
*/
CAmount GetFee(size_t nBytes) const;
CAmount GetFee(uint32_t num_bytes) const;
/**
* Return the fee in satoshis for a size of 1000 bytes
*/

View File

@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(GetFeeTest)
BOOST_CHECK(CFeeRate(CAmount(26), 789) == CFeeRate(32));
BOOST_CHECK(CFeeRate(CAmount(27), 789) == CFeeRate(34));
// Maximum size in bytes, should not crash
CFeeRate(MAX_MONEY, std::numeric_limits<size_t>::max() >> 1).GetFeePerK();
CFeeRate(MAX_MONEY, std::numeric_limits<uint32_t>::max()).GetFeePerK();
}
BOOST_AUTO_TEST_CASE(BinaryOperatorTest)

View File

@ -20,8 +20,8 @@ FUZZ_TARGET(fee_rate)
const CFeeRate fee_rate{satoshis_per_k};
(void)fee_rate.GetFeePerK();
const size_t bytes = fuzzed_data_provider.ConsumeIntegral<size_t>();
if (!MultiplicationOverflow(static_cast<int64_t>(bytes), satoshis_per_k) && bytes <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
const auto bytes = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
if (!MultiplicationOverflow(int64_t{bytes}, satoshis_per_k)) {
(void)fee_rate.GetFee(bytes);
}
(void)fee_rate.ToString();