diff --git a/src/core_io.h b/src/core_io.h index 80ec80cd5..037433032 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -6,6 +6,7 @@ #define BITCOIN_CORE_IO_H #include +#include #include #include @@ -40,6 +41,7 @@ int ParseSighashString(const UniValue& sighash); // core_write.cpp UniValue ValueFromAmount(const CAmount& amount); +UniValue ValueFromAmount(const arith_uint256& amount); std::string FormatScript(const CScript& script); std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0); std::string SighashToStr(unsigned char sighash_type); diff --git a/src/core_write.cpp b/src/core_write.cpp index 3980d8cb2..f5cb3b580 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -25,6 +26,16 @@ UniValue ValueFromAmount(const CAmount& amount) strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder)); } +// Dogecoin: Added to support very large total coin values, although this has a limitation that it doesn't support above 2^64 Doge. +UniValue ValueFromAmount(const arith_uint256& amount) +{ + // uint256 is unsigned, so we never worry about sign. + arith_uint256 quotient = amount / COIN; + arith_uint256 remainder = amount - (quotient * COIN); + return UniValue(UniValue::VNUM, + strprintf("%d.%08d", ArithToUint256(quotient).GetUint64(0), ArithToUint256(remainder).GetUint64(0))); +} + std::string FormatScript(const CScript& script) { std::string ret; diff --git a/src/node/coinstats.h b/src/node/coinstats.h index 2a7441c10..56a2ed1e1 100644 --- a/src/node/coinstats.h +++ b/src/node/coinstats.h @@ -7,6 +7,7 @@ #define BITCOIN_NODE_COINSTATS_H #include +#include #include #include @@ -28,7 +29,7 @@ struct CCoinsStats uint64_t nBogoSize{0}; uint256 hashSerialized{}; uint64_t nDiskSize{0}; - CAmount nTotalAmount{0}; + arith_uint256 nTotalAmount{0}; //! The number of coins contained. uint64_t coins_count{0}; diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index df9dfbea1..457ef5836 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -176,6 +176,21 @@ BOOST_AUTO_TEST_CASE(rpc_format_monetary_values) BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100000000).write(), "0.00000001"); } +// Dogecoin: Test the uint256 amount formatting +BOOST_AUTO_TEST_CASE(rpc_format_monetary_values_uint256) +{ + // Verify the simple zero case + const arith_uint256 zero = UintToArith256(uint256S("0x0000000000000000000000000000000000000000000000000000000000000000")); + BOOST_CHECK_EQUAL(ValueFromAmount(zero).write(), "0.00000000"); + // Verify a number greater than 2^64 to prove that works. This is (2 ^ 72) - 1 Koinu (as in, 1*10^-8) + const arith_uint256 largeQuantity = UintToArith256(uint256S("0x0000000000000000000000000000000000000000000000ffffffffffffffffff")); + BOOST_CHECK_EQUAL(ValueFromAmount(largeQuantity).write(), "47223664828696.45213695"); + + // Verify that if we calculate a negative number and store it in a uint type, we get a positive back. + const arith_uint256 negativeQuantity = zero - largeQuantity; + BOOST_CHECK_EQUAL(ValueFromAmount(negativeQuantity).write(), "6366458373880712194.84426241"); +} + static UniValue ValueFromString(const std::string &str) { UniValue value;