diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 36d6a2d38..9fd158fe1 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -540,10 +540,10 @@ A few guidelines for introducing and reviewing new RPC interfaces: which is error prone, and it is easy to get things such as escaping wrong. JSON already supports nested data structures, no need to re-invent the wheel. - - *Exception*: AmountToValue can parse amounts as string. This was introduced because many JSON + - *Exception*: AmountFromValue can parse amounts as string. This was introduced because many JSON parsers and formatters hard-code handling decimal numbers as floating point values, resulting in potential loss of precision. This is unacceptable for - monetary values. **Always** use `AmountToValue` and `ValueToAmount` when + monetary values. **Always** use `AmountFromValue` and `ValueFromAmount` when inputting or outputting monetary values. The only exceptions to this are `prioritisetransaction` and `getblocktemplate` because their interface is specified as-is in BIP22. diff --git a/src/core_io.h b/src/core_io.h index f7f9c4958..8ce9a1f96 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_CORE_IO_H #define BITCOIN_CORE_IO_H +#include "amount.h" + #include #include @@ -27,6 +29,7 @@ uint256 ParseHashStr(const std::string&, const std::string& strName); std::vector ParseHexUV(const UniValue& v, const std::string& strName); // core_write.cpp +UniValue ValueFromAmount(const CAmount& amount); std::string FormatScript(const CScript& script); std::string EncodeHexTx(const CTransaction& tx); void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); diff --git a/src/core_write.cpp b/src/core_write.cpp index 87664f0ac..01ba12bda 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -22,6 +22,15 @@ #include "evo/specialtx.h" #include "llmq/quorums_commitment.h" +UniValue ValueFromAmount(const CAmount& amount) +{ + bool sign = amount < 0; + int64_t n_abs = (sign ? -amount : amount); + int64_t quotient = n_abs / COIN; + int64_t remainder = n_abs % COIN; + return UniValue(UniValue::VNUM, + strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder)); +} std::string FormatScript(const CScript& script) { @@ -199,8 +208,7 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, UniValue out(UniValue::VOBJ); - UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue)); - out.pushKV("value", outValue); + out.pushKV("value", ValueFromAmount(txout.nValue)); out.pushKV("valueSat", txout.nValue); out.pushKV("n", (int64_t)i); diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index b4e47fb5e..5bbdc2765 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -4,6 +4,7 @@ #include "masternode/activemasternode.h" #include "consensus/validation.h" +#include "core_io.h" #include "governance/governance.h" #include "governance/governance-vote.h" #include "governance/governance-classes.h" diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 29da7022c..8ac8cf695 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -7,6 +7,7 @@ #include "base58.h" #include "chain.h" #include "clientversion.h" +#include "core_io.h" #include "init.h" #include "httpserver.h" #include "net.h" diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index e9e72b27a..23566c859 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -7,6 +7,7 @@ #include "chainparams.h" #include "clientversion.h" +#include "core_io.h" #include "validation.h" #include "net.h" #include "net_processing.h" diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index b5261072b..40dba30dd 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -125,16 +125,6 @@ CAmount AmountFromValue(const UniValue& value) return amount; } -UniValue ValueFromAmount(const CAmount& amount) -{ - bool sign = amount < 0; - int64_t n_abs = (sign ? -amount : amount); - int64_t quotient = n_abs / COIN; - int64_t remainder = n_abs % COIN; - return UniValue(UniValue::VNUM, - strprintf("%s%d.%08d", sign ? "-" : "", quotient, remainder)); -} - uint256 ParseHashV(const UniValue& v, std::string strName) { std::string strHex; diff --git a/src/rpc/server.h b/src/rpc/server.h index f2f1dd2a9..b17a7c7d7 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -187,7 +187,6 @@ extern double ParseDoubleV(const UniValue& v, const std::string &strName); extern bool ParseBoolV(const UniValue& v, const std::string &strName); extern CAmount AmountFromValue(const UniValue& value); -extern UniValue ValueFromAmount(const CAmount& amount); extern std::string HelpExampleCli(const std::string& methodname, const std::string& args); extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index cb1020705..e582c71c2 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -6,6 +6,7 @@ #include "rpc/client.h" #include "base58.h" +#include "core_io.h" #include "netbase.h" #include "test/test_dash.h" diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h index 5839b0734..bc885ee16 100644 --- a/src/utilmoneystr.h +++ b/src/utilmoneystr.h @@ -14,6 +14,9 @@ #include "amount.h" +/* Do not use these functions to represent or parse monetary amounts to or from + * JSON but use AmountFromValue and ValueFromAmount for that. + */ std::string FormatMoney(const CAmount& n); bool ParseMoney(const std::string& str, CAmount& nRet); bool ParseMoney(const char* pszIn, CAmount& nRet); diff --git a/test/util/data/tt-delin1-out.json b/test/util/data/tt-delin1-out.json index db9bf301b..17ad71459 100644 --- a/test/util/data/tt-delin1-out.json +++ b/test/util/data/tt-delin1-out.json @@ -187,7 +187,7 @@ ], "vout": [ { - "value": 1.3782, + "value": 1.37820000, "valueSat": 137820000, "n": 0, "scriptPubKey": { diff --git a/test/util/data/tt-delout1-out.json b/test/util/data/tt-delout1-out.json index 6d0036e1a..d0e15e9f7 100644 --- a/test/util/data/tt-delout1-out.json +++ b/test/util/data/tt-delout1-out.json @@ -196,7 +196,7 @@ ], "vout": [ { - "value": 1.3782, + "value": 1.37820000, "valueSat": 137820000, "n": 0, "scriptPubKey": { diff --git a/test/util/data/tt-locktime317000-out.json b/test/util/data/tt-locktime317000-out.json index 9cb44ac98..c4510638d 100644 --- a/test/util/data/tt-locktime317000-out.json +++ b/test/util/data/tt-locktime317000-out.json @@ -196,7 +196,7 @@ ], "vout": [ { - "value": 1.3782, + "value": 1.37820000, "valueSat": 137820000, "n": 0, "scriptPubKey": { diff --git a/test/util/data/txcreate1.json b/test/util/data/txcreate1.json index 1eece2ef8..f0a027489 100644 --- a/test/util/data/txcreate1.json +++ b/test/util/data/txcreate1.json @@ -34,7 +34,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "valueSat": 18000000, "n": 0, "scriptPubKey": { @@ -48,7 +48,7 @@ } }, { - "value": 4.00, + "value": 4.00000000, "valueSat": 400000000, "n": 1, "scriptPubKey": { diff --git a/test/util/data/txcreate2.json b/test/util/data/txcreate2.json index ea4e12b57..de1ee952b 100644 --- a/test/util/data/txcreate2.json +++ b/test/util/data/txcreate2.json @@ -7,7 +7,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "valueSat": 0, "n": 0, "scriptPubKey": { diff --git a/test/util/data/txcreatedata1.json b/test/util/data/txcreatedata1.json index 7c37f8b18..e2fcf1575 100644 --- a/test/util/data/txcreatedata1.json +++ b/test/util/data/txcreatedata1.json @@ -16,7 +16,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "valueSat": 18000000, "n": 0, "scriptPubKey": { @@ -30,7 +30,7 @@ } }, { - "value": 4.00, + "value": 4.00000000, "valueSat": 400000000, "n": 1, "scriptPubKey": { diff --git a/test/util/data/txcreatedata2.json b/test/util/data/txcreatedata2.json index eba7e7d4c..ea70aee75 100644 --- a/test/util/data/txcreatedata2.json +++ b/test/util/data/txcreatedata2.json @@ -16,7 +16,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "valueSat": 18000000, "n": 0, "scriptPubKey": { @@ -30,7 +30,7 @@ } }, { - "value": 0.00, + "value": 0.00000000, "valueSat": 0, "n": 1, "scriptPubKey": { diff --git a/test/util/data/txcreatedata_seq0.json b/test/util/data/txcreatedata_seq0.json index e13a1d101..5820ed15e 100644 --- a/test/util/data/txcreatedata_seq0.json +++ b/test/util/data/txcreatedata_seq0.json @@ -16,7 +16,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "valueSat": 18000000, "n": 0, "scriptPubKey": { diff --git a/test/util/data/txcreatedata_seq1.json b/test/util/data/txcreatedata_seq1.json index a76c95232..a57c17af2 100644 --- a/test/util/data/txcreatedata_seq1.json +++ b/test/util/data/txcreatedata_seq1.json @@ -25,7 +25,7 @@ ], "vout": [ { - "value": 0.18, + "value": 0.18000000, "valueSat": 18000000, "n": 0, "scriptPubKey": { diff --git a/test/util/data/txcreatemultisig1.json b/test/util/data/txcreatemultisig1.json index a707abed0..4f4219ef6 100644 --- a/test/util/data/txcreatemultisig1.json +++ b/test/util/data/txcreatemultisig1.json @@ -7,7 +7,7 @@ ], "vout": [ { - "value": 1.00, + "value": 1.00000000, "valueSat": 100000000, "n": 0, "scriptPubKey": { diff --git a/test/util/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json index 79d477f62..e6e7fdd02 100644 --- a/test/util/data/txcreatemultisig2.json +++ b/test/util/data/txcreatemultisig2.json @@ -7,7 +7,7 @@ ], "vout": [ { - "value": 1.00, + "value": 1.00000000, "valueSat": 100000000, "n": 0, "scriptPubKey": { diff --git a/test/util/data/txcreateoutpubkey1.json b/test/util/data/txcreateoutpubkey1.json index e9f48ee99..f68105e9d 100644 --- a/test/util/data/txcreateoutpubkey1.json +++ b/test/util/data/txcreateoutpubkey1.json @@ -7,7 +7,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "valueSat": 0, "n": 0, "scriptPubKey": { diff --git a/test/util/data/txcreatescript1.json b/test/util/data/txcreatescript1.json index 0eadaf32d..cb923073f 100644 --- a/test/util/data/txcreatescript1.json +++ b/test/util/data/txcreatescript1.json @@ -7,7 +7,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "valueSat": 0, "n": 0, "scriptPubKey": { diff --git a/test/util/data/txcreatescript2.json b/test/util/data/txcreatescript2.json index 25ad9caad..942e90573 100644 --- a/test/util/data/txcreatescript2.json +++ b/test/util/data/txcreatescript2.json @@ -7,7 +7,7 @@ ], "vout": [ { - "value": 0.00, + "value": 0.00000000, "valueSat": 0, "n": 0, "scriptPubKey": { diff --git a/test/util/data/txcreatesignv1.json b/test/util/data/txcreatesignv1.json index b6a3d5894..4d5f85691 100644 --- a/test/util/data/txcreatesignv1.json +++ b/test/util/data/txcreatesignv1.json @@ -16,7 +16,7 @@ ], "vout": [ { - "value": 0.001, + "value": 0.00100000, "valueSat": 100000, "n": 0, "scriptPubKey": {