Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid overflow when calculating using int64_t #2935

Merged
merged 1 commit into from
Jun 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 51 additions & 1 deletion src/dfi/rpc_customtx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,55 @@
#include <rpc/request.h>
#include <univalue.h>

#include <boost/multiprecision/cpp_int.hpp>

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<int64_t>::max())) {
return std::numeric_limits<int64_t>::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<int64_t>::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;
Expand Down Expand Up @@ -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));
}
}

Expand Down
Loading