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)
This commit is contained in:
commit
643114f539
6 changed files with 44 additions and 42 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 ParseHashV(const UniValue& v, string strName)
|
uint256 ParseHashV(const UniValue& v, string strName)
|
||||||
|
|
|
@ -131,6 +131,9 @@ static UniValue ValueFromString(const std::string &str)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
|
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.00000001")), 1LL);
|
||||||
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.17622195")), 17622195LL);
|
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.17622195")), 17622195LL);
|
||||||
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.5")), 50000000LL);
|
BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.5")), 50000000LL);
|
||||||
|
|
|
@ -146,29 +146,27 @@ BOOST_AUTO_TEST_CASE(util_GetArg)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(util_FormatMoney)
|
BOOST_AUTO_TEST_CASE(util_FormatMoney)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(0, false), "0.00");
|
BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789, false), "12345.6789");
|
BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789), "12345.6789");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN, true), "+1.00");
|
BOOST_CHECK_EQUAL(FormatMoney(-COIN), "-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*100000000), "100000000.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000, false), "10000000.00");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000), "10000000.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000, false), "1000000.00");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000), "1000000.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN*100000, false), "100000.00");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN*100000), "100000.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN*10000, false), "10000.00");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN*10000), "10000.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN*1000, false), "1000.00");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN*1000), "1000.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN*100, false), "100.00");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN*100), "100.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN*10, false), "10.00");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN*10), "10.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN, false), "1.00");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN), "1.00");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN/10, false), "0.10");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN/10), "0.10");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN/100, false), "0.01");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN/100), "0.01");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN/1000, false), "0.001");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN/1000), "0.001");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000, false), "0.0001");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000), "0.0001");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000, false), "0.00001");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000), "0.00001");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000, false), "0.000001");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000, false), "0.0000001");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001");
|
||||||
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000, false), "0.00000001");
|
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(util_ParseMoney)
|
BOOST_AUTO_TEST_CASE(util_ParseMoney)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
using namespace std;
|
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
|
// Note: not using straight sprintf here because we do NOT want
|
||||||
// localized number formatting.
|
// localized number formatting.
|
||||||
|
@ -29,8 +29,6 @@ string FormatMoney(const CAmount& n, bool fPlus)
|
||||||
|
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
str.insert((unsigned int)0, 1, '-');
|
str.insert((unsigned int)0, 1, '-');
|
||||||
else if (fPlus && n > 0)
|
|
||||||
str.insert((unsigned int)0, 1, '+');
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include "amount.h"
|
#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 std::string& str, CAmount& nRet);
|
||||||
bool ParseMoney(const char* pszIn, CAmount& nRet);
|
bool ParseMoney(const char* pszIn, CAmount& nRet);
|
||||||
|
|
||||||
|
|
|
@ -414,6 +414,8 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)
|
||||||
|
|
||||||
// Amount
|
// Amount
|
||||||
CAmount nAmount = AmountFromValue(params[1]);
|
CAmount nAmount = AmountFromValue(params[1]);
|
||||||
|
if (nAmount <= 0)
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||||
|
|
||||||
// Wallet comments
|
// Wallet comments
|
||||||
CWalletTx wtx;
|
CWalletTx wtx;
|
||||||
|
@ -809,6 +811,8 @@ UniValue movecmd(const UniValue& params, bool fHelp)
|
||||||
string strFrom = AccountFromValue(params[0]);
|
string strFrom = AccountFromValue(params[0]);
|
||||||
string strTo = AccountFromValue(params[1]);
|
string strTo = AccountFromValue(params[1]);
|
||||||
CAmount nAmount = AmountFromValue(params[2]);
|
CAmount nAmount = AmountFromValue(params[2]);
|
||||||
|
if (nAmount <= 0)
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||||
if (params.size() > 3)
|
if (params.size() > 3)
|
||||||
// unused parameter, used to be nMinDepth, keep type-checking it though
|
// unused parameter, used to be nMinDepth, keep type-checking it though
|
||||||
(void)params[3].get_int();
|
(void)params[3].get_int();
|
||||||
|
@ -888,6 +892,8 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
|
||||||
if (!address.IsValid())
|
if (!address.IsValid())
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||||
CAmount nAmount = AmountFromValue(params[2]);
|
CAmount nAmount = AmountFromValue(params[2]);
|
||||||
|
if (nAmount <= 0)
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||||
int nMinDepth = 1;
|
int nMinDepth = 1;
|
||||||
if (params.size() > 3)
|
if (params.size() > 3)
|
||||||
nMinDepth = params[3].get_int();
|
nMinDepth = params[3].get_int();
|
||||||
|
@ -987,6 +993,8 @@ UniValue sendmany(const UniValue& params, bool fHelp)
|
||||||
|
|
||||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||||
CAmount nAmount = AmountFromValue(sendTo[name_]);
|
CAmount nAmount = AmountFromValue(sendTo[name_]);
|
||||||
|
if (nAmount <= 0)
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||||
totalAmount += nAmount;
|
totalAmount += nAmount;
|
||||||
|
|
||||||
bool fSubtractFeeFromAmount = false;
|
bool fSubtractFeeFromAmount = false;
|
||||||
|
@ -2168,9 +2176,7 @@ UniValue settxfee(const UniValue& params, bool fHelp)
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
|
|
||||||
// Amount
|
// Amount
|
||||||
CAmount nAmount = 0;
|
CAmount nAmount = AmountFromValue(params[0]);
|
||||||
if (params[0].get_real() != 0.0)
|
|
||||||
nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
|
|
||||||
|
|
||||||
payTxFee = CFeeRate(nAmount, 1000);
|
payTxFee = CFeeRate(nAmount, 1000);
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue