From 43d16e0de7f9ac97583fa02cfd0b24dd31564a98 Mon Sep 17 00:00:00 2001 From: barton26 Date: Wed, 15 Sep 2021 21:41:50 -0400 Subject: [PATCH 1/3] build: Update univalue subtree --- src/univalue/Makefile.am | 2 + src/univalue/README.md | 21 ++------ src/univalue/gen/gen.cpp | 2 - src/univalue/include/univalue.h | 75 ++--------------------------- src/univalue/lib/univalue.cpp | 16 +++--- src/univalue/lib/univalue_read.cpp | 21 +++++--- src/univalue/lib/univalue_write.cpp | 18 +++---- src/univalue/test/fail45.json | 1 + src/univalue/test/object.cpp | 14 +++++- src/univalue/test/pass4.json | 1 + src/univalue/test/unitester.cpp | 17 ++++--- 11 files changed, 66 insertions(+), 122 deletions(-) create mode 100644 src/univalue/test/fail45.json create mode 100644 src/univalue/test/pass4.json diff --git a/src/univalue/Makefile.am b/src/univalue/Makefile.am index e283fc890e..0f5ba59954 100644 --- a/src/univalue/Makefile.am +++ b/src/univalue/Makefile.am @@ -95,6 +95,7 @@ TEST_FILES = \ $(TEST_DATA_DIR)/fail41.json \ $(TEST_DATA_DIR)/fail42.json \ $(TEST_DATA_DIR)/fail44.json \ + $(TEST_DATA_DIR)/fail45.json \ $(TEST_DATA_DIR)/fail3.json \ $(TEST_DATA_DIR)/fail4.json \ $(TEST_DATA_DIR)/fail5.json \ @@ -105,6 +106,7 @@ TEST_FILES = \ $(TEST_DATA_DIR)/pass1.json \ $(TEST_DATA_DIR)/pass2.json \ $(TEST_DATA_DIR)/pass3.json \ + $(TEST_DATA_DIR)/pass4.json \ $(TEST_DATA_DIR)/round1.json \ $(TEST_DATA_DIR)/round2.json \ $(TEST_DATA_DIR)/round3.json \ diff --git a/src/univalue/README.md b/src/univalue/README.md index 36aa786a4c..7c62c33970 100644 --- a/src/univalue/README.md +++ b/src/univalue/README.md @@ -12,21 +12,10 @@ an arbitrary depth. This class is aligned with the JSON standard, [RFC 7159](https://tools.ietf.org/html/rfc7159.html). -## Installation +## Library usage -This project is a standard GNU -[autotools](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html) -project. Build and install instructions are available in the `INSTALL` -file provided with GNU autotools. - -``` -$ ./autogen.sh -$ ./configure -$ make -``` - -## Design - -UniValue provides a single dynamic RAII C++ object class, -and minimizes template use (contra json_spirit). +This is a fork of univalue used by Bitcoin Core. It is not maintained for usage +by other projects. Notably, the API may break in non-backward-compatible ways. +Other projects looking for a maintained library should use the upstream +univalue at https://github.com/jgarzik/univalue. diff --git a/src/univalue/gen/gen.cpp b/src/univalue/gen/gen.cpp index 7af06a292a..be3d4ccf72 100644 --- a/src/univalue/gen/gen.cpp +++ b/src/univalue/gen/gen.cpp @@ -12,8 +12,6 @@ #include #include "univalue.h" -using namespace std; - static bool initEscapes; static std::string escapes[256]; diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h index 10ce39aec8..b85fe0766d 100644 --- a/src/univalue/include/univalue.h +++ b/src/univalue/include/univalue.h @@ -15,7 +15,6 @@ #include #include // .get_int64() -#include // std::pair class UniValue { public: @@ -48,7 +47,6 @@ class UniValue { std::string s(val_); setStr(s); } - ~UniValue() {} void clear(); @@ -102,6 +100,10 @@ class UniValue { UniValue tmpVal(val_); return push_back(tmpVal); } + bool push_back(bool val_) { + UniValue tmpVal(val_); + return push_back(tmpVal); + } bool push_back(int val_) { UniValue tmpVal(val_); return push_back(tmpVal); @@ -131,7 +133,7 @@ class UniValue { return pushKV(key, tmpVal); } bool pushKV(const std::string& key, bool val_) { - UniValue tmpVal((bool)val_); + UniValue tmpVal(val_); return pushKV(key, tmpVal); } bool pushKV(const std::string& key, int val_) { @@ -177,76 +179,9 @@ class UniValue { const UniValue& get_array() const; enum VType type() const { return getType(); } - bool push_back(std::pair pear) { - return pushKV(pear.first, pear.second); - } friend const UniValue& find_value( const UniValue& obj, const std::string& name); }; -// -// The following were added for compatibility with json_spirit. -// Most duplicate other methods, and should be removed. -// -static inline std::pair Pair(const char *cKey, const char *cVal) -{ - std::string key(cKey); - UniValue uVal(cVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, std::string strVal) -{ - std::string key(cKey); - UniValue uVal(strVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, uint64_t u64Val) -{ - std::string key(cKey); - UniValue uVal(u64Val); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, int64_t i64Val) -{ - std::string key(cKey); - UniValue uVal(i64Val); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, bool iVal) -{ - std::string key(cKey); - UniValue uVal(iVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, int iVal) -{ - std::string key(cKey); - UniValue uVal(iVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, double dVal) -{ - std::string key(cKey); - UniValue uVal(dVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, const UniValue& uVal) -{ - std::string key(cKey); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(std::string key, const UniValue& uVal) -{ - return std::make_pair(key, uVal); -} - enum jtokentype { JTOK_ERR = -1, JTOK_NONE = 0, // eof diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp index 6349ed0505..2b966ad859 100644 --- a/src/univalue/lib/univalue.cpp +++ b/src/univalue/lib/univalue.cpp @@ -10,8 +10,6 @@ #include "univalue.h" -using namespace std; - const UniValue NullUniValue; void UniValue::clear() @@ -37,15 +35,15 @@ bool UniValue::setBool(bool val_) return true; } -static bool validNumStr(const string& s) +static bool validNumStr(const std::string& s) { - string tokenVal; + std::string tokenVal; unsigned int consumed; enum jtokentype tt = getJsonToken(tokenVal, consumed, s.data(), s.data() + s.size()); return (tt == JTOK_NUMBER); } -bool UniValue::setNumStr(const string& val_) +bool UniValue::setNumStr(const std::string& val_) { if (!validNumStr(val_)) return false; @@ -58,7 +56,7 @@ bool UniValue::setNumStr(const string& val_) bool UniValue::setInt(uint64_t val_) { - ostringstream oss; + std::ostringstream oss; oss << val_; @@ -67,7 +65,7 @@ bool UniValue::setInt(uint64_t val_) bool UniValue::setInt(int64_t val_) { - ostringstream oss; + std::ostringstream oss; oss << val_; @@ -76,7 +74,7 @@ bool UniValue::setInt(int64_t val_) bool UniValue::setFloat(double val_) { - ostringstream oss; + std::ostringstream oss; oss << std::setprecision(16) << val_; @@ -85,7 +83,7 @@ bool UniValue::setFloat(double val_) return ret; } -bool UniValue::setStr(const string& val_) +bool UniValue::setStr(const std::string& val_) { clear(); typ = VSTR; diff --git a/src/univalue/lib/univalue_read.cpp b/src/univalue/lib/univalue_read.cpp index 7a1134dd77..f8a5d4d76f 100644 --- a/src/univalue/lib/univalue_read.cpp +++ b/src/univalue/lib/univalue_read.cpp @@ -8,7 +8,13 @@ #include "univalue.h" #include "univalue_utffilter.h" -using namespace std; +/* + * According to stackexchange, the original json test suite wanted + * to limit depth to 22. Widely-deployed PHP bails at depth 512, + * so we will follow PHP's lead, which should be more than sufficient + * (further stackexchange comments indicate depth > 32 rarely occurs). + */ +static const size_t MAX_JSON_DEPTH = 512; static bool json_isdigit(int ch) { @@ -42,7 +48,7 @@ static const char *hatoui(const char *first, const char *last, return first; } -enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, +enum jtokentype getJsonToken(std::string& tokenVal, unsigned int& consumed, const char *raw, const char *end) { tokenVal.clear(); @@ -114,7 +120,7 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, case '8': case '9': { // part 1: int - string numStr; + std::string numStr; const char *first = raw; @@ -174,7 +180,7 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, case '"': { raw++; // skip " - string valStr; + std::string valStr; JSONUTF8StringFilter writer(valStr); while (true) { @@ -255,9 +261,9 @@ bool UniValue::read(const char *raw, size_t size) clear(); uint32_t expectMask = 0; - vector stack; + std::vector stack; - string tokenVal; + std::string tokenVal; unsigned int consumed; enum jtokentype tok = JTOK_NONE; enum jtokentype last_tok = JTOK_NONE; @@ -325,6 +331,9 @@ bool UniValue::read(const char *raw, size_t size) stack.push_back(newTop); } + if (stack.size() > MAX_JSON_DEPTH) + return false; + if (utyp == VOBJ) setExpect(OBJ_NAME); else diff --git a/src/univalue/lib/univalue_write.cpp b/src/univalue/lib/univalue_write.cpp index 0bbb092d89..d31414edde 100644 --- a/src/univalue/lib/univalue_write.cpp +++ b/src/univalue/lib/univalue_write.cpp @@ -8,11 +8,9 @@ #include "univalue.h" #include "univalue_escapes.h" -using namespace std; - -static string json_escape(const string& inS) +static std::string json_escape(const std::string& inS) { - string outS; + std::string outS; outS.reserve(inS.size() * 2); for (unsigned int i = 0; i < inS.size(); i++) { @@ -28,10 +26,10 @@ static string json_escape(const string& inS) return outS; } -string UniValue::write(unsigned int prettyIndent, - unsigned int indentLevel) const +std::string UniValue::write(unsigned int prettyIndent, + unsigned int indentLevel) const { - string s; + std::string s; s.reserve(1024); unsigned int modIndent = indentLevel; @@ -62,12 +60,12 @@ string UniValue::write(unsigned int prettyIndent, return s; } -static void indentStr(unsigned int prettyIndent, unsigned int indentLevel, string& s) +static void indentStr(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) { s.append(prettyIndent * indentLevel, ' '); } -void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, string& s) const +void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const { s += "["; if (prettyIndent) @@ -89,7 +87,7 @@ void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, s s += "]"; } -void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, string& s) const +void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const { s += "{"; if (prettyIndent) diff --git a/src/univalue/test/fail45.json b/src/univalue/test/fail45.json new file mode 100644 index 0000000000..03a30d8800 --- /dev/null +++ b/src/univalue/test/fail45.json @@ -0,0 +1 @@ +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp index a168493907..c2f52f83ac 100644 --- a/src/univalue/test/object.cpp +++ b/src/univalue/test/object.cpp @@ -210,19 +210,31 @@ BOOST_AUTO_TEST_CASE(univalue_array) BOOST_CHECK(arr.push_back((int64_t) -400LL)); BOOST_CHECK(arr.push_back((int) -401)); BOOST_CHECK(arr.push_back(-40.1)); + BOOST_CHECK(arr.push_back(true)); BOOST_CHECK_EQUAL(arr.empty(), false); - BOOST_CHECK_EQUAL(arr.size(), 9); + BOOST_CHECK_EQUAL(arr.size(), 10); BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023"); + BOOST_CHECK_EQUAL(arr[0].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy"); + BOOST_CHECK_EQUAL(arr[1].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy"); + BOOST_CHECK_EQUAL(arr[2].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing"); + BOOST_CHECK_EQUAL(arr[3].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[4].getValStr(), "going"); + BOOST_CHECK_EQUAL(arr[4].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[5].getValStr(), "400"); + BOOST_CHECK_EQUAL(arr[5].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[6].getValStr(), "-400"); + BOOST_CHECK_EQUAL(arr[6].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[7].getValStr(), "-401"); + BOOST_CHECK_EQUAL(arr[7].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[8].getValStr(), "-40.1"); + BOOST_CHECK_EQUAL(arr[8].getType(), UniValue::VNUM); + BOOST_CHECK_EQUAL(arr[9].getValStr(), "1"); + BOOST_CHECK_EQUAL(arr[9].getType(), UniValue::VBOOL); BOOST_CHECK_EQUAL(arr[999].getValStr(), ""); diff --git a/src/univalue/test/pass4.json b/src/univalue/test/pass4.json new file mode 100644 index 0000000000..f5a680b31c --- /dev/null +++ b/src/univalue/test/pass4.json @@ -0,0 +1 @@ +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] diff --git a/src/univalue/test/unitester.cpp b/src/univalue/test/unitester.cpp index 128d753a94..1a6c9ef69f 100644 --- a/src/univalue/test/unitester.cpp +++ b/src/univalue/test/unitester.cpp @@ -17,8 +17,7 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif -using namespace std; -string srcdir(JSON_TEST_SRC); +std::string srcdir(JSON_TEST_SRC); static bool test_failed = false; #define d_assert(expr) { if (!(expr)) { test_failed = true; fprintf(stderr, "%s failed\n", filename.c_str()); } } @@ -30,9 +29,9 @@ static std::string rtrim(std::string s) return s; } -static void runtest(string filename, const string& jdata) +static void runtest(std::string filename, const std::string& jdata) { - string prefix = filename.substr(0, 4); + std::string prefix = filename.substr(0, 4); bool wantPass = (prefix == "pass") || (prefix == "roun"); bool wantFail = (prefix == "fail"); @@ -56,19 +55,19 @@ static void runtest(string filename, const string& jdata) static void runtest_file(const char *filename_) { - string basename(filename_); - string filename = srcdir + "/" + basename; + std::string basename(filename_); + std::string filename = srcdir + "/" + basename; FILE *f = fopen(filename.c_str(), "r"); assert(f != NULL); - string jdata; + std::string jdata; char buf[4096]; while (!feof(f)) { int bread = fread(buf, 1, sizeof(buf), f); assert(!ferror(f)); - string s(buf, bread); + std::string s(buf, bread); jdata += s; } @@ -115,6 +114,7 @@ static const char *filenames[] = { "fail41.json", // invalid unicode: unfinished UTF-8 "fail42.json", // valid json with garbage following a nul byte "fail44.json", // unterminated string + "fail45.json", // nested beyond max depth "fail3.json", "fail4.json", // extra comma "fail5.json", @@ -125,6 +125,7 @@ static const char *filenames[] = { "pass1.json", "pass2.json", "pass3.json", + "pass4.json", "round1.json", // round-trip test "round2.json", // unicode "round3.json", // bare string From e4ba8977343ccfc63835306bcbf852cca7c28a68 Mon Sep 17 00:00:00 2001 From: barton26 Date: Wed, 15 Sep 2021 22:45:21 -0400 Subject: [PATCH 2/3] rpc: Consistently use UniValue.pushKV instead of push_back(Pair()) --- src/rpc/protocol.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index b7a4da4890..ba8a732a03 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -241,9 +241,9 @@ int ReadHTTPMessage(std::basic_istream& stream, std::map Date: Thu, 16 Sep 2021 18:53:42 -0400 Subject: [PATCH 3/3] rpc: Consistently use UniValue.pushKV instead of push_back in consolidateunspent Co-Authored-By: James C. Owens --- src/rpc/rawtransaction.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 59b3dfabfe..5dacd88f57 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1195,19 +1195,19 @@ UniValue consolidatemsunspent(const UniValue& params, bool fHelp) sMultisigtype.append("_of_"); sMultisigtype.append(ToString(vOpCodes[1])); - result.push_back(std::make_pair("multi_sig_type", sMultisigtype)); - result.push_back(std::make_pair("block_start", nBlockStart)); - result.push_back(std::make_pair("block_end", nBlockEnd)); + result.pushKV("multi_sig_type", sMultisigtype); + result.pushKV("block_start", nBlockStart); + result.pushKV("block_end", nBlockEnd); // Let rpc caller know this was the last block we were in especially if the target amount of inputs was met before end block - result.push_back(std::make_pair("last_block_checked", nBlockCurrent)); - result.push_back(std::make_pair("number_of_inputs", nInputs)); - result.push_back(std::make_pair("maximum_possible_inputs", nMaxInputs)); - result.push_back(std::make_pair("total_grc_in", ValueFromAmount(nTotal))); - result.push_back(std::make_pair("fee", nTxFee)); - result.push_back(std::make_pair("output_amount", ValueFromAmount(nOutput))); - result.push_back(std::make_pair("estimated_signed_hex_size", (nBytes * 2))); - result.push_back(std::make_pair("estimated_signed_binary_size", nBytes)); - result.push_back(std::make_pair("rawtx", sHash)); + result.pushKV("last_block_checked", nBlockCurrent); + result.pushKV("number_of_inputs", nInputs); + result.pushKV("maximum_possible_inputs", nMaxInputs); + result.pushKV("total_grc_in", ValueFromAmount(nTotal)); + result.pushKV("fee", nTxFee); + result.pushKV("output_amount", ValueFromAmount(nOutput)); + result.pushKV("estimated_signed_hex_size", (nBytes * 2)); + result.pushKV("estimated_signed_binary_size", nBytes); + result.pushKV("rawtx", sHash); return result; }