Change count type used by gettxoutsetinfo

changing CAmount (is a int64_t) to arith_uint256 for nTotalAmount in CCoinsStats to prevent overflow
This commit is contained in:
Ross Nicoll 2018-01-01 16:24:14 +00:00
parent 60cc97c7c4
commit 30142014b7
No known key found for this signature in database
GPG key ID: E679E30C312B94E0
4 changed files with 30 additions and 1 deletions

View file

@ -6,6 +6,7 @@
#define BITCOIN_CORE_IO_H
#include <amount.h>
#include <arith_uint256.h>
#include <attributes.h>
#include <string>
@ -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);

View file

@ -4,6 +4,7 @@
#include <core_io.h>
#include <arith_uint256.h>
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <key_io.h>
@ -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;

View file

@ -7,6 +7,7 @@
#define BITCOIN_NODE_COINSTATS_H
#include <amount.h>
#include <arith_uint256.h>
#include <uint256.h>
#include <cstdint>
@ -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};

View file

@ -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;