Don't go through double in AmountFromValue and ValueFromAmount
My prime gripe with JSON spirit was that monetary values still had to be converted from and to floating point which can cause deviations (see #3759 and https://bitcoin.stackexchange.com/questions/22716/bitcoind-sendfrom-round-amount-error). As UniValue stores internal values as strings, this is no longer necessary. This avoids risky double-to-integer and integer-to-double conversions completely, and results in more elegant code to boot.
This commit is contained in:
parent
12cdbabc26
commit
4b4b9a8de6
1 changed files with 9 additions and 12 deletions
|
@ -11,6 +11,7 @@
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "utilmoneystr.h"
|
||||||
#include "utilstrencodings.h"
|
#include "utilstrencodings.h"
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
|
@ -118,25 +119,21 @@ void RPCTypeCheckObj(const UniValue& o,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int64_t roundint64(double d)
|
|
||||||
{
|
|
||||||
return (int64_t)(d > 0 ? d + 0.5 : d - 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
CAmount AmountFromValue(const UniValue& value)
|
CAmount AmountFromValue(const UniValue& value)
|
||||||
{
|
{
|
||||||
double dAmount = value.get_real();
|
if (!value.isReal() && !value.isNum())
|
||||||
if (dAmount <= 0.0 || dAmount > 21000000.0)
|
throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number");
|
||||||
|
CAmount amount;
|
||||||
|
if (!ParseMoney(value.getValStr(), amount))
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
|
||||||
CAmount nAmount = roundint64(dAmount * COIN);
|
if (!MoneyRange(amount))
|
||||||
if (!MoneyRange(nAmount))
|
throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
|
return amount;
|
||||||
return nAmount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue ValueFromAmount(const CAmount& amount)
|
UniValue ValueFromAmount(const CAmount& amount)
|
||||||
{
|
{
|
||||||
return (double)amount / (double)COIN;
|
return UniValue(UniValue::VREAL, FormatMoney(amount, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 ParseHashV(const UniValue& v, string strName)
|
uint256 ParseHashV(const UniValue& v, string strName)
|
||||||
|
|
Loading…
Reference in a new issue