Merge #10999: Fix amounts formatting in decoderawtransaction
ce07638 doc: Add comment to use ValueFromAmount/AmountFromValue for JSON, not utilmoneystr (Wladimir J. van der Laan) ec05c50 rpc: Use ValueFromAmount instead of FormatMoney in TxToUniv (Wladimir J. van der Laan) 46347ad rpc: Move ValueFromAmount to core_write (Wladimir J. van der Laan) dac3782 doc: Correct AmountFromValue/ValueFromAmount names (Wladimir J. van der Laan) Pull request description: With this, the amounts returned in `decoderawtransaction` will be padded to 8 digits like anywhere else in the API. This is accomplished by using `ValueFromAmount` in `TxToUniv`, instead of `FormatMoney` which it currently (mistakingly) uses. The `FormatMoney` function is only for debugging/logging use! To avoid dependency issues, `ValueFromAmount` is moved to `core_write.cpp`, where it also fits better. I don't move `AmountFromValue` to `core_read.cpp` at the same time, as this would have more impact due to the RPCError dependency there. (n.b.: large number of changed files is solely due to the util_tests JSONs needing update) Tree-SHA512: 10fc2d27d33a77dbcb57aa7eccd4f53110c05d38eb7df6d40f10f14c08fad4274472e93af75aa59fe68ad0720fdf0930f0108124abef518e0dd162b3d2b2b292
This commit is contained in:
parent
dfd14bf573
commit
cd490905be
@ -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.
|
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.
|
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
|
parsers and formatters hard-code handling decimal numbers as floating point
|
||||||
values, resulting in potential loss of precision. This is unacceptable for
|
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
|
inputting or outputting monetary values. The only exceptions to this are
|
||||||
`prioritisetransaction` and `getblocktemplate` because their interface
|
`prioritisetransaction` and `getblocktemplate` because their interface
|
||||||
is specified as-is in BIP22.
|
is specified as-is in BIP22.
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#ifndef BITCOIN_CORE_IO_H
|
#ifndef BITCOIN_CORE_IO_H
|
||||||
#define BITCOIN_CORE_IO_H
|
#define BITCOIN_CORE_IO_H
|
||||||
|
|
||||||
|
#include "amount.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -27,6 +29,7 @@ uint256 ParseHashStr(const std::string&, const std::string& strName);
|
|||||||
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
|
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
|
||||||
|
|
||||||
// core_write.cpp
|
// core_write.cpp
|
||||||
|
UniValue ValueFromAmount(const CAmount& amount);
|
||||||
std::string FormatScript(const CScript& script);
|
std::string FormatScript(const CScript& script);
|
||||||
std::string EncodeHexTx(const CTransaction& tx);
|
std::string EncodeHexTx(const CTransaction& tx);
|
||||||
void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
|
void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
|
||||||
|
@ -22,6 +22,15 @@
|
|||||||
#include "evo/specialtx.h"
|
#include "evo/specialtx.h"
|
||||||
#include "llmq/quorums_commitment.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)
|
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 out(UniValue::VOBJ);
|
||||||
|
|
||||||
UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue));
|
out.pushKV("value", ValueFromAmount(txout.nValue));
|
||||||
out.pushKV("value", outValue);
|
|
||||||
out.pushKV("valueSat", txout.nValue);
|
out.pushKV("valueSat", txout.nValue);
|
||||||
out.pushKV("n", (int64_t)i);
|
out.pushKV("n", (int64_t)i);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "masternode/activemasternode.h"
|
#include "masternode/activemasternode.h"
|
||||||
#include "consensus/validation.h"
|
#include "consensus/validation.h"
|
||||||
|
#include "core_io.h"
|
||||||
#include "governance/governance.h"
|
#include "governance/governance.h"
|
||||||
#include "governance/governance-vote.h"
|
#include "governance/governance-vote.h"
|
||||||
#include "governance/governance-classes.h"
|
#include "governance/governance-classes.h"
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
#include "chain.h"
|
#include "chain.h"
|
||||||
#include "clientversion.h"
|
#include "clientversion.h"
|
||||||
|
#include "core_io.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "httpserver.h"
|
#include "httpserver.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
#include "clientversion.h"
|
#include "clientversion.h"
|
||||||
|
#include "core_io.h"
|
||||||
#include "validation.h"
|
#include "validation.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "net_processing.h"
|
#include "net_processing.h"
|
||||||
|
@ -125,16 +125,6 @@ CAmount AmountFromValue(const UniValue& value)
|
|||||||
return amount;
|
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)
|
uint256 ParseHashV(const UniValue& v, std::string strName)
|
||||||
{
|
{
|
||||||
std::string strHex;
|
std::string strHex;
|
||||||
|
@ -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 bool ParseBoolV(const UniValue& v, const std::string &strName);
|
||||||
|
|
||||||
extern CAmount AmountFromValue(const UniValue& value);
|
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 HelpExampleCli(const std::string& methodname, const std::string& args);
|
||||||
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
|
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "rpc/client.h"
|
#include "rpc/client.h"
|
||||||
|
|
||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
|
#include "core_io.h"
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
|
|
||||||
#include "test/test_dash.h"
|
#include "test/test_dash.h"
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
|
|
||||||
#include "amount.h"
|
#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);
|
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);
|
||||||
|
@ -187,7 +187,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 1.3782,
|
"value": 1.37820000,
|
||||||
"valueSat": 137820000,
|
"valueSat": 137820000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -196,7 +196,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 1.3782,
|
"value": 1.37820000,
|
||||||
"valueSat": 137820000,
|
"valueSat": 137820000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -196,7 +196,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 1.3782,
|
"value": 1.37820000,
|
||||||
"valueSat": 137820000,
|
"valueSat": 137820000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.18,
|
"value": 0.18000000,
|
||||||
"valueSat": 18000000,
|
"valueSat": 18000000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
@ -48,7 +48,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"value": 4.00,
|
"value": 4.00000000,
|
||||||
"valueSat": 400000000,
|
"valueSat": 400000000,
|
||||||
"n": 1,
|
"n": 1,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.00,
|
"value": 0.00000000,
|
||||||
"valueSat": 0,
|
"valueSat": 0,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.18,
|
"value": 0.18000000,
|
||||||
"valueSat": 18000000,
|
"valueSat": 18000000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
@ -30,7 +30,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"value": 4.00,
|
"value": 4.00000000,
|
||||||
"valueSat": 400000000,
|
"valueSat": 400000000,
|
||||||
"n": 1,
|
"n": 1,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.18,
|
"value": 0.18000000,
|
||||||
"valueSat": 18000000,
|
"valueSat": 18000000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
@ -30,7 +30,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"value": 0.00,
|
"value": 0.00000000,
|
||||||
"valueSat": 0,
|
"valueSat": 0,
|
||||||
"n": 1,
|
"n": 1,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.18,
|
"value": 0.18000000,
|
||||||
"valueSat": 18000000,
|
"valueSat": 18000000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.18,
|
"value": 0.18000000,
|
||||||
"valueSat": 18000000,
|
"valueSat": 18000000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 1.00,
|
"value": 1.00000000,
|
||||||
"valueSat": 100000000,
|
"valueSat": 100000000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 1.00,
|
"value": 1.00000000,
|
||||||
"valueSat": 100000000,
|
"valueSat": 100000000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.00,
|
"value": 0.00000000,
|
||||||
"valueSat": 0,
|
"valueSat": 0,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.00,
|
"value": 0.00000000,
|
||||||
"valueSat": 0,
|
"valueSat": 0,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.00,
|
"value": 0.00000000,
|
||||||
"valueSat": 0,
|
"valueSat": 0,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
],
|
],
|
||||||
"vout": [
|
"vout": [
|
||||||
{
|
{
|
||||||
"value": 0.001,
|
"value": 0.00100000,
|
||||||
"valueSat": 100000,
|
"valueSat": 100000,
|
||||||
"n": 0,
|
"n": 0,
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
|
Loading…
Reference in New Issue
Block a user