From 7ed44592f70fdedb325d0979592df052cb42772f Mon Sep 17 00:00:00 2001 From: Bushstar Date: Mon, 10 Jun 2024 12:18:28 +0100 Subject: [PATCH] Avoid overflow when calculating using int64_t --- src/dfi/rpc_customtx.cpp | 52 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/dfi/rpc_customtx.cpp b/src/dfi/rpc_customtx.cpp index f46c049aa2..9ad4d6eb83 100644 --- a/src/dfi/rpc_customtx.cpp +++ b/src/dfi/rpc_customtx.cpp @@ -9,8 +9,55 @@ #include #include +#include + extern std::string ScriptToString(const CScript &script); +// Extract the lower 64 bits of arith_uint256 and convert to int64_t +static int64_t arith_uint256_to_int64(const arith_uint256 &value) { + auto lower64 = value.GetLow64(); + if (value > arith_uint256(std::numeric_limits::max())) { + return std::numeric_limits::max(); + } else { + return lower64; + } +} + +// Ceil arith_uint256 to int64_t +static auto ceil_arith_uint256_to_int64(const arith_uint256 &value) { + int64_t lower64 = arith_uint256_to_int64(value); + const auto truncated_value = arith_uint256(lower64); + if (truncated_value < value && lower64 != std::numeric_limits::max()) { + lower64 += 1; + } + return lower64; +} + +// Convert arith_uint256 to a string with high precision +auto GetHighPrecisionString(const arith_uint256 &value) { + struct HighPrecisionInterestValue { + typedef boost::multiprecision::uint256_t boost256; + + boost256 internalValue; + + explicit HighPrecisionInterestValue(const arith_uint256 &val) + : internalValue("0x" + val.GetHex()) {} + + auto GetFloatingPoint() const { return internalValue % COIN; } + + auto GetInteger() const { return internalValue / COIN; } + + std::string GetInterestPerBlockString() const { + std::ostringstream result; + const auto floatingPoint = GetFloatingPoint(); + const auto integer = GetInteger(); + result << integer << "." << std::setw(8) << std::setfill('0') << floatingPoint; + return result.str(); + } + }; + return HighPrecisionInterestValue(value).GetInterestPerBlockString(); +} + class CCustomTxRpcVisitor { uint32_t height; UniValue &rpcInfo; @@ -244,7 +291,10 @@ class CCustomTxRpcVisitor { auto price = PoolPrice::getMaxValid(); rpcInfo.pushKV("maxPrice", ValueFromAmount((price.integer * COIN) + price.fraction)); } else { - rpcInfo.pushKV("maxPrice", ValueFromAmount((obj.maxPrice.integer * COIN) + obj.maxPrice.fraction)); + const auto consensusCalc = arith_uint256(obj.maxPrice.integer) * COIN + obj.maxPrice.fraction; + const auto ceiledValue = ceil_arith_uint256_to_int64(consensusCalc); + rpcInfo.pushKV("maxPrice", ValueFromAmount(ceiledValue)); + rpcInfo.pushKV("maxPriceHighPrecision", GetHighPrecisionString(consensusCalc)); } }