aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2015-06-04 14:22:26 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2015-06-06 09:30:41 +0200
commit4b4b9a8de662e6327f78aaf04a1e83d45713c06a (patch)
treec706e3110388a099d914f7f27dace69f4eb76194
parent12cdbabc26a58fe19b97a2e45a3d31ddc455bbc8 (diff)
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.
-rw-r--r--src/rpcserver.cpp21
1 files changed, 9 insertions, 12 deletions
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index e6bf008618..11312ff63e 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -11,6 +11,7 @@
#include "sync.h"
#include "ui_interface.h"
#include "util.h"
+#include "utilmoneystr.h"
#include "utilstrencodings.h"
#ifdef ENABLE_WALLET
#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)
{
- double dAmount = value.get_real();
- if (dAmount <= 0.0 || dAmount > 21000000.0)
- throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
- CAmount nAmount = roundint64(dAmount * COIN);
- if (!MoneyRange(nAmount))
+ if (!value.isReal() && !value.isNum())
+ throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number");
+ CAmount amount;
+ if (!ParseMoney(value.getValStr(), amount))
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
- return nAmount;
+ if (!MoneyRange(amount))
+ throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
+ return 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)