Browse Source

Merge pull request #6239

7d8ffac Changes necessary now that zero values accepted in AmountFromValue (Wladimir J. van der Laan)
a04bdef Get rid of fPlus argument to FormatMoney (Wladimir J. van der Laan)
4b4b9a8 Don't go through double in AmountFromValue and ValueFromAmount (Wladimir J. van der Laan)
0.13
Wladimir J. van der Laan 10 years ago
parent
commit
643114f539
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 21
      src/rpcserver.cpp
  2. 3
      src/test/rpc_tests.cpp
  3. 44
      src/test/util_tests.cpp
  4. 4
      src/utilmoneystr.cpp
  5. 2
      src/utilmoneystr.h
  6. 12
      src/wallet/rpcwallet.cpp

21
src/rpcserver.cpp

@ -11,6 +11,7 @@ @@ -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, @@ -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));
}
uint256 ParseHashV(const UniValue& v, string strName)

3
src/test/rpc_tests.cpp

@ -131,6 +131,9 @@ static UniValue ValueFromString(const std::string &str) @@ -131,6 +131,9 @@ static UniValue ValueFromString(const std::string &str)
BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
{
BOOST_CHECK_THROW(AmountFromValue(ValueFromString("-0.00000001")), UniValue);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0")), 0LL);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000000")), 0LL);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001")), 1LL);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.17622195")), 17622195LL);
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.5")), 50000000LL);

44
src/test/util_tests.cpp

@ -146,29 +146,27 @@ BOOST_AUTO_TEST_CASE(util_GetArg) @@ -146,29 +146,27 @@ BOOST_AUTO_TEST_CASE(util_GetArg)
BOOST_AUTO_TEST_CASE(util_FormatMoney)
{
BOOST_CHECK_EQUAL(FormatMoney(0, false), "0.00");
BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789, false), "12345.6789");
BOOST_CHECK_EQUAL(FormatMoney(COIN, true), "+1.00");
BOOST_CHECK_EQUAL(FormatMoney(-COIN, false), "-1.00");
BOOST_CHECK_EQUAL(FormatMoney(-COIN, true), "-1.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000, false), "100000000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000, false), "10000000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000, false), "1000000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*100000, false), "100000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*10000, false), "10000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*1000, false), "1000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*100, false), "100.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*10, false), "10.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN, false), "1.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN/10, false), "0.10");
BOOST_CHECK_EQUAL(FormatMoney(COIN/100, false), "0.01");
BOOST_CHECK_EQUAL(FormatMoney(COIN/1000, false), "0.001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000, false), "0.0001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000, false), "0.00001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000, false), "0.000001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000, false), "0.0000001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000, false), "0.00000001");
BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789), "12345.6789");
BOOST_CHECK_EQUAL(FormatMoney(-COIN), "-1.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000), "100000000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000), "10000000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000), "1000000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*100000), "100000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*10000), "10000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*1000), "1000.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*100), "100.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN*10), "10.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN), "1.00");
BOOST_CHECK_EQUAL(FormatMoney(COIN/10), "0.10");
BOOST_CHECK_EQUAL(FormatMoney(COIN/100), "0.01");
BOOST_CHECK_EQUAL(FormatMoney(COIN/1000), "0.001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000), "0.0001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000), "0.00001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001");
}
BOOST_AUTO_TEST_CASE(util_ParseMoney)

4
src/utilmoneystr.cpp

@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
using namespace std;
string FormatMoney(const CAmount& n, bool fPlus)
std::string FormatMoney(const CAmount& n)
{
// Note: not using straight sprintf here because we do NOT want
// localized number formatting.
@ -29,8 +29,6 @@ string FormatMoney(const CAmount& n, bool fPlus) @@ -29,8 +29,6 @@ string FormatMoney(const CAmount& n, bool fPlus)
if (n < 0)
str.insert((unsigned int)0, 1, '-');
else if (fPlus && n > 0)
str.insert((unsigned int)0, 1, '+');
return str;
}

2
src/utilmoneystr.h

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
#include "amount.h"
std::string FormatMoney(const CAmount& n, bool fPlus=false);
std::string FormatMoney(const CAmount& n);
bool ParseMoney(const std::string& str, CAmount& nRet);
bool ParseMoney(const char* pszIn, CAmount& nRet);

12
src/wallet/rpcwallet.cpp

@ -414,6 +414,8 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) @@ -414,6 +414,8 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)
// Amount
CAmount nAmount = AmountFromValue(params[1]);
if (nAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
// Wallet comments
CWalletTx wtx;
@ -809,6 +811,8 @@ UniValue movecmd(const UniValue& params, bool fHelp) @@ -809,6 +811,8 @@ UniValue movecmd(const UniValue& params, bool fHelp)
string strFrom = AccountFromValue(params[0]);
string strTo = AccountFromValue(params[1]);
CAmount nAmount = AmountFromValue(params[2]);
if (nAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
if (params.size() > 3)
// unused parameter, used to be nMinDepth, keep type-checking it though
(void)params[3].get_int();
@ -888,6 +892,8 @@ UniValue sendfrom(const UniValue& params, bool fHelp) @@ -888,6 +892,8 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
CAmount nAmount = AmountFromValue(params[2]);
if (nAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
int nMinDepth = 1;
if (params.size() > 3)
nMinDepth = params[3].get_int();
@ -987,6 +993,8 @@ UniValue sendmany(const UniValue& params, bool fHelp) @@ -987,6 +993,8 @@ UniValue sendmany(const UniValue& params, bool fHelp)
CScript scriptPubKey = GetScriptForDestination(address.Get());
CAmount nAmount = AmountFromValue(sendTo[name_]);
if (nAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
totalAmount += nAmount;
bool fSubtractFeeFromAmount = false;
@ -2168,9 +2176,7 @@ UniValue settxfee(const UniValue& params, bool fHelp) @@ -2168,9 +2176,7 @@ UniValue settxfee(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
// Amount
CAmount nAmount = 0;
if (params[0].get_real() != 0.0)
nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
CAmount nAmount = AmountFromValue(params[0]);
payTxFee = CFeeRate(nAmount, 1000);
return true;

Loading…
Cancel
Save