diff options
-rwxr-xr-x | ci/test/05_before_script.sh | 2 | ||||
-rw-r--r-- | doc/release-notes-15437.md | 53 | ||||
-rw-r--r-- | doc/release-notes-15954.md | 4 | ||||
-rw-r--r-- | doc/release-notes-17056.md | 4 | ||||
-rw-r--r-- | doc/release-notes-17264.md | 4 | ||||
-rw-r--r-- | doc/release-notes-17410.md | 5 | ||||
-rw-r--r-- | doc/release-notes-17437.md | 5 | ||||
-rw-r--r-- | doc/release-notes-17578.md | 13 | ||||
-rw-r--r-- | doc/release-notes.md | 79 | ||||
-rw-r--r-- | src/logging/timer.h | 2 | ||||
-rw-r--r-- | src/node/psbt.cpp | 2 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 620 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 219 | ||||
-rw-r--r-- | src/rpc/misc.cpp | 86 | ||||
-rw-r--r-- | src/rpc/net.cpp | 256 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 554 | ||||
-rw-r--r-- | src/rpc/server.cpp | 26 | ||||
-rw-r--r-- | src/rpc/util.cpp | 114 | ||||
-rw-r--r-- | src/rpc/util.h | 143 | ||||
-rw-r--r-- | src/txmempool.h | 2 | ||||
-rw-r--r-- | src/wallet/rpcdump.cpp | 37 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 691 | ||||
-rw-r--r-- | src/zmq/zmqrpc.cpp | 17 | ||||
-rwxr-xr-x | test/functional/feature_backwards_compatibility.py | 2 | ||||
-rwxr-xr-x | test/lint/lint-shell.sh | 2 | ||||
-rw-r--r-- | test/lint/lint-spelling.ignore-words.txt | 2 |
26 files changed, 1598 insertions, 1346 deletions
diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh index 1cb5c30901..933f4cea91 100755 --- a/ci/test/05_before_script.sh +++ b/ci/test/05_before_script.sh @@ -26,7 +26,7 @@ if [[ $HOST = *-mingw32 ]]; then fi if [ -z "$NO_DEPENDS" ]; then if [[ $DOCKER_NAME_TAG == centos* ]]; then - # CentOS has problems building the depends if the config shell is not explicitely set + # CentOS has problems building the depends if the config shell is not explicitly set # (i.e. for libevent a Makefile with an empty SHELL variable is generated, leading to # an error as the first command is executed) SHELL_OPTS="CONFIG_SHELL=/bin/bash" diff --git a/doc/release-notes-15437.md b/doc/release-notes-15437.md deleted file mode 100644 index 6614207757..0000000000 --- a/doc/release-notes-15437.md +++ /dev/null @@ -1,53 +0,0 @@ -P2P and network changes ------------------------ - -#### Removal of reject network messages from Bitcoin Core (BIP61) - -The command line option to enable BIP61 (`-enablebip61`) has been removed. - -This feature has been disabled by default since Bitcoin Core version 0.18.0. -Nodes on the network can not generally be trusted to send valid ("reject") -messages, so this should only ever be used when connected to a trusted node. -Please use the recommended alternatives if you rely on this deprecated feature: - -* Testing or debugging of implementations of the Bitcoin P2P network protocol - should be done by inspecting the log messages that are produced by a recent - version of Bitcoin Core. Bitcoin Core logs debug messages - (`-debug=<category>`) to a stream (`-printtoconsole`) or to a file - (`-debuglogfile=<debug.log>`). - -* Testing the validity of a block can be achieved by specific RPCs: - - `submitblock` - - `getblocktemplate` with `'mode'` set to `'proposal'` for blocks with - potentially invalid POW - -* Testing the validity of a transaction can be achieved by specific RPCs: - - `sendrawtransaction` - - `testmempoolaccept` - -* Wallets should not use the absence of "reject" messages to indicate a - transaction has propagated the network, nor should wallets use "reject" - messages to set transaction fees. Wallets should rather use fee estimation - to determine transaction fees and set replace-by-fee if desired. Thus, they - could wait until the transaction has confirmed (taking into account the fee - target they set (compare the RPC `estimatesmartfee`)) or listen for the - transaction announcement by other network peers to check for propagation. - -The removal of BIP61 REJECT message support also has the following minor RPC -and logging implications: - -* `testmempoolaccept` and `sendrawtransaction` no longer return the P2P REJECT - code when a transaction is not accepted to the mempool. They still return the - verbal reject reason. - -* Log messages that previously reported the REJECT code when a transaction was - not accepted to the mempool now no longer report the REJECT code. The reason - for rejection is still reported. - -Updated RPCs ------------- - -- `testmempoolaccept` and `sendrawtransaction` no longer return the P2P REJECT - code when a transaction is not accepted to the mempool. See the Section - _Removal of reject network messages from Bitcoin Core (BIP61)_ for details on - the removal of BIP61 REJECT message support. diff --git a/doc/release-notes-15954.md b/doc/release-notes-15954.md deleted file mode 100644 index f4d2c5688c..0000000000 --- a/doc/release-notes-15954.md +++ /dev/null @@ -1,4 +0,0 @@ -Configuration option changes ------------------------------ - -Importing blocks upon startup via the `bootstrap.dat` file no longer occurs by default. The file must now be specified with `-loadblock=<file>`. diff --git a/doc/release-notes-17056.md b/doc/release-notes-17056.md deleted file mode 100644 index 23d5a8c8cd..0000000000 --- a/doc/release-notes-17056.md +++ /dev/null @@ -1,4 +0,0 @@ -Low-level RPC Changes -=== - -- A new descriptor type `sortedmulti(...)` has been added to support multisig scripts where the public keys are sorted lexicographically in the resulting script. diff --git a/doc/release-notes-17264.md b/doc/release-notes-17264.md deleted file mode 100644 index f6e0979596..0000000000 --- a/doc/release-notes-17264.md +++ /dev/null @@ -1,4 +0,0 @@ -Updated RPCs ------------- - -- `walletprocesspsbt` and `walletcreatefundedpsbt` now include BIP 32 derivation paths by default for public keys if we know them. This can be disabled by setting `bip32derivs` to `false`. diff --git a/doc/release-notes-17410.md b/doc/release-notes-17410.md deleted file mode 100644 index 08ed353889..0000000000 --- a/doc/release-notes-17410.md +++ /dev/null @@ -1,5 +0,0 @@ -Command-line options --------------------- - -- The `-debug=db` logging category has been renamed to `-debug=walletdb`, to distinguish it from `coindb`. - `-debug=db` has been deprecated and will be removed in the next major release. diff --git a/doc/release-notes-17437.md b/doc/release-notes-17437.md deleted file mode 100644 index 3edfd00a38..0000000000 --- a/doc/release-notes-17437.md +++ /dev/null @@ -1,5 +0,0 @@ -Low-level RPC Changes -=== - -- The RPC gettransaction, listtransactions and listsinceblock responses now also -includes the height of the block that contains the wallet transaction, if any. diff --git a/doc/release-notes-17578.md b/doc/release-notes-17578.md deleted file mode 100644 index 664d17fd78..0000000000 --- a/doc/release-notes-17578.md +++ /dev/null @@ -1,13 +0,0 @@ -Deprecated or removed RPCs --------------------------- - -- RPC `getaddressinfo` changes: - - - the `label` field has been deprecated in favor of the `labels` field and - will be removed in 0.21. It can be re-enabled in the interim by launching - with `-deprecatedrpc=label`. - - - the `labels` behavior of returning an array of JSON objects containing name - and purpose key/value pairs has been deprecated in favor of an array of - label names and will be removed in 0.21. The previous behavior can be - re-enabled in the interim by launching with `-deprecatedrpc=labelspurpose`. diff --git a/doc/release-notes.md b/doc/release-notes.md index 99ca53c597..cb46408d94 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -62,6 +62,64 @@ distribution provides binaries for the RISC-V platform. Notable changes =============== +P2P and network changes +----------------------- + +#### Removal of reject network messages from Bitcoin Core (BIP61) + +The command line option to enable BIP61 (`-enablebip61`) has been removed. + +This feature has been disabled by default since Bitcoin Core version 0.18.0. +Nodes on the network can not generally be trusted to send valid ("reject") +messages, so this should only ever be used when connected to a trusted node. +Please use the recommended alternatives if you rely on this deprecated feature: + +* Testing or debugging of implementations of the Bitcoin P2P network protocol + should be done by inspecting the log messages that are produced by a recent + version of Bitcoin Core. Bitcoin Core logs debug messages + (`-debug=<category>`) to a stream (`-printtoconsole`) or to a file + (`-debuglogfile=<debug.log>`). + +* Testing the validity of a block can be achieved by specific RPCs: + - `submitblock` + - `getblocktemplate` with `'mode'` set to `'proposal'` for blocks with + potentially invalid POW + +* Testing the validity of a transaction can be achieved by specific RPCs: + - `sendrawtransaction` + - `testmempoolaccept` + +* Wallets should not use the absence of "reject" messages to indicate a + transaction has propagated the network, nor should wallets use "reject" + messages to set transaction fees. Wallets should rather use fee estimation + to determine transaction fees and set replace-by-fee if desired. Thus, they + could wait until the transaction has confirmed (taking into account the fee + target they set (compare the RPC `estimatesmartfee`)) or listen for the + transaction announcement by other network peers to check for propagation. + +The removal of BIP61 REJECT message support also has the following minor RPC +and logging implications: + +* `testmempoolaccept` and `sendrawtransaction` no longer return the P2P REJECT + code when a transaction is not accepted to the mempool. They still return the + verbal reject reason. + +* Log messages that previously reported the REJECT code when a transaction was + not accepted to the mempool now no longer report the REJECT code. The reason + for rejection is still reported. + +Updated RPCs +------------ + +- `testmempoolaccept` and `sendrawtransaction` no longer return the P2P REJECT + code when a transaction is not accepted to the mempool. See the Section + _Removal of reject network messages from Bitcoin Core (BIP61)_ for details on + the removal of BIP61 REJECT message support. + +- A new descriptor type `sortedmulti(...)` has been added to support multisig scripts where the public keys are sorted lexicographically in the resulting script. + +- `walletprocesspsbt` and `walletcreatefundedpsbt` now include BIP 32 derivation paths by default for public keys if we know them. This can be disabled by setting `bip32derivs` to `false`. + Build System ------------ @@ -84,11 +142,10 @@ It can be set with two command line arguments (`rpcwhitelist` and `rpcwhitelistd Updated settings ---------------- -Updated RPCs ------------- +Importing blocks upon startup via the `bootstrap.dat` file no longer occurs by default. The file must now be specified with `-loadblock=<file>`. -Note: some low-level RPC changes mainly useful for testing are described in the -Low-level Changes section below. +- The `-debug=db` logging category has been renamed to `-debug=walletdb`, to distinguish it from `coindb`. + `-debug=db` has been deprecated and will be removed in the next major release. GUI changes ----------- @@ -101,6 +158,20 @@ Wallet - The wallet now by default uses bech32 addresses when using RPC, and creates native segwit change outputs. - The way that output trust was computed has been fixed in #16766, which impacts confirmed/unconfirmed balance status and coin selection. +- The RPC gettransaction, listtransactions and listsinceblock responses now also +includes the height of the block that contains the wallet transaction, if any. + +- RPC `getaddressinfo` changes: + + - the `label` field has been deprecated in favor of the `labels` field and + will be removed in 0.21. It can be re-enabled in the interim by launching + with `-deprecatedrpc=label`. + + - the `labels` behavior of returning an array of JSON objects containing name + and purpose key/value pairs has been deprecated in favor of an array of + label names and will be removed in 0.21. The previous behavior can be + re-enabled in the interim by launching with `-deprecatedrpc=labelspurpose`. + Low-level changes ================= diff --git a/src/logging/timer.h b/src/logging/timer.h index 45bfc4aa65..2b27c71080 100644 --- a/src/logging/timer.h +++ b/src/logging/timer.h @@ -85,7 +85,7 @@ private: const std::string m_title{}; //! Forwarded on to LogPrint if specified - has the effect of only - //! outputing the timing log when a particular debug= category is specified. + //! outputting the timing log when a particular debug= category is specified. const BCLog::LogFlags m_log_category{}; }; diff --git a/src/node/psbt.cpp b/src/node/psbt.cpp index 0fc19b7a11..5b16035f7d 100644 --- a/src/node/psbt.cpp +++ b/src/node/psbt.cpp @@ -84,7 +84,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx) } } - // Calculate next role for PSBT by grabbing "minumum" PSBTInput next role + // Calculate next role for PSBT by grabbing "minimum" PSBTInput next role result.next = PSBTRole::EXTRACTOR; for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) { PSBTInputAnalysis& input_analysis = result.inputs[i]; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 40637a552e..133d1b809f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -177,8 +177,7 @@ static UniValue getblockcount(const JSONRPCRequest& request) "The genesis block has height 0.\n", {}, RPCResult{ - "n (numeric) The current block count\n" - }, + RPCResult::Type::NUM, "", "The current block count"}, RPCExamples{ HelpExampleCli("getblockcount", "") + HelpExampleRpc("getblockcount", "") @@ -195,8 +194,7 @@ static UniValue getbestblockhash(const JSONRPCRequest& request) "\nReturns the hash of the best (tip) block in the most-work fully-validated chain.\n", {}, RPCResult{ - "\"hex\" (string) the block hash, hex-encoded\n" - }, + RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"}, RPCExamples{ HelpExampleCli("getbestblockhash", "") + HelpExampleRpc("getbestblockhash", "") @@ -226,11 +224,11 @@ static UniValue waitfornewblock(const JSONRPCRequest& request) {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."}, }, RPCResult{ - "{ (json object)\n" - " \"hash\" : { (string) The blockhash\n" - " \"height\" : { (numeric) Block height\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "The blockhash"}, + {RPCResult::Type::NUM, "height", "Block height"}, + }}, RPCExamples{ HelpExampleCli("waitfornewblock", "1000") + HelpExampleRpc("waitfornewblock", "1000") @@ -266,11 +264,11 @@ static UniValue waitforblock(const JSONRPCRequest& request) {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."}, }, RPCResult{ - "{ (json object)\n" - " \"hash\" : { (string) The blockhash\n" - " \"height\" : { (numeric) Block height\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "The blockhash"}, + {RPCResult::Type::NUM, "height", "Block height"}, + }}, RPCExamples{ HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000") + HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000") @@ -310,11 +308,11 @@ static UniValue waitforblockheight(const JSONRPCRequest& request) {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."}, }, RPCResult{ - "{ (json object)\n" - " \"hash\" : { (string) The blockhash\n" - " \"height\" : { (numeric) Block height\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "The blockhash"}, + {RPCResult::Type::NUM, "height", "Block height"}, + }}, RPCExamples{ HelpExampleCli("waitforblockheight", "\"100\", 1000") + HelpExampleRpc("waitforblockheight", "\"100\", 1000") @@ -364,8 +362,7 @@ static UniValue getdifficulty(const JSONRPCRequest& request) "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n", {}, RPCResult{ - "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - }, + RPCResult::Type::NUM, "", "the proof-of-work difficulty as a multiple of the minimum difficulty."}, RPCExamples{ HelpExampleCli("getdifficulty", "") + HelpExampleRpc("getdifficulty", "") @@ -376,37 +373,35 @@ static UniValue getdifficulty(const JSONRPCRequest& request) return GetDifficulty(::ChainActive().Tip()); } -static std::string EntryDescriptionString() -{ - return " \"vsize\" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.\n" - " \"size\" : n, (numeric) (DEPRECATED) same as vsize. Only returned if bitcoind is started with -deprecatedrpc=size\n" - " size will be completely removed in v0.20.\n" - " \"weight\" : n, (numeric) transaction weight as defined in BIP 141.\n" - " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)\n" - " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority (DEPRECATED)\n" - " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" - " \"height\" : n, (numeric) block height when transaction entered pool\n" - " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n" - " \"descendantsize\" : n, (numeric) virtual transaction size of in-mempool descendants (including this one)\n" - " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) (DEPRECATED)\n" - " \"ancestorcount\" : n, (numeric) number of in-mempool ancestor transactions (including this one)\n" - " \"ancestorsize\" : n, (numeric) virtual transaction size of in-mempool ancestors (including this one)\n" - " \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) (DEPRECATED)\n" - " \"wtxid\" : hash, (string) hash of serialized transaction, including witness data\n" - " \"fees\" : {\n" - " \"base\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" - " \"modified\" : n, (numeric) transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT + "\n" - " \"ancestor\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT + "\n" - " \"descendant\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT + "\n" - " }\n" - " \"depends\" : [ (json array) unconfirmed transactions used as inputs for this transaction\n" - " \"transactionid\", (string) parent transaction id\n" - " ... ]\n" - " \"spentby\" : [ (json array) unconfirmed transactions spending outputs from this transaction\n" - " \"transactionid\", (string) child transaction id\n" - " ... ]\n" - " \"bip125-replaceable\" : true|false, (boolean) Whether this transaction could be replaced due to BIP125 (replace-by-fee)\n"; -} +static std::vector<RPCResult> MempoolEntryDescription() { return { + RPCResult{RPCResult::Type::NUM, "vsize", "virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."}, + RPCResult{RPCResult::Type::NUM, "size", "(DEPRECATED) same as vsize. Only returned if bitcoind is started with -deprecatedrpc=size\n" + "size will be completely removed in v0.20."}, + RPCResult{RPCResult::Type::NUM, "weight", "transaction weight as defined in BIP 141."}, + RPCResult{RPCResult::Type::STR_AMOUNT, "fee", "transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)"}, + RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee", "transaction fee with fee deltas used for mining priority (DEPRECATED)"}, + RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"}, + RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"}, + RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"}, + RPCResult{RPCResult::Type::NUM, "descendantsize", "virtual transaction size of in-mempool descendants (including this one)"}, + RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees", "modified fees (see above) of in-mempool descendants (including this one) (DEPRECATED)"}, + RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"}, + RPCResult{RPCResult::Type::NUM, "ancestorsize", "virtual transaction size of in-mempool ancestors (including this one)"}, + RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees", "modified fees (see above) of in-mempool ancestors (including this one) (DEPRECATED)"}, + RPCResult{RPCResult::Type::STR_HEX, "wtxid", "hash of serialized transaction, including witness data"}, + RPCResult{RPCResult::Type::OBJ, "fees", "", + { + RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT}, + RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT}, + RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT}, + RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT}, + }}, + RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction", + {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}}, + RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction", + {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}}, + RPCResult{RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction could be replaced due to BIP125 (replace-by-fee)"}, +};} static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs) { @@ -505,17 +500,17 @@ static UniValue getrawmempool(const JSONRPCRequest& request) { {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"}, }, - RPCResult{"for verbose = false", - "[ (json array of string)\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - "\nResult: (for verbose = true):\n" - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - + EntryDescriptionString() - + " }, ...\n" - "}\n" + { + RPCResult{"for verbose = false", + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::STR_HEX, "", "The transaction id"}, + }}, + RPCResult{"for verbose = true", + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ_DYN, "transactionid", "", MempoolEntryDescription()}, + }}, }, RPCExamples{ HelpExampleCli("getrawmempool", "true") @@ -540,18 +535,10 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request) }, { RPCResult{"for verbose = false", - "[ (json array of strings)\n" - " \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n" - " ,...\n" - "]\n" - }, + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool ancestor transaction"}}}, RPCResult{"for verbose = true", - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - + EntryDescriptionString() - + " }, ...\n" - "}\n" - }, + RPCResult::Type::OBJ_DYN, "transactionid", "", MempoolEntryDescription()}, }, RPCExamples{ HelpExampleCli("getmempoolancestors", "\"mytxid\"") @@ -608,18 +595,13 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request) }, { RPCResult{"for verbose = false", - "[ (json array of strings)\n" - " \"transactionid\" (string) The transaction id of an in-mempool descendant transaction\n" - " ,...\n" - "]\n" - }, + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool descendant transaction"}}}, RPCResult{"for verbose = true", - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - + EntryDescriptionString() - + " }, ...\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ_DYN, "transactionid", "", MempoolEntryDescription()}, + }}, }, RPCExamples{ HelpExampleCli("getmempooldescendants", "\"mytxid\"") @@ -674,10 +656,7 @@ static UniValue getmempoolentry(const JSONRPCRequest& request) {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"}, }, RPCResult{ - "{ (json object)\n" - + EntryDescriptionString() - + "}\n" - }, + RPCResult::Type::OBJ_DYN, "", "", MempoolEntryDescription()}, RPCExamples{ HelpExampleCli("getmempoolentry", "\"mytxid\"") + HelpExampleRpc("getmempoolentry", "\"mytxid\"") @@ -708,8 +687,7 @@ static UniValue getblockhash(const JSONRPCRequest& request) {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The height index"}, }, RPCResult{ - "\"hash\" (string) The block hash\n" - }, + RPCResult::Type::STR_HEX, "", "The block hash"}, RPCExamples{ HelpExampleCli("getblockhash", "1000") + HelpExampleRpc("getblockhash", "1000") @@ -737,27 +715,26 @@ static UniValue getblockheader(const JSONRPCRequest& request) }, { RPCResult{"for verbose = true", - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"time\" : ttt, (numeric) The block time expressed in " + UNIX_EPOCH_TIME + "\n" - " \"mediantime\" : ttt, (numeric) The median block time expressed in " + UNIX_EPOCH_TIME + "\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n" - " \"nTx\" : n, (numeric) The number of transactions in the block.\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\", (string) The hash of the next block\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "the block hash (same as provided)"}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations, or -1 if the block is not on the main chain"}, + {RPCResult::Type::NUM, "height", "The block height or index"}, + {RPCResult::Type::NUM, "version", "The block version"}, + {RPCResult::Type::STR_HEX, "versionHex", "The block version formatted in hexadecimal"}, + {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"}, + {RPCResult::Type::NUM_TIME, "time", "The block time expressed in " + UNIX_EPOCH_TIME}, + {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME}, + {RPCResult::Type::NUM, "nonce", "The nonce"}, + {RPCResult::Type::STR_HEX, "bits", "The bits"}, + {RPCResult::Type::NUM, "difficulty", "The difficulty"}, + {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the current chain"}, + {RPCResult::Type::NUM, "nTx", "The number of transactions in the block"}, + {RPCResult::Type::STR_HEX, "previousblockhash", "The hash of the previous block"}, + {RPCResult::Type::STR_HEX, "nextblockhash", "The hash of the next block"}, + }}, RPCResult{"for verbose=false", - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - }, + RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"}, }, RPCExamples{ HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") @@ -839,44 +816,45 @@ static UniValue getblock(const JSONRPCRequest& request) }, { RPCResult{"for verbosity = 0", - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - }, + RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"}, RPCResult{"for verbosity = 1", - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"size\" : n, (numeric) The block size\n" - " \"strippedsize\" : n, (numeric) The block size excluding witness data\n" - " \"weight\" : n (numeric) The block weight as defined in BIP 141\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"tx\" : [ (array of string) The transaction ids\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - " ],\n" - " \"time\" : ttt, (numeric) The block time expressed in " + UNIX_EPOCH_TIME + "\n" - " \"mediantime\" : ttt, (numeric) The median block time expressed in " + UNIX_EPOCH_TIME + "\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"chainwork\" : \"xxxx\", (string) Expected number of hashes required to produce the chain up to this block (in hex)\n" - " \"nTx\" : n, (numeric) The number of transactions in the block.\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "the block hash (same as provided)"}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations, or -1 if the block is not on the main chain"}, + {RPCResult::Type::NUM, "size", "The block size"}, + {RPCResult::Type::NUM, "strippedsize", "The block size excluding witness data"}, + {RPCResult::Type::NUM, "weight", "The block weight as defined in BIP 141"}, + {RPCResult::Type::NUM, "height", "The block height or index"}, + {RPCResult::Type::NUM, "version", "The block version"}, + {RPCResult::Type::STR_HEX, "versionHex", "The block version formatted in hexadecimal"}, + {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"}, + {RPCResult::Type::ARR, "tx", "The transaction ids", + {{RPCResult::Type::STR_HEX, "", "The transaction id"}}}, + {RPCResult::Type::NUM_TIME, "time", "The block time expressed in " + UNIX_EPOCH_TIME}, + {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME}, + {RPCResult::Type::NUM, "nonce", "The nonce"}, + {RPCResult::Type::STR_HEX, "bits", "The bits"}, + {RPCResult::Type::NUM, "difficulty", "The difficulty"}, + {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the chain up to this block (in hex)"}, + {RPCResult::Type::NUM, "nTx", "The number of transactions in the block"}, + {RPCResult::Type::STR_HEX, "previousblockhash", "The hash of the previous block"}, + {RPCResult::Type::STR_HEX, "nextblockhash", "The hash of the next block"}, + }}, RPCResult{"for verbosity = 2", - "{\n" - " ..., Same output as verbosity = 1.\n" - " \"tx\" : [ (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result.\n" - " ,...\n" - " ],\n" - " ,... Same output as verbosity = 1.\n" - "}\n" - }, - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ELISION, "", "Same output as verbosity = 1"}, + {RPCResult::Type::ARR, "tx", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ELISION, "", "The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result"}, + }}, + }}, + {RPCResult::Type::ELISION, "", "Same output as verbosity = 1"}, + }}, + }, RPCExamples{ HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") @@ -927,8 +905,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request) " to prune blocks whose block time is at least 2 hours older than the provided timestamp."}, }, RPCResult{ - "n (numeric) Height of the last block pruned.\n" - }, + RPCResult::Type::NUM, "", "Height of the last block pruned"}, RPCExamples{ HelpExampleCli("pruneblockchain", "1000") + HelpExampleRpc("pruneblockchain", "1000") @@ -982,17 +959,17 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request) "Note this call may take some time.\n", {}, RPCResult{ - "{\n" - " \"height\" : n, (numeric) The current block height (index)\n" - " \"bestblock\" : \"hex\", (string) The hash of the block at the tip of the chain\n" - " \"transactions\" : n, (numeric) The number of transactions with unspent outputs\n" - " \"txouts\" : n, (numeric) The number of unspent transaction outputs\n" - " \"bogosize\" : n, (numeric) A meaningless metric for UTXO set size\n" - " \"hash_serialized_2\": \"hash\", (string) The serialized hash\n" - " \"disk_size\" : n, (numeric) The estimated size of the chainstate on disk\n" - " \"total_amount\" : x.xxx (numeric) The total amount\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "height", "The current block height (index)"}, + {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"}, + {RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"}, + {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"}, + {RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"}, + {RPCResult::Type::STR_HEX, "hash_serialized_2", "The serialized hash"}, + {RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk"}, + {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount"}, + }}, RPCExamples{ HelpExampleCli("gettxoutsetinfo", "") + HelpExampleRpc("gettxoutsetinfo", "") @@ -1030,23 +1007,22 @@ UniValue gettxout(const JSONRPCRequest& request) {"include_mempool", RPCArg::Type::BOOL, /* default */ "true", "Whether to include the mempool. Note that an unspent output that is spent in the mempool won't appear."}, }, RPCResult{ - "{\n" - " \"bestblock\" : \"hash\", (string) The hash of the block at the tip of the chain\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"code\", (string) \n" - " \"hex\" : \"hex\", (string) \n" - " \"reqSigs\" : n, (numeric) Number of required signatures\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" - " \"addresses\" : [ (array of string) array of bitcoin addresses\n" - " \"address\" (string) bitcoin address\n" - " ,...\n" - " ]\n" - " },\n" - " \"coinbase\" : true|false (boolean) Coinbase or not\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations"}, + {RPCResult::Type::STR_AMOUNT, "value", "The transaction value in " + CURRENCY_UNIT}, + {RPCResult::Type::OBJ, "scriptPubKey", "", + { + {RPCResult::Type::STR_HEX, "asm", ""}, + {RPCResult::Type::STR_HEX, "hex", ""}, + {RPCResult::Type::NUM, "reqSigs", "Number of required signatures"}, + {RPCResult::Type::STR_HEX, "type", "The type, eg pubkeyhash"}, + {RPCResult::Type::ARR, "addresses", "array of bitcoin addresses", + {{RPCResult::Type::STR, "address", "bitcoin address"}}}, + }}, + {RPCResult::Type::BOOL, "coinbase", "Coinbase or not"}, + }}, RPCExamples{ "\nGet unspent transactions\n" + HelpExampleCli("listunspent", "") + @@ -1111,8 +1087,7 @@ static UniValue verifychain(const JSONRPCRequest& request) {"nblocks", RPCArg::Type::NUM, /* default */ strprintf("%d, 0=all", nCheckDepth), "The number of blocks to check."}, }, RPCResult{ - "true|false (boolean) Verified or not\n" - }, + RPCResult::Type::BOOL, "", "Verified or not"}, RPCExamples{ HelpExampleCli("verifychain", "") + HelpExampleRpc("verifychain", "") @@ -1202,45 +1177,49 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) "Returns an object containing various state info regarding blockchain processing.\n", {}, RPCResult{ - "{\n" - " \"chain\" : \"xxxx\", (string) current network name (main, test, regtest)\n" - " \"blocks\" : xxxxxx, (numeric) the height of the most-work fully-validated chain. The genesis block has height 0\n" - " \"headers\" : xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\" : \"...\", (string) the hash of the currently best block\n" - " \"difficulty\" : xxxxxx, (numeric) the current difficulty\n" - " \"mediantime\" : xxxxxx, (numeric) median time for the current best block\n" - " \"verificationprogress\" : xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"initialblockdownload\" : xxxx, (boolean) (debug information) estimate of whether this node is in Initial Block Download mode.\n" - " \"chainwork\" : \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"size_on_disk\" : xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" - " \"pruned\" : xx, (boolean) if the blocks are subject to pruning\n" - " \"pruneheight\" : xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n" - " \"automatic_pruning\" : xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n" - " \"prune_target_size\" : xxxxxx, (numeric) the target size used by pruning (only present if automatic pruning is enabled)\n" - " \"softforks\" : { (json object) status of softforks\n" - " \"xxxx\" : { (string) name of the softfork\n" - " \"type\" : \"xxxx\", (string) one of \"buried\", \"bip9\"\n" - " \"bip9\": { (json object) status of bip9 softforks (only for \"bip9\" type)\n" - " \"status\" : \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" - " \"bit\" : xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" - " \"start_time\" : xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" - " \"timeout\" : xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" - " \"since\" : xx, (numeric) height of the first block to which the status applies\n" - " \"statistics\" : { (json object) numeric statistics about BIP9 signalling for a softfork\n" - " \"period\" : xx, (numeric) the length in blocks of the BIP9 signalling period \n" - " \"threshold\" : xx, (numeric) the number of blocks with the version bit set required to activate the feature \n" - " \"elapsed\" : xx, (numeric) the number of blocks elapsed since the beginning of the current period \n" - " \"count\" : xx, (numeric) the number of blocks with the version bit set in the current period \n" - " \"possible\" : xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n" - " }\n" - " },\n" - " \"height\" : \"xxxxxx\", (numeric) height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)\n" - " \"active\" : xx, (boolean) true if the rules are enforced for the mempool and the next block\n" - " }\n" - " }\n" - " \"warnings\" : \"...\", (string) any network and blockchain warnings.\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "chain", "current network name (main, test, regtest)"}, + {RPCResult::Type::NUM, "blocks", "the height of the most-work fully-validated chain. The genesis block has height 0"}, + {RPCResult::Type::NUM, "headers", "the current number of headers we have validated"}, + {RPCResult::Type::STR, "bestblockhash", "the hash of the currently best block"}, + {RPCResult::Type::NUM, "difficulty", "the current difficulty"}, + {RPCResult::Type::NUM, "mediantime", "median time for the current best block"}, + {RPCResult::Type::NUM, "verificationprogress", "estimate of verification progress [0..1]"}, + {RPCResult::Type::BOOL, "initialblockdownload", "(debug information) estimate of whether this node is in Initial Block Download mode"}, + {RPCResult::Type::STR_HEX, "chainwork", "total amount of work in active chain, in hexadecimal"}, + {RPCResult::Type::NUM, "size_on_disk", "the estimated size of the block and undo files on disk"}, + {RPCResult::Type::BOOL, "pruned", "if the blocks are subject to pruning"}, + {RPCResult::Type::NUM, "pruneheight", "lowest-height complete block stored (only present if pruning is enabled)"}, + {RPCResult::Type::BOOL, "automatic_pruning", "whether automatic pruning is enabled (only present if pruning is enabled)"}, + {RPCResult::Type::NUM, "prune_target_size", "the target size used by pruning (only present if automatic pruning is enabled)"}, + {RPCResult::Type::OBJ_DYN, "softforks", "status of softforks", + { + {RPCResult::Type::OBJ, "xxxx", "name of the softfork", + { + {RPCResult::Type::STR, "type", "one of \"buried\", \"bip9\""}, + {RPCResult::Type::OBJ, "bip9", "status of bip9 softforks (only for \"bip9\" type)", + { + {RPCResult::Type::STR, "status", "one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\""}, + {RPCResult::Type::NUM, "bit", "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)"}, + {RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"}, + {RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"}, + {RPCResult::Type::NUM, "since", "height of the first block to which the status applies"}, + {RPCResult::Type::OBJ, "statistics", "numeric statistics about BIP9 signalling for a softfork", + { + {RPCResult::Type::NUM, "period", "the length in blocks of the BIP9 signalling period"}, + {RPCResult::Type::NUM, "threshold", "the number of blocks with the version bit set required to activate the feature"}, + {RPCResult::Type::NUM, "elapsed", "the number of blocks elapsed since the beginning of the current period"}, + {RPCResult::Type::NUM, "count", "the number of blocks with the version bit set in the current period"}, + {RPCResult::Type::BOOL, "possible", "returns false if there are not enough blocks left in this period to pass activation threshold"}, + }}, + }}, + {RPCResult::Type::NUM, "height", "height of the first block which the rules are or will be enforced (only for \"buried\" type, or \"bip9\" type with \"active\" status)"}, + {RPCResult::Type::BOOL, "active", "true if the rules are enforced for the mempool and the next block"}, + }}, + }}, + {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, + }}, RPCExamples{ HelpExampleCli("getblockchaininfo", "") + HelpExampleRpc("getblockchaininfo", "") @@ -1315,27 +1294,20 @@ static UniValue getchaintips(const JSONRPCRequest& request) " including the main chain as well as orphaned branches.\n", {}, RPCResult{ - "[\n" - " {\n" - " \"height\" : xxxx, (numeric) height of the chain tip\n" - " \"hash\" : \"xxxx\", (string) block hash of the tip\n" - " \"branchlen\" : 0 (numeric) zero for main chain\n" - " \"status\" : \"active\" (string) \"active\" for the main chain\n" - " },\n" - " {\n" - " \"height\" : xxxx,\n" - " \"hash\" : \"xxxx\",\n" - " \"branchlen\" : 1 (numeric) length of branch connecting the tip to the main chain\n" - " \"status\" : \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" - " }\n" - "]\n" + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "height", "height of the chain tip"}, + {RPCResult::Type::STR_HEX, "hash", "block hash of the tip"}, + {RPCResult::Type::NUM, "branchlen", "zero for main chain, otherwise length of branch connecting the tip to the main chain"}, + {RPCResult::Type::STR, "status", "status of the chain, \"active\" for the main chain\n" "Possible values for status:\n" "1. \"invalid\" This branch contains at least one invalid block\n" "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" - "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" - }, + "5. \"active\" This is the tip of the active main chain, which is certainly valid"}, + }}}}, RPCExamples{ HelpExampleCli("getchaintips", "") + HelpExampleRpc("getchaintips", "") @@ -1435,16 +1407,16 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request) "\nReturns details on the active state of the TX memory pool.\n", {}, RPCResult{ - "{\n" - " \"loaded\" : true|false (boolean) True if the mempool is fully loaded\n" - " \"size\" : xxxxx, (numeric) Current tx count\n" - " \"bytes\" : xxxxx, (numeric) Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted\n" - " \"usage\" : xxxxx, (numeric) Total memory usage for the mempool\n" - " \"maxmempool\" : xxxxx, (numeric) Maximum memory usage for the mempool\n" - " \"mempoolminfee\" : xxxxx (numeric) Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee\n" - " \"minrelaytxfee\" : xxxxx (numeric) Current minimum relay fee for transactions\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "loaded", "True if the mempool is fully loaded"}, + {RPCResult::Type::NUM, "size", "Current tx count"}, + {RPCResult::Type::NUM, "bytes", "Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted"}, + {RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"}, + {RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"}, + {RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"}, + {RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"}, + }}, RPCExamples{ HelpExampleCli("getmempoolinfo", "") + HelpExampleRpc("getmempoolinfo", "") @@ -1575,17 +1547,17 @@ static UniValue getchaintxstats(const JSONRPCRequest& request) {"blockhash", RPCArg::Type::STR_HEX, /* default */ "chain tip", "The hash of the block that ends the window."}, }, RPCResult{ - "{\n" - " \"time\" : xxxxx, (numeric) The timestamp for the final block in the window, expressed in " + UNIX_EPOCH_TIME + ".\n" - " \"txcount\" : xxxxx, (numeric) The total number of transactions in the chain up to that point.\n" - " \"window_final_block_hash\" : \"...\", (string) The hash of the final block in the window.\n" - " \"window_final_block_height\" : xxxxx, (numeric) The height of the final block in the window.\n" - " \"window_block_count\" : xxxxx, (numeric) Size of the window in number of blocks.\n" - " \"window_tx_count\" : xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n" - " \"window_interval\" : xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n" - " \"txrate\" : x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM_TIME, "time", "The timestamp for the final block in the window, expressed in " + UNIX_EPOCH_TIME}, + {RPCResult::Type::NUM, "txcount", "The total number of transactions in the chain up to that point"}, + {RPCResult::Type::STR_HEX, "window_final_block_hash", "The hash of the final block in the window"}, + {RPCResult::Type::NUM, "window_final_block_height", "The height of the final block in the window."}, + {RPCResult::Type::NUM, "window_block_count", "Size of the window in number of blocks"}, + {RPCResult::Type::NUM, "window_tx_count", "The number of transactions in the window. Only returned if \"window_block_count\" is > 0"}, + {RPCResult::Type::NUM, "window_interval", "The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0"}, + {RPCResult::Type::NUM, "txrate", "The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0"}, + }}, RPCExamples{ HelpExampleCli("getchaintxstats", "") + HelpExampleRpc("getchaintxstats", "2016") @@ -1714,44 +1686,45 @@ static UniValue getblockstats(const JSONRPCRequest& request) "stats"}, }, RPCResult{ - "{ (json object)\n" - " \"avgfee\" : xxxxx, (numeric) Average fee in the block\n" - " \"avgfeerate\" : xxxxx, (numeric) Average feerate (in satoshis per virtual byte)\n" - " \"avgtxsize\" : xxxxx, (numeric) Average transaction size\n" - " \"blockhash\" : xxxxx, (string) The block hash (to check for potential reorgs)\n" - " \"feerate_percentiles\" : [ (array of numeric) Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)\n" - " \"10th_percentile_feerate\", (numeric) The 10th percentile feerate\n" - " \"25th_percentile_feerate\", (numeric) The 25th percentile feerate\n" - " \"50th_percentile_feerate\", (numeric) The 50th percentile feerate\n" - " \"75th_percentile_feerate\", (numeric) The 75th percentile feerate\n" - " \"90th_percentile_feerate\", (numeric) The 90th percentile feerate\n" - " ],\n" - " \"height\" : xxxxx, (numeric) The height of the block\n" - " \"ins\" : xxxxx, (numeric) The number of inputs (excluding coinbase)\n" - " \"maxfee\" : xxxxx, (numeric) Maximum fee in the block\n" - " \"maxfeerate\" : xxxxx, (numeric) Maximum feerate (in satoshis per virtual byte)\n" - " \"maxtxsize\" : xxxxx, (numeric) Maximum transaction size\n" - " \"medianfee\" : xxxxx, (numeric) Truncated median fee in the block\n" - " \"mediantime\" : xxxxx, (numeric) The block median time past\n" - " \"mediantxsize\" : xxxxx, (numeric) Truncated median transaction size\n" - " \"minfee\" : xxxxx, (numeric) Minimum fee in the block\n" - " \"minfeerate\" : xxxxx, (numeric) Minimum feerate (in satoshis per virtual byte)\n" - " \"mintxsize\" : xxxxx, (numeric) Minimum transaction size\n" - " \"outs\" : xxxxx, (numeric) The number of outputs\n" - " \"subsidy\" : xxxxx, (numeric) The block subsidy\n" - " \"swtotal_size\" : xxxxx, (numeric) Total size of all segwit transactions\n" - " \"swtotal_weight\" : xxxxx, (numeric) Total weight of all segwit transactions divided by segwit scale factor (4)\n" - " \"swtxs\" : xxxxx, (numeric) The number of segwit transactions\n" - " \"time\" : xxxxx, (numeric) The block time\n" - " \"total_out\" : xxxxx, (numeric) Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])\n" - " \"total_size\" : xxxxx, (numeric) Total size of all non-coinbase transactions\n" - " \"total_weight\" : xxxxx, (numeric) Total weight of all non-coinbase transactions divided by segwit scale factor (4)\n" - " \"totalfee\" : xxxxx, (numeric) The fee total\n" - " \"txs\" : xxxxx, (numeric) The number of transactions (excluding coinbase)\n" - " \"utxo_increase\" : xxxxx, (numeric) The increase/decrease in the number of unspent outputs\n" - " \"utxo_size_inc\" : xxxxx, (numeric) The increase/decrease in size for the utxo index (not discounting op_return and similar)\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "avgfee", "Average fee in the block"}, + {RPCResult::Type::NUM, "avgfeerate", "Average feerate (in satoshis per virtual byte)"}, + {RPCResult::Type::NUM, "avgtxsize", "Average transaction size"}, + {RPCResult::Type::STR_HEX, "blockhash", "The block hash (to check for potential reorgs)"}, + {RPCResult::Type::ARR_FIXED, "feerate_percentiles", "Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte)", + { + {RPCResult::Type::NUM, "10th_percentile_feerate", "The 10th percentile feerate"}, + {RPCResult::Type::NUM, "25th_percentile_feerate", "The 25th percentile feerate"}, + {RPCResult::Type::NUM, "50th_percentile_feerate", "The 50th percentile feerate"}, + {RPCResult::Type::NUM, "75th_percentile_feerate", "The 75th percentile feerate"}, + {RPCResult::Type::NUM, "90th_percentile_feerate", "The 90th percentile feerate"}, + }}, + {RPCResult::Type::NUM, "height", "The height of the block"}, + {RPCResult::Type::NUM, "ins", "The number of inputs (excluding coinbase)"}, + {RPCResult::Type::NUM, "maxfee", "Maximum fee in the block"}, + {RPCResult::Type::NUM, "maxfeerate", "Maximum feerate (in satoshis per virtual byte)"}, + {RPCResult::Type::NUM, "maxtxsize", "Maximum transaction size"}, + {RPCResult::Type::NUM, "medianfee", "Truncated median fee in the block"}, + {RPCResult::Type::NUM, "mediantime", "The block median time past"}, + {RPCResult::Type::NUM, "mediantxsize", "Truncated median transaction size"}, + {RPCResult::Type::NUM, "minfee", "Minimum fee in the block"}, + {RPCResult::Type::NUM, "minfeerate", "Minimum feerate (in satoshis per virtual byte)"}, + {RPCResult::Type::NUM, "mintxsize", "Minimum transaction size"}, + {RPCResult::Type::NUM, "outs", "The number of outputs"}, + {RPCResult::Type::NUM, "subsidy", "The block subsidy"}, + {RPCResult::Type::NUM, "swtotal_size", "Total size of all segwit transactions"}, + {RPCResult::Type::NUM, "swtotal_weight", "Total weight of all segwit transactions divided by segwit scale factor (4)"}, + {RPCResult::Type::NUM, "swtxs", "The number of segwit transactions"}, + {RPCResult::Type::NUM, "time", "The block time"}, + {RPCResult::Type::NUM, "total_out", "Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"}, + {RPCResult::Type::NUM, "total_size", "Total size of all non-coinbase transactions"}, + {RPCResult::Type::NUM, "total_weight", "Total weight of all non-coinbase transactions divided by segwit scale factor (4)"}, + {RPCResult::Type::NUM, "totalfee", "The fee total"}, + {RPCResult::Type::NUM, "txs", "The number of transactions (excluding coinbase)"}, + {RPCResult::Type::NUM, "utxo_increase", "The increase/decrease in the number of unspent outputs"}, + {RPCResult::Type::NUM, "utxo_size_inc", "The increase/decrease in size for the utxo index (not discounting op_return and similar)"}, + }}, RPCExamples{ HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'") + HelpExampleRpc("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'") @@ -2074,24 +2047,26 @@ UniValue scantxoutset(const JSONRPCRequest& request) "[scanobjects,...]"}, }, RPCResult{ - "{\n" - " \"success\" : true|false, (boolean) Whether the scan was completed\n" - " \"txouts\" : n, (numeric) The number of unspent transaction outputs scanned\n" - " \"height\" : n, (numeric) The current block height (index)\n" - " \"bestblock\" : \"hex\", (string) The hash of the block at the tip of the chain\n" - " \"unspents\" : [\n" - " {\n" - " \"txid\" : \"hash\", (string) The transaction id\n" - " \"vout\" : n, (numeric) The vout value\n" - " \"scriptPubKey\" : \"script\", (string) The script key\n" - " \"desc\" : \"descriptor\", (string) A specialized descriptor for the matched scriptPubKey\n" - " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " of the unspent output\n" - " \"height\" : n, (numeric) Height of the unspent transaction output\n" - " }\n" - " ,...],\n" - " \"total_amount\" : x.xxx, (numeric) The total amount of all found unspent outputs in " + CURRENCY_UNIT + "\n" - "]\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "success", "Whether the scan was completed"}, + {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs scanned"}, + {RPCResult::Type::NUM, "height", "The current block height (index)"}, + {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"}, + {RPCResult::Type::ARR, "unspents", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + {RPCResult::Type::NUM, "vout", "The vout value"}, + {RPCResult::Type::STR_HEX, "scriptPubKey", "The script key"}, + {RPCResult::Type::STR, "desc", "A specialized descriptor for the matched scriptPubKey"}, + {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the unspent output"}, + {RPCResult::Type::NUM, "height", "Height of the unspent transaction output"}, + }}, + }}, + {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of all found unspent outputs in " + CURRENCY_UNIT}, + }}, RPCExamples{""}, }.Check(request); @@ -2197,11 +2172,11 @@ static UniValue getblockfilter(const JSONRPCRequest& request) {"filtertype", RPCArg::Type::STR, /*default*/ "basic", "The type name of the filter"}, }, RPCResult{ - "{\n" - " \"filter\" : (string) the hex-encoded filter data\n" - " \"header\" : (string) the hex-encoded filter header\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "filter", "the hex-encoded filter data"}, + {RPCResult::Type::STR_HEX, "header", "the hex-encoded filter header"}, + }}, RPCExamples{ HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"") } @@ -2282,12 +2257,13 @@ UniValue dumptxoutset(const JSONRPCRequest& request) "path to the output file. If relative, will be prefixed by datadir."}, }, RPCResult{ - "{\n" - " \"coins_written\" : n, (numeric) the number of coins written in the snapshot\n" - " \"base_hash\" : \"...\", (string) the hash of the base of the snapshot\n" - " \"base_height\" : n, (string) the height of the base of the snapshot\n" - " \"path\" : \"...\" (string) the absolute path that the snapshot was written to\n" - "]\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "coins_written", "the number of coins written in the snapshot"}, + {RPCResult::Type::STR_HEX, "base_hash", "the hash of the base of the snapshot"}, + {RPCResult::Type::NUM, "base_height", "the height of the base of the snapshot"}, + {RPCResult::Type::STR, "path", "the absolute path that the snapshot was written to"}, + } }, RPCExamples{ HelpExampleCli("dumptxoutset", "utxo.dat") diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 5bfdcd6555..9245d09b89 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -89,8 +89,7 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request) {"height", RPCArg::Type::NUM, /* default */ "-1", "To estimate at the time of the given height."}, }, RPCResult{ - "x (numeric) Hashes per second estimated\n" - }, + RPCResult::Type::NUM, "", "Hashes per second estimated"}, RPCExamples{ HelpExampleCli("getnetworkhashps", "") + HelpExampleRpc("getnetworkhashps", "") @@ -153,7 +152,11 @@ static UniValue generatetodescriptor(const JSONRPCRequest& request) {"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."}, }, RPCResult{ - "[ blockhashes ] (json array) hashes of blocks generated\n"}, + RPCResult::Type::ARR, "", "hashes of blocks generated", + { + {RPCResult::Type::STR_HEX, "", "blockhash"}, + } + }, RPCExamples{ "\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")}, } @@ -195,8 +198,10 @@ static UniValue generatetoaddress(const JSONRPCRequest& request) {"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."}, }, RPCResult{ - "[ blockhashes ] (json array) hashes of blocks generated\n" - }, + RPCResult::Type::ARR, "", "hashes of blocks generated", + { + {RPCResult::Type::STR_HEX, "", "blockhash"}, + }}, RPCExamples{ "\nGenerate 11 blocks to myaddress\n" + HelpExampleCli("generatetoaddress", "11 \"myaddress\"") @@ -229,17 +234,17 @@ static UniValue getmininginfo(const JSONRPCRequest& request) "\nReturns a json object containing mining-related information.", {}, RPCResult{ - "{\n" - " \"blocks\" : nnn, (numeric) The current block\n" - " \"currentblockweight\" : nnn, (numeric, optional) The block weight of the last assembled block (only present if a block was ever assembled)\n" - " \"currentblocktx\" : nnn, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)\n" - " \"difficulty\" : xxx.xxxxx (numeric) The current difficulty\n" - " \"networkhashps\" : nnn, (numeric) The network hashes per second\n" - " \"pooledtx\" : n (numeric) The size of the mempool\n" - " \"chain\" : \"xxxx\", (string) current network name (main, test, regtest)\n" - " \"warnings\" : \"...\" (string) any network and blockchain warnings\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "blocks", "The current block"}, + {RPCResult::Type::NUM, "currentblockweight", /* optional */ true, "The block weight of the last assembled block (only present if a block was ever assembled)"}, + {RPCResult::Type::NUM, "currentblocktx", /* optional */ true, "The number of block transactions of the last assembled block (only present if a block was ever assembled)"}, + {RPCResult::Type::NUM, "difficulty", "The current difficulty"}, + {RPCResult::Type::NUM, "networkhashps", "The network hashes per second"}, + {RPCResult::Type::NUM, "pooledtx", "The size of the mempool"}, + {RPCResult::Type::STR, "chain", "current network name (main, test, regtest)"}, + {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, + }}, RPCExamples{ HelpExampleCli("getmininginfo", "") + HelpExampleRpc("getmininginfo", "") @@ -277,8 +282,7 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request) " considers the transaction as it would have paid a higher (or lower) fee."}, }, RPCResult{ - "true (boolean) Returns true\n" - }, + RPCResult::Type::BOOL, "", "Returns true"}, RPCExamples{ HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000") + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000") @@ -355,48 +359,58 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) "\"template_request\""}, }, RPCResult{ - "{\n" - " \"version\" : n, (numeric) The preferred block version\n" - " \"rules\" : [ \"rulename\", ... ], (array of strings) specific block rules that are to be enforced\n" - " \"vbavailable\" : { (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n" - " \"rulename\" : bitnumber (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n" - " ,...\n" - " },\n" - " \"vbrequired\" : n, (numeric) bit mask of versionbits the server requires set in submissions\n" - " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n" - " \"transactions\" : [ (json array) contents of non-coinbase transactions that should be included in the next block\n" - " {\n" - " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n" - " \"txid\" : \"xxxx\", (string) transaction id encoded in little-endian hexadecimal\n" - " \"hash\" : \"xxxx\", (string) hash encoded in little-endian hexadecimal (including witness data)\n" - " \"depends\" : [ (json array) array of numbers \n" - " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n" - " ,...\n" - " ],\n" - " \"fee\" : n, (numeric) difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n" - " \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n" - " \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n" - " }\n" - " ,...\n" - " ],\n" - " \"coinbaseaux\" : { ... }, (json object) data that should be included in the coinbase's scriptSig content\n" - " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)\n" - " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" - " \"target\" : \"xxxx\", (string) The hash target\n" - " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for the next block time, expressed in " + UNIX_EPOCH_TIME + "\n" - " \"mutable\" : [ (array of string) list of ways the block template may be changed \n" - " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n" - " ,...\n" - " ],\n" - " \"noncerange\" : \"00000000ffffffff\",(string) A range of valid nonces\n" - " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n" - " \"sizelimit\" : n, (numeric) limit of block size\n" - " \"weightlimit\" : n, (numeric) limit of block weight\n" - " \"curtime\" : ttt, (numeric) current timestamp in " + UNIX_EPOCH_TIME + "\n" - " \"bits\" : \"xxxxxxxx\", (string) compressed target of next block\n" - " \"height\" : n (numeric) The height of the next block\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "version", "The preferred block version"}, + {RPCResult::Type::ARR, "rules", "specific block rules that are to be enforced", + { + {RPCResult::Type::STR, "", "rulename"}, + }}, + {RPCResult::Type::OBJ_DYN, "vbavailable", "set of pending, supported versionbit (BIP 9) softfork deployments", + { + {RPCResult::Type::NUM, "rulename", "identifies the bit number as indicating acceptance and readiness for the named softfork rule"}, + }}, + {RPCResult::Type::NUM, "vbrequired", "bit mask of versionbits the server requires set in submissions"}, + {RPCResult::Type::STR, "previousblockhash", "The hash of current highest block"}, + {RPCResult::Type::ARR, "", "contents of non-coinbase transactions that should be included in the next block", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "data", "transaction data encoded in hexadecimal (byte-for-byte)"}, + {RPCResult::Type::STR_HEX, "txid", "transaction id encoded in little-endian hexadecimal"}, + {RPCResult::Type::STR_HEX, "hash", "hash encoded in little-endian hexadecimal (including witness data)"}, + {RPCResult::Type::ARR, "depends", "array of numbers", + { + {RPCResult::Type::NUM, "", "transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is"}, + }}, + {RPCResult::Type::NUM, "fee", "difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one"}, + {RPCResult::Type::NUM, "sigops", "total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero"}, + {RPCResult::Type::NUM, "weight", "total transaction weight, as counted for purposes of block limits"}, + }}, + }}, + {RPCResult::Type::OBJ, "coinbaseaux", "data that should be included in the coinbase's scriptSig content", + { + {RPCResult::Type::ELISION, "", ""}, + }}, + {RPCResult::Type::NUM, "coinbasevalue", "maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)"}, + {RPCResult::Type::OBJ, "coinbasetxn", "information for coinbase transaction", + { + {RPCResult::Type::ELISION, "", ""}, + }}, + {RPCResult::Type::STR, "target", "The hash target"}, + {RPCResult::Type::NUM_TIME, "mintime", "The minimum timestamp appropriate for the next block time, expressed in " + UNIX_EPOCH_TIME}, + {RPCResult::Type::ARR, "mutable", "list of ways the block template may be changed", + { + {RPCResult::Type::STR, "value", "A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'"}, + }}, + {RPCResult::Type::STR_HEX, "noncerange", "A range of valid nonces"}, + {RPCResult::Type::NUM, "sigoplimit", "limit of sigops in blocks"}, + {RPCResult::Type::NUM, "sizelimit", "limit of block size"}, + {RPCResult::Type::NUM, "weightlimit", "limit of block weight"}, + {RPCResult::Type::NUM_TIME, "curtime", "current timestamp in " + UNIX_EPOCH_TIME}, + {RPCResult::Type::STR, "bits", "compressed target of next block"}, + {RPCResult::Type::NUM, "height", "The height of the next block"}, + }}, RPCExamples{ HelpExampleCli("getblocktemplate", "'{\"rules\": [\"segwit\"]}'") + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}") @@ -799,8 +813,7 @@ static UniValue submitheader(const JSONRPCRequest& request) {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"}, }, RPCResult{ - "None" - }, + RPCResult::Type::NONE, "", "None"}, RPCExamples{ HelpExampleCli("submitheader", "\"aabbcc\"") + HelpExampleRpc("submitheader", "\"aabbcc\"") @@ -847,17 +860,19 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request) " \"CONSERVATIVE\""}, }, RPCResult{ - "{\n" - " \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n" - " \"errors\" : [ str... ] (json array of strings, optional) Errors encountered during processing\n" - " \"blocks\" : n (numeric) block number where estimate was found\n" - "}\n" - "\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "feerate", /* optional */ true, "estimate fee rate in " + CURRENCY_UNIT + "/kB (only present if no errors were encountered)"}, + {RPCResult::Type::ARR, "errors", "Errors encountered during processing", + { + {RPCResult::Type::STR, "", "error"}, + }}, + {RPCResult::Type::NUM, "blocks", "block number where estimate was found\n" "The request target will be clamped between 2 and the highest target\n" "fee estimation is able to return based on how long it has been running.\n" "An error is returned if not enough transactions and blocks\n" - "have been observed to make an estimate for any number of blocks.\n" - }, + "have been observed to make an estimate for any number of blocks."}, + }}, RPCExamples{ HelpExampleCli("estimatesmartfee", "6") }, @@ -907,36 +922,40 @@ static UniValue estimaterawfee(const JSONRPCRequest& request) " lower buckets."}, }, RPCResult{ - "{ (json object) Results are returned for any horizon which tracks blocks up to the confirmation target\n" - " \"short\" : { (json object, optional) estimate for short time horizon\n" - " \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n" - " \"decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n" - " \"scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n" - " \"pass\" : { (json object, optional) information about the lowest range of feerates to succeed in meeting the threshold\n" - " \"startrange\" : x.x, (numeric) start of feerate range\n" - " \"endrange\" : x.x, (numeric) end of feerate range\n" - " \"withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n" - " \"totalconfirmed\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed at any point\n" - " \"inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n" - " \"leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n" - " },\n" - " \"fail\" : { (json object, optional) information about the highest range of feerates to fail to meet the threshold\n" - " ...\n" - " },\n" - " \"errors\" : [ (json array, optional) Errors encountered during processing\n" - " \"str\", (string)\n" - " ...\n" - " ],\n" - " },\n" - " \"medium\" : { (json object, optional) estimate for medium time horizon\n" - " ...\n" - " },\n" - " \"long\" : { (json object, optional) estimate for long time horizon\n" - " ...\n" - " },\n" - "}\n" - "\n" - }, + RPCResult::Type::OBJ, "", "Results are returned for any horizon which tracks blocks up to the confirmation target", + { + {RPCResult::Type::OBJ, "short", /* optional */ true, "estimate for short time horizon", + { + {RPCResult::Type::NUM, "feerate", /* optional */ true, "estimate fee rate in " + CURRENCY_UNIT + "/kB"}, + {RPCResult::Type::NUM, "decay", "exponential decay (per block) for historical moving average of confirmation data"}, + {RPCResult::Type::NUM, "scale", "The resolution of confirmation targets at this time horizon"}, + {RPCResult::Type::OBJ, "pass", /* optional */ true, "information about the lowest range of feerates to succeed in meeting the threshold", + { + {RPCResult::Type::NUM, "startrange", "start of feerate range"}, + {RPCResult::Type::NUM, "endrange", "end of feerate range"}, + {RPCResult::Type::NUM, "withintarget", "number of txs over history horizon in the feerate range that were confirmed within target"}, + {RPCResult::Type::NUM, "totalconfirmed", "number of txs over history horizon in the feerate range that were confirmed at any point"}, + {RPCResult::Type::NUM, "inmempool", "current number of txs in mempool in the feerate range unconfirmed for at least target blocks"}, + {RPCResult::Type::NUM, "leftmempool", "number of txs over history horizon in the feerate range that left mempool unconfirmed after target"}, + }}, + {RPCResult::Type::OBJ, "fail", /* optional */ true, "information about the highest range of feerates to fail to meet the threshold", + { + {RPCResult::Type::ELISION, "", ""}, + }}, + {RPCResult::Type::ARR, "errors", /* optional */ true, "Errors encountered during processing", + { + {RPCResult::Type::STR, "error", ""}, + }}, + }}, + {RPCResult::Type::OBJ, "medium", /* optional */ true, "estimate for medium time horizon", + { + {RPCResult::Type::ELISION, "", ""}, + }}, + {RPCResult::Type::OBJ, "long", /* optional */ true, "estimate for long time horizon", + { + {RPCResult::Type::ELISION, "", ""}, + }}, + }}, RPCExamples{ HelpExampleCli("estimaterawfee", "6 0.9") }, diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 4279756f4d..ccfdfe4340 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -33,15 +33,16 @@ static UniValue validateaddress(const JSONRPCRequest& request) {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to validate"}, }, RPCResult{ - "{\n" - " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" - " \"address\" : \"address\", (string) The bitcoin address validated\n" - " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n" - " \"isscript\" : true|false, (boolean) If the key is a script\n" - " \"iswitness\" : true|false, (boolean) If the address is a witness address\n" - " \"witness_version\" : version (numeric, optional) The version number of the witness program\n" - " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "isvalid", "If the address is valid or not. If not, this is the only property returned."}, + {RPCResult::Type::STR, "address", "The bitcoin address validated"}, + {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address"}, + {RPCResult::Type::BOOL, "isscript", "If the key is a script"}, + {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address"}, + {RPCResult::Type::NUM, "witness_version", /* optional */ true, "The version number of the witness program"}, + {RPCResult::Type::STR_HEX, "witness_program", /* optional */ true, "The hex value of the witness program"}, + } }, RPCExamples{ HelpExampleCli("validateaddress", EXAMPLE_ADDRESS) + @@ -82,11 +83,12 @@ static UniValue createmultisig(const JSONRPCRequest& request) {"address_type", RPCArg::Type::STR, /* default */ "legacy", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, }, RPCResult{ - "{\n" - " \"address\" : \"multisigaddress\", (string) The value of the new multisig address.\n" - " \"redeemScript\" : \"script\" (string) The string value of the hex-encoded redemption script.\n" - " \"descriptor\" : \"descriptor\" (string) The descriptor for this multisig\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", "The value of the new multisig address."}, + {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script."}, + {RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"}, + } }, RPCExamples{ "\nCreate a multisig address from 2 public keys\n" @@ -141,13 +143,14 @@ UniValue getdescriptorinfo(const JSONRPCRequest& request) {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."}, }, RPCResult{ - "{\n" - " \"descriptor\" : \"desc\", (string) The descriptor in canonical form, without private keys\n" - " \"checksum\" : \"chksum\", (string) The checksum for the input descriptor\n" - " \"isrange\" : true|false, (boolean) Whether the descriptor is ranged\n" - " \"issolvable\" : true|false, (boolean) Whether the descriptor is solvable\n" - " \"hasprivatekeys\" : true|false, (boolean) Whether the input descriptor contained at least one private key\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "descriptor", "The descriptor in canonical form, without private keys"}, + {RPCResult::Type::STR, "checksum", "The checksum for the input descriptor"}, + {RPCResult::Type::BOOL, "isrange", "Whether the descriptor is ranged"}, + {RPCResult::Type::BOOL, "issolvable", "Whether the descriptor is solvable"}, + {RPCResult::Type::BOOL, "hasprivatekeys", "Whether the input descriptor contained at least one private key"}, + } }, RPCExamples{ "Analyse a descriptor\n" + @@ -189,7 +192,10 @@ UniValue deriveaddresses(const JSONRPCRequest& request) {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."}, }, RPCResult{ - "[ address ] (json array) the derived addresses\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::STR, "address", "the derived addresses"}, + } }, RPCExamples{ "First three native segwit receive addresses\n" + @@ -258,7 +264,7 @@ static UniValue verifymessage(const JSONRPCRequest& request) {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."}, }, RPCResult{ - "true|false (boolean) If the signature is verified or not.\n" + RPCResult::Type::BOOL, "", "If the signature is verified or not." }, RPCExamples{ "\nUnlock the wallet for 30 seconds\n" @@ -304,7 +310,7 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request) {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."}, }, RPCResult{ - "\"signature\" (string) The signature of the message encoded in base 64\n" + RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64" }, RPCExamples{ "\nCreate the signature\n" @@ -437,19 +443,21 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request) }, { RPCResult{"mode \"stats\"", - "{\n" - " \"locked\" : { (json object) Information about locked memory manager\n" - " \"used\" : xxxxx, (numeric) Number of bytes used\n" - " \"free\" : xxxxx, (numeric) Number of bytes available in current arenas\n" - " \"total\" : xxxxxxx, (numeric) Total number of bytes managed\n" - " \"locked\" : xxxxxx, (numeric) Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk.\n" - " \"chunks_used\" : xxxxx, (numeric) Number allocated chunks\n" - " \"chunks_free\" : xxxxx, (numeric) Number unused chunks\n" - " }\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ, "locked", "Information about locked memory manager", + { + {RPCResult::Type::NUM, "used", "Number of bytes used"}, + {RPCResult::Type::NUM, "free", "Number of bytes available in current arenas"}, + {RPCResult::Type::NUM, "total", "Total number of bytes managed"}, + {RPCResult::Type::NUM, "locked", "Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk."}, + {RPCResult::Type::NUM, "chunks_used", "Number allocated chunks"}, + {RPCResult::Type::NUM, "chunks_free", "Number unused chunks"}, + }}, + } }, RPCResult{"mode \"mallocinfo\"", - "\"<malloc version=\"1\">...\"\n" + RPCResult::Type::STR, "", "\"<malloc version=\"1\">...\"" }, }, RPCExamples{ @@ -516,10 +524,10 @@ UniValue logging(const JSONRPCRequest& request) }}, }, RPCResult{ - "{ (json object where keys are the logging categories, and values indicates its status\n" - " \"category\" : true|false, (boolean) if being debug logged or not. false:inactive, true:active\n" - " ...\n" - "}\n" + RPCResult::Type::OBJ_DYN, "", "keys are the logging categories, and values indicates its status", + { + {RPCResult::Type::BOOL, "category", "if being debug logged or not. false:inactive, true:active"}, + } }, RPCExamples{ HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 92542539df..482c689285 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -33,7 +33,7 @@ static UniValue getconnectioncount(const JSONRPCRequest& request) "\nReturns the number of connections to other nodes.\n", {}, RPCResult{ - "n (numeric) The connection count\n" + RPCResult::Type::NUM, "", "The connection count" }, RPCExamples{ HelpExampleCli("getconnectioncount", "") @@ -77,57 +77,59 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) "\nReturns data about each connected network node as a json array of objects.\n", {}, RPCResult{ - "[\n" - " {\n" - " \"id\" : n, (numeric) Peer index\n" - " \"addr\" : \"host:port\", (string) The IP address and port of the peer\n" - " \"addrbind\" : \"ip:port\", (string) Bind address of the connection to the peer\n" - " \"addrlocal\" : \"ip:port\", (string) Local address as reported by the peer\n" - " \"mapped_as\" : \"mapped_as\", (string) The AS in the BGP route to the peer used for diversifying peer selection\n" - " \"services\" : \"xxxxxxxxxxxxxxxx\", (string) The services offered\n" - " \"servicesnames\" : [ (json array) the services offered, in human-readable form\n" - " \"SERVICE_NAME\", (string) the service name if it is recognised\n" - " ...\n" - " ],\n" - " \"relaytxes\" : true|false, (boolean) Whether peer has asked us to relay transactions to it\n" - " \"lastsend\" : ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the last send\n" - " \"lastrecv\" : ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the last receive\n" - " \"bytessent\" : n, (numeric) The total bytes sent\n" - " \"bytesrecv\" : n, (numeric) The total bytes received\n" - " \"conntime\" : ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the connection\n" - " \"timeoffset\" : ttt, (numeric) The time offset in seconds\n" - " \"pingtime\" : n, (numeric) ping time (if available)\n" - " \"minping\" : n, (numeric) minimum observed ping time (if any at all)\n" - " \"pingwait\" : n, (numeric) ping wait (if non-zero)\n" - " \"version\" : v, (numeric) The peer version, such as 70001\n" - " \"subver\" : \"/Satoshi:0.8.5/\", (string) The string version\n" - " \"inbound\" : true|false, (boolean) Inbound (true) or Outbound (false)\n" - " \"addnode\" : true|false, (boolean) Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n" - " \"startingheight\" : n, (numeric) The starting height (block) of the peer\n" - " \"banscore\" : n, (numeric) The ban score\n" - " \"synced_headers\" : n, (numeric) The last header we have in common with this peer\n" - " \"synced_blocks\" : n, (numeric) The last block we have in common with this peer\n" - " \"inflight\" : [\n" - " n, (numeric) The heights of blocks we're currently asking from this peer\n" - " ...\n" - " ],\n" - " \"whitelisted\" : true|false, (boolean) Whether the peer is whitelisted\n" - " \"minfeefilter\" : n, (numeric) The minimum fee rate for transactions this peer accepts\n" - " \"bytessent_per_msg\" : {\n" - " \"msg\" : n, (numeric) The total bytes sent aggregated by message type\n" - " When a message type is not listed in this json object, the bytes sent are 0.\n" - " Only known message types can appear as keys in the object.\n" - " ...\n" - " },\n" - " \"bytesrecv_per_msg\" : {\n" - " \"msg\" : n, (numeric) The total bytes received aggregated by message type\n" - " When a message type is not listed in this json object, the bytes received are 0.\n" - " Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'.\n" - " ...\n" - " }\n" - " }\n" - " ,...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + { + {RPCResult::Type::NUM, "id", "Peer index"}, + {RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"}, + {RPCResult::Type::STR, "addrbind", "(ip:port) Bind address of the connection to the peer"}, + {RPCResult::Type::STR, "addrlocal", "(ip:port) Local address as reported by the peer"}, + {RPCResult::Type::STR, "mapped_as", "The AS in the BGP route to the peer used for diversifying peer selection"}, + {RPCResult::Type::STR_HEX, "services", "The services offered"}, + {RPCResult::Type::ARR, "servicesnames", "the services offered, in human-readable form", + { + {RPCResult::Type::STR, "SERVICE_NAME", "the service name if it is recognised"} + }}, + {RPCResult::Type::BOOL, "relaytxes", "Whether peer has asked us to relay transactions to it"}, + {RPCResult::Type::NUM_TIME, "lastsend", "The " + UNIX_EPOCH_TIME + " of the last send"}, + {RPCResult::Type::NUM_TIME, "lastrecv", "The " + UNIX_EPOCH_TIME + " of the last receive"}, + {RPCResult::Type::NUM, "bytessent", "The total bytes sent"}, + {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"}, + {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"}, + {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"}, + {RPCResult::Type::NUM, "pingtime", "ping time (if available)"}, + {RPCResult::Type::NUM, "minping", "minimum observed ping time (if any at all)"}, + {RPCResult::Type::NUM, "pingwait", "ping wait (if non-zero)"}, + {RPCResult::Type::NUM, "version", "The peer version, such as 70001"}, + {RPCResult::Type::STR, "subver", "The string version"}, + {RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"}, + {RPCResult::Type::BOOL, "addnode", "Whether connection was due to addnode/-connect or if it was an automatic/inbound connection"}, + {RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"}, + {RPCResult::Type::NUM, "banscore", "The ban score"}, + {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"}, + {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"}, + {RPCResult::Type::ARR, "inflight", "", + { + {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"}, + }}, + {RPCResult::Type::BOOL, "whitelisted", "Whether the peer is whitelisted"}, + {RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"}, + {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "", + { + {RPCResult::Type::NUM, "msg", "The total bytes sent aggregated by message type\n" + "When a message type is not listed in this json object, the bytes sent are 0.\n" + "Only known message types can appear as keys in the object."} + }}, + {RPCResult::Type::OBJ, "bytesrecv_per_msg", "", + { + {RPCResult::Type::NUM, "msg", "The total bytes received aggregated by message type\n" + "When a message type is not listed in this json object, the bytes received are 0.\n" + "Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'."} + }}, + }}, + }}, }, RPCExamples{ HelpExampleCli("getpeerinfo", "") @@ -320,19 +322,22 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request) {"node", RPCArg::Type::STR, /* default */ "all nodes", "If provided, return information about this specific node, otherwise all nodes are returned."}, }, RPCResult{ - "[\n" - " {\n" - " \"addednode\" : \"192.168.0.201\", (string) The node IP address or name (as provided to addnode)\n" - " \"connected\" : true|false, (boolean) If connected\n" - " \"addresses\" : [ (list of objects) Only when connected = true\n" - " {\n" - " \"address\" : \"192.168.0.201:8333\", (string) The bitcoin server IP and port we're connected to\n" - " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n" - " }\n" - " ]\n" - " }\n" - " ,...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "addednode", "The node IP address or name (as provided to addnode)"}, + {RPCResult::Type::BOOL, "connected", "If connected"}, + {RPCResult::Type::ARR, "addresses", "Only when connected = true", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", "The bitcoin server IP and port we're connected to"}, + {RPCResult::Type::STR, "connected", "connection, inbound or outbound"}, + }}, + }}, + }}, + } }, RPCExamples{ HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"") @@ -386,20 +391,21 @@ static UniValue getnettotals(const JSONRPCRequest& request) "and current time.\n", {}, RPCResult{ - "{\n" - " \"totalbytesrecv\" : n, (numeric) Total bytes received\n" - " \"totalbytessent\" : n, (numeric) Total bytes sent\n" - " \"timemillis\" : t, (numeric) Current UNIX time in milliseconds\n" - " \"uploadtarget\" : \n" - " {\n" - " \"timeframe\" : n, (numeric) Length of the measuring timeframe in seconds\n" - " \"target\" : n, (numeric) Target in bytes\n" - " \"target_reached\" : true|false, (boolean) True if target is reached\n" - " \"serve_historical_blocks\" : true|false, (boolean) True if serving historical blocks\n" - " \"bytes_left_in_cycle\" : t, (numeric) Bytes left in current time cycle\n" - " \"time_left_in_cycle\" : t (numeric) Seconds left in current time cycle\n" - " }\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"}, + {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"}, + {RPCResult::Type::NUM_TIME, "timemillis", "Current UNIX time in milliseconds"}, + {RPCResult::Type::OBJ, "uploadtarget", "", + { + {RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"}, + {RPCResult::Type::NUM, "target", "Target in bytes"}, + {RPCResult::Type::BOOL, "target_reached", "True if target is reached"}, + {RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"}, + {RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"}, + {RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"}, + }}, + } }, RPCExamples{ HelpExampleCli("getnettotals", "") @@ -452,41 +458,44 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request) "Returns an object containing various state info regarding P2P networking.\n", {}, RPCResult{ - "{ (json object)\n" - " \"version\" : xxxxx, (numeric) the server version\n" - " \"subversion\" : \"str\", (string) the server subversion string\n" - " \"protocolversion\" : xxxxx, (numeric) the protocol version\n" - " \"localservices\" : \"hex\", (string) the services we offer to the network\n" - " \"localservicesnames\" : [ (json array) the services we offer to the network, in human-readable form\n" - " \"SERVICE_NAME\", (string) the service name\n" - " ...\n" - " ],\n" - " \"localrelay\" : true|false, (boolean) true if transaction relay is requested from peers\n" - " \"timeoffset\" : xxxxx, (numeric) the time offset\n" - " \"connections\" : xxxxx, (numeric) the number of connections\n" - " \"networkactive\" : true|false, (boolean) whether p2p networking is enabled\n" - " \"networks\" : [ (json array) information per network\n" - " { (json object)\n" - " \"name\" : \"str\", (string) network (ipv4, ipv6 or onion)\n" - " \"limited\" : true|false, (boolean) is the network limited using -onlynet?\n" - " \"reachable\" : true|false, (boolean) is the network reachable?\n" - " \"proxy\" : \"str\" (string) (\"host:port\") the proxy that is used for this network, or empty if none\n" - " \"proxy_randomize_credentials\" : true|false, (boolean) Whether randomized credentials are used\n" - " },\n" - " ...\n" - " ],\n" - " \"relayfee\" : x.xxxxxxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n" - " \"incrementalfee\" : x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB\n" - " \"localaddresses\" : [ (json array) list of local addresses\n" - " { (json object)\n" - " \"address\" : \"xxxx\", (string) network address\n" - " \"port\" : xxx, (numeric) network port\n" - " \"score\" : xxx (numeric) relative score\n" - " },\n" - " ...\n" - " ],\n" - " \"warnings\" : \"str\", (string) any network and blockchain warnings\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "version", "the server version"}, + {RPCResult::Type::STR, "subversion", "the server subversion string"}, + {RPCResult::Type::NUM, "protocolversion", "the protocol version"}, + {RPCResult::Type::STR_HEX, "localservices", "the services we offer to the network"}, + {RPCResult::Type::ARR, "localservicesnames", "the services we offer to the network, in human-readable form", + { + {RPCResult::Type::STR, "SERVICE_NAME", "the service name"}, + }}, + {RPCResult::Type::BOOL, "localrelay", "true if transaction relay is requested from peers"}, + {RPCResult::Type::NUM, "timeoffset", "the time offset"}, + {RPCResult::Type::NUM, "connections", "the number of connections"}, + {RPCResult::Type::BOOL, "networkactive", "whether p2p networking is enabled"}, + {RPCResult::Type::ARR, "networks", "information per network", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "name", "network (ipv4, ipv6 or onion)"}, + {RPCResult::Type::BOOL, "limited", "is the network limited using -onlynet?"}, + {RPCResult::Type::BOOL, "reachable", "is the network reachable?"}, + {RPCResult::Type::STR, "proxy", "(\"host:port\") the proxy that is used for this network, or empty if none"}, + {RPCResult::Type::BOOL, "proxy_randomize_credentials", "Whether randomized credentials are used"}, + }}, + }}, + {RPCResult::Type::NUM, "relayfee", "minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB"}, + {RPCResult::Type::NUM, "incrementalfee", "minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB"}, + {RPCResult::Type::ARR, "localaddresses", "list of local addresses", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", "network address"}, + {RPCResult::Type::NUM, "port", "network port"}, + {RPCResult::Type::NUM, "score", "relative score"}, + }}, + }}, + {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, + } }, RPCExamples{ HelpExampleCli("getnetworkinfo", "") @@ -693,15 +702,16 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request) {"count", RPCArg::Type::NUM, /* default */ "1", "How many addresses to return. Limited to the smaller of " + std::to_string(ADDRMAN_GETADDR_MAX) + " or " + std::to_string(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses."}, }, RPCResult{ - "[\n" - " {\n" - " \"time\" : ttt, (numeric) The " + UNIX_EPOCH_TIME + " of when the node was last seen\n" - " \"services\" : n, (numeric) The services offered\n" - " \"address\" : \"host\", (string) The address of the node\n" - " \"port\" : n (numeric) The port of the node\n" - " }\n" - " ,....\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM_TIME, "time", "The " + UNIX_EPOCH_TIME + " of when the node was last seen"}, + {RPCResult::Type::NUM, "services", "The services offered"}, + {RPCResult::Type::STR, "address", "The address of the node"}, + {RPCResult::Type::NUM, "port", "The port of the node"}, + }}, + } }, RPCExamples{ HelpExampleCli("getnodeaddresses", "8") diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index cd1c657c26..361cf08086 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -94,54 +94,62 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) }, { RPCResult{"if verbose is not set or set to false", - "\"data\" (string) The serialized, hex-encoded data for 'txid'\n" + RPCResult::Type::STR, "data", "The serialized, hex-encoded data for 'txid'" }, RPCResult{"if verbose is set to true", - "{\n" - " \"in_active_chain\" : b, (boolean) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n" - " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n" - " \"txid\" : \"id\", (string) The transaction id (same as provided)\n" - " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" - " \"size\" : n, (numeric) The serialized transaction size\n" - " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n" - " \"weight\" : n, (numeric) The transaction's weight (between vsize*4-3 and vsize*4)\n" - " \"version\" : n, (numeric) The version\n" - " \"locktime\" : ttt, (numeric) The lock time\n" - " \"vin\" : [ (array of json objects)\n" - " {\n" - " \"txid\" : \"id\", (string) The transaction id\n" - " \"vout\" : n, (numeric) \n" - " \"scriptSig\" : { (json object) The script\n" - " \"asm\" : \"asm\", (string) asm\n" - " \"hex\" : \"hex\" (string) hex\n" - " },\n" - " \"sequence\" : n (numeric) The script sequence number\n" - " \"txinwitness\" : [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n" - " }\n" - " ,...\n" - " ],\n" - " \"vout\" : [ (array of json objects)\n" - " {\n" - " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" - " \"n\" : n, (numeric) index\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"asm\", (string) the asm\n" - " \"hex\" : \"hex\", (string) the hex\n" - " \"reqSigs\" : n, (numeric) The required sigs\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " \"addresses\" : [ (json array of string)\n" - " \"address\" (string) bitcoin address\n" - " ,...\n" - " ]\n" - " }\n" - " }\n" - " ,...\n" - " ],\n" - " \"blockhash\" : \"hash\", (string) the block hash\n" - " \"confirmations\" : n, (numeric) The confirmations\n" - " \"blocktime\" : ttt (numeric) The block time expressed in " + UNIX_EPOCH_TIME + "\n" - " \"time\" : ttt, (numeric) Same as \"blocktime\"\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "in_active_chain", "Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)"}, + {RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded data for 'txid'"}, + {RPCResult::Type::STR_HEX, "txid", "The transaction id (same as provided)"}, + {RPCResult::Type::STR_HEX, "hash", "The transaction hash (differs from txid for witness transactions)"}, + {RPCResult::Type::NUM, "size", "The serialized transaction size"}, + {RPCResult::Type::NUM, "vsize", "The virtual transaction size (differs from size for witness transactions)"}, + {RPCResult::Type::NUM, "weight", "The transaction's weight (between vsize*4-3 and vsize*4)"}, + {RPCResult::Type::NUM, "version", "The version"}, + {RPCResult::Type::NUM_TIME, "locktime", "The lock time"}, + {RPCResult::Type::ARR, "vin", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + {RPCResult::Type::STR, "vout", ""}, + {RPCResult::Type::OBJ, "scriptSig", "The script", + { + {RPCResult::Type::STR, "asm", "asm"}, + {RPCResult::Type::STR_HEX, "hex", "hex"}, + }}, + {RPCResult::Type::NUM, "sequence", "The script sequence number"}, + {RPCResult::Type::ARR, "txinwitness", "", + { + {RPCResult::Type::STR_HEX, "hex", "hex-encoded witness data (if any)"}, + }}, + }}, + }}, + {RPCResult::Type::ARR, "vout", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "value", "The value in " + CURRENCY_UNIT}, + {RPCResult::Type::NUM, "n", "index"}, + {RPCResult::Type::OBJ, "scriptPubKey", "", + { + {RPCResult::Type::STR, "asm", "the asm"}, + {RPCResult::Type::STR, "hex", "the hex"}, + {RPCResult::Type::NUM, "reqSigs", "The required sigs"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + {RPCResult::Type::ARR, "addresses", "", + { + {RPCResult::Type::STR, "address", "bitcoin address"}, + }}, + }}, + }}, + }}, + {RPCResult::Type::STR_HEX, "blockhash", "the block hash"}, + {RPCResult::Type::NUM, "confirmations", "The confirmations"}, + {RPCResult::Type::NUM_TIME, "blocktime", "The block time expressed in " + UNIX_EPOCH_TIME}, + {RPCResult::Type::NUM, "time", "Same as \"blocktime\""}, + } }, }, RPCExamples{ @@ -230,7 +238,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request) {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "If specified, looks for txid in the block with this hash"}, }, RPCResult{ - "\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n" + RPCResult::Type::STR, "data", "A string that is a serialized, hex-encoded data for the proof." }, RPCExamples{""}, }.Check(request); @@ -315,7 +323,10 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request) {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"}, }, RPCResult{ - "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof can not be validated.\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The txid(s) which the proof commits to, or empty array if the proof can not be validated."}, + } }, RPCExamples{""}, }.Check(request); @@ -390,7 +401,7 @@ static UniValue createrawtransaction(const JSONRPCRequest& request) " Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."}, }, RPCResult{ - "\"transaction\" (string) hex string of the transaction\n" + RPCResult::Type::STR_HEX, "transaction", "hex string of the transaction" }, RPCExamples{ HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"") @@ -432,45 +443,53 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request) }, }, RPCResult{ - "{\n" - " \"txid\" : \"id\", (string) The transaction id\n" - " \"hash\" : \"id\", (string) The transaction hash (differs from txid for witness transactions)\n" - " \"size\" : n, (numeric) The transaction size\n" - " \"vsize\" : n, (numeric) The virtual transaction size (differs from size for witness transactions)\n" - " \"weight\" : n, (numeric) The transaction's weight (between vsize*4 - 3 and vsize*4)\n" - " \"version\" : n, (numeric) The version\n" - " \"locktime\" : ttt, (numeric) The lock time\n" - " \"vin\" : [ (array of json objects)\n" - " {\n" - " \"txid\" : \"id\", (string) The transaction id\n" - " \"vout\" : n, (numeric) The output number\n" - " \"scriptSig\" : { (json object) The script\n" - " \"asm\" : \"asm\", (string) asm\n" - " \"hex\" : \"hex\" (string) hex\n" - " },\n" - " \"txinwitness\" : [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n" - " \"sequence\" : n (numeric) The script sequence number\n" - " }\n" - " ,...\n" - " ],\n" - " \"vout\" : [ (array of json objects)\n" - " {\n" - " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" - " \"n\" : n, (numeric) index\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"asm\", (string) the asm\n" - " \"hex\" : \"hex\", (string) the hex\n" - " \"reqSigs\" : n, (numeric) The required sigs\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " \"addresses\" : [ (json array of string)\n" - " \"12tvKAXCxZjSmdNbao16dKXC8tRWfcF5oc\" (string) bitcoin address\n" - " ,...\n" - " ]\n" - " }\n" - " }\n" - " ,...\n" - " ],\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + {RPCResult::Type::STR_HEX, "hash", "The transaction hash (differs from txid for witness transactions)"}, + {RPCResult::Type::NUM, "size", "The transaction size"}, + {RPCResult::Type::NUM, "vsize", "The virtual transaction size (differs from size for witness transactions)"}, + {RPCResult::Type::NUM, "weight", "The transaction's weight (between vsize*4 - 3 and vsize*4)"}, + {RPCResult::Type::NUM, "version", "The version"}, + {RPCResult::Type::NUM_TIME, "locktime", "The lock time"}, + {RPCResult::Type::ARR, "vin", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + {RPCResult::Type::NUM, "vout", "The output number"}, + {RPCResult::Type::OBJ, "scriptSig", "The script", + { + {RPCResult::Type::STR, "asm", "asm"}, + {RPCResult::Type::STR_HEX, "hex", "hex"}, + }}, + {RPCResult::Type::ARR, "txinwitness", "", + { + {RPCResult::Type::STR_HEX, "hex", "hex-encoded witness data (if any)"}, + }}, + {RPCResult::Type::NUM, "sequence", "The script sequence number"}, + }}, + }}, + {RPCResult::Type::ARR, "vout", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "value", "The value in " + CURRENCY_UNIT}, + {RPCResult::Type::NUM, "n", "index"}, + {RPCResult::Type::OBJ, "scriptPubKey", "", + { + {RPCResult::Type::STR, "asm", "the asm"}, + {RPCResult::Type::STR_HEX, "hex", "the hex"}, + {RPCResult::Type::NUM, "reqSigs", "The required sigs"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + {RPCResult::Type::ARR, "addresses", "", + { + {RPCResult::Type::STR, "address", "bitcoin address"}, + }}, + }}, + }}, + }}, + } }, RPCExamples{ HelpExampleCli("decoderawtransaction", "\"hexstring\"") @@ -513,26 +532,29 @@ static UniValue decodescript(const JSONRPCRequest& request) {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded script"}, }, RPCResult{ - "{\n" - " \"asm\" : \"asm\", (string) Script public key\n" - " \"type\" : \"type\", (string) The output type (e.g. "+GetAllOutputTypes()+")\n" - " \"reqSigs\" : n, (numeric) The required signatures\n" - " \"addresses\" : [ (json array of string)\n" - " \"address\" (string) bitcoin address\n" - " ,...\n" - " ],\n" - " \"p2sh\":\"str\" (string) address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).\n" - " \"segwit\" : { (json object) Result of a witness script public key wrapping this redeem script (not returned if the script is a P2SH or witness).\n" - " \"asm\" : \"str\", (string) String representation of the script public key\n" - " \"hex\" : \"hexstr\", (string) Hex string of the script public key\n" - " \"type\" : \"str\", (string) The type of the script public key (e.g. witness_v0_keyhash or witness_v0_scripthash)\n" - " \"reqSigs\" : n, (numeric) The required signatures (always 1)\n" - " \"addresses\" : [ (json array of string) (always length 1)\n" - " \"address\" (string) segwit address\n" - " ,...\n" - " ],\n" - " \"p2sh-segwit\":\"str\" (string) address of the P2SH script wrapping this witness redeem script.\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "asm", "Script public key"}, + {RPCResult::Type::STR, "type", "The output type (e.g. "+GetAllOutputTypes()+")"}, + {RPCResult::Type::NUM, "reqSigs", "The required signatures"}, + {RPCResult::Type::ARR, "addresses", "", + { + {RPCResult::Type::STR, "address", "bitcoin address"}, + }}, + {RPCResult::Type::STR, "p2sh", "address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH)"}, + {RPCResult::Type::OBJ, "segwit", "Result of a witness script public key wrapping this redeem script (not returned if the script is a P2SH or witness)", + { + {RPCResult::Type::STR, "asm", "String representation of the script public key"}, + {RPCResult::Type::STR_HEX, "hex", "Hex string of the script public key"}, + {RPCResult::Type::STR, "type", "The type of the script public key (e.g. witness_v0_keyhash or witness_v0_scripthash)"}, + {RPCResult::Type::NUM, "reqSigs", "The required signatures (always 1)"}, + {RPCResult::Type::ARR, "addresses", "(always length 1)", + { + {RPCResult::Type::STR, "address", "segwit address"}, + }}, + {RPCResult::Type::STR, "p2sh-segwit", "address of the P2SH script wrapping this witness redeem script"}, + }}, + } }, RPCExamples{ HelpExampleCli("decodescript", "\"hexstring\"") @@ -607,7 +629,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) }, }, RPCResult{ - "\"hex\" (string) The hex-encoded raw transaction with signature(s)\n" + RPCResult::Type::STR, "", "The hex-encoded raw transaction with signature(s)" }, RPCExamples{ HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')") @@ -715,20 +737,22 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) }, }, RPCResult{ - "{\n" - " \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n" - " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n" - " \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n" - " {\n" - " \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n" - " \"vout\" : n, (numeric) The index of the output to spent and used as input\n" - " \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n" - " \"sequence\" : n, (numeric) Script sequence number\n" - " \"error\" : \"text\" (string) Verification or signing error related to the input\n" - " }\n" - " ,...\n" - " ]\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"}, + {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"}, + {RPCResult::Type::ARR, "errors", "Script verification errors (if there are any)", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"}, + {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"}, + {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"}, + {RPCResult::Type::NUM, "sequence", "Script sequence number"}, + {RPCResult::Type::STR, "error", "Verification or signing error related to the input"}, + }}, + }}, + } }, RPCExamples{ HelpExampleCli("signrawtransactionwithkey", "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"") @@ -784,7 +808,7 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request) "/kB.\nSet to 0 to accept any fee rate.\n"}, }, RPCResult{ - "\"hex\" (string) The transaction hash in hex\n" + RPCResult::Type::STR_HEX, "", "The transaction hash in hex" }, RPCExamples{ "\nCreate a transaction\n" @@ -846,14 +870,16 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) {"maxfeerate", RPCArg::Type::AMOUNT, /* default */ FormatMoney(DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK()), "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + "/kB\n"}, }, RPCResult{ - "[ (json array) The result of the mempool acceptance test for each raw transaction in the input array.\n" - " Length is exactly one for now.\n" - " {\n" - " \"txid\" (string) The transaction hash in hex\n" - " \"allowed\" (boolean) If the mempool allows this tx to be inserted\n" - " \"reject-reason\" (string) Rejection string (only present when 'allowed' is false)\n" - " }\n" - "]\n" + RPCResult::Type::ARR, "", "The result of the mempool acceptance test for each raw transaction in the input array.\n" + "Length is exactly one for now.", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"}, + {RPCResult::Type::BOOL, "allowed", "If the mempool allows this tx to be inserted"}, + {RPCResult::Type::STR, "reject-reason", "Rejection string (only present when 'allowed' is false)"}, + }}, + } }, RPCExamples{ "\nCreate a transaction\n" @@ -950,92 +976,108 @@ UniValue decodepsbt(const JSONRPCRequest& request) {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The PSBT base64 string"}, }, RPCResult{ - "{\n" - " \"tx\" : { (json object) The decoded network-serialized unsigned transaction.\n" - " ... The layout is the same as the output of decoderawtransaction.\n" - " },\n" - " \"unknown\" : { (json object) The unknown global fields\n" - " \"key\" : \"value\" (key-value pair) An unknown key-value pair\n" - " ...\n" - " },\n" - " \"inputs\" : [ (array of json objects)\n" - " {\n" - " \"non_witness_utxo\" : { (json object, optional) Decoded network transaction for non-witness UTXOs\n" - " ...\n" - " },\n" - " \"witness_utxo\" : { (json object, optional) Transaction output for witness UTXOs\n" - " \"amount\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"asm\", (string) The asm\n" - " \"hex\" : \"hex\", (string) The hex\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " \"address\" : \"address\" (string) Bitcoin address if there is one\n" - " }\n" - " },\n" - " \"partial_signatures\" : { (json object, optional)\n" - " \"pubkey\" : \"signature\", (string) The public key and signature that corresponds to it.\n" - " ,...\n" - " }\n" - " \"sighash\" : \"type\", (string, optional) The sighash type to be used\n" - " \"redeem_script\" : { (json object, optional)\n" - " \"asm\" : \"asm\", (string) The asm\n" - " \"hex\" : \"hex\", (string) The hex\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " }\n" - " \"witness_script\" : { (json object, optional)\n" - " \"asm\" : \"asm\", (string) The asm\n" - " \"hex\" : \"hex\", (string) The hex\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " }\n" - " \"bip32_derivs\" : { (json object, optional)\n" - " \"pubkey\" : { (json object, optional) The public key with the derivation path as the value.\n" - " \"master_fingerprint\" : \"fingerprint\" (string) The fingerprint of the master key\n" - " \"path\" : \"path\", (string) The path\n" - " }\n" - " ,...\n" - " }\n" - " \"final_scriptsig\" : { (json object, optional)\n" - " \"asm\" : \"asm\", (string) The asm\n" - " \"hex\" : \"hex\", (string) The hex\n" - " }\n" - " \"final_scriptwitness\" : [\"hex\", ...] (array of string) hex-encoded witness data (if any)\n" - " \"unknown\" : { (json object) The unknown global fields\n" - " \"key\" : \"value\" (key-value pair) An unknown key-value pair\n" - " ...\n" - " },\n" - " }\n" - " ,...\n" - " ]\n" - " \"outputs\" : [ (array of json objects)\n" - " {\n" - " \"redeem_script\" : { (json object, optional)\n" - " \"asm\" : \"asm\", (string) The asm\n" - " \"hex\" : \"hex\", (string) The hex\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " }\n" - " \"witness_script\" : { (json object, optional)\n" - " \"asm\" : \"asm\", (string) The asm\n" - " \"hex\" : \"hex\", (string) The hex\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " }\n" - " \"bip32_derivs\" : [ (array of json objects, optional)\n" - " {\n" - " \"pubkey\" : \"pubkey\", (string) The public key this path corresponds to\n" - " \"master_fingerprint\" : \"fingerprint\" (string) The fingerprint of the master key\n" - " \"path\" : \"path\", (string) The path\n" - " }\n" - " }\n" - " ,...\n" - " ],\n" - " \"unknown\" : { (json object) The unknown global fields\n" - " \"key\" : \"value\" (key-value pair) An unknown key-value pair\n" - " ...\n" - " },\n" - " }\n" - " ,...\n" - " ]\n" - " \"fee\" : fee (numeric, optional) The transaction fee paid if all UTXOs slots in the PSBT have been filled.\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ, "tx", "The decoded network-serialized unsigned transaction.", + { + {RPCResult::Type::ELISION, "", "The layout is the same as the output of decoderawtransaction."}, + }}, + {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields", + { + {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"}, + }}, + {RPCResult::Type::ARR, "inputs", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ, "non_witness_utxo", /* optional */ true, "Decoded network transaction for non-witness UTXOs", + { + {RPCResult::Type::ELISION, "",""}, + }}, + {RPCResult::Type::OBJ, "witness_utxo", /* optional */ true, "Transaction output for witness UTXOs", + { + {RPCResult::Type::NUM, "amount", "The value in " + CURRENCY_UNIT}, + {RPCResult::Type::OBJ, "scriptPubKey", "", + { + {RPCResult::Type::STR, "asm", "The asm"}, + {RPCResult::Type::STR_HEX, "hex", "The hex"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + {RPCResult::Type::STR, "address"," Bitcoin address if there is one"}, + }}, + }}, + {RPCResult::Type::OBJ_DYN, "partial_signatures", /* optional */ true, "", + { + {RPCResult::Type::STR, "pubkey", "The public key and signature that corresponds to it."}, + }}, + {RPCResult::Type::STR, "sighash", /* optional */ true, "The sighash type to be used"}, + {RPCResult::Type::OBJ, "redeem_script", /* optional */ true, "", + { + {RPCResult::Type::STR, "asm", "The asm"}, + {RPCResult::Type::STR_HEX, "hex", "The hex"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + }}, + {RPCResult::Type::OBJ, "witness_script", /* optional */ true, "", + { + {RPCResult::Type::STR, "asm", "The asm"}, + {RPCResult::Type::STR_HEX, "hex", "The hex"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + }}, + {RPCResult::Type::ARR, "bip32_derivs", /* optional */ true, "", + { + {RPCResult::Type::OBJ, "pubkey", /* optional */ true, "The public key with the derivation path as the value.", + { + {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"}, + {RPCResult::Type::STR, "path", "The path"}, + }}, + }}, + {RPCResult::Type::OBJ, "final_scriptsig", /* optional */ true, "", + { + {RPCResult::Type::STR, "asm", "The asm"}, + {RPCResult::Type::STR, "hex", "The hex"}, + }}, + {RPCResult::Type::ARR, "final_scriptwitness", "", + { + {RPCResult::Type::STR_HEX, "", "hex-encoded witness data (if any)"}, + }}, + {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields", + { + {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"}, + }}, + }}, + }}, + {RPCResult::Type::ARR, "outputs", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ, "redeem_script", /* optional */ true, "", + { + {RPCResult::Type::STR, "asm", "The asm"}, + {RPCResult::Type::STR_HEX, "hex", "The hex"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + }}, + {RPCResult::Type::OBJ, "witness_script", /* optional */ true, "", + { + {RPCResult::Type::STR, "asm", "The asm"}, + {RPCResult::Type::STR_HEX, "hex", "The hex"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + }}, + {RPCResult::Type::ARR, "bip32_derivs", /* optional */ true, "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"}, + {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"}, + {RPCResult::Type::STR, "path", "The path"}, + }}, + }}, + {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields", + { + {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"}, + }}, + }}, + }}, + {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The transaction fee paid if all UTXOs slots in the PSBT have been filled."}, + } }, RPCExamples{ HelpExampleCli("decodepsbt", "\"psbt\"") @@ -1244,7 +1286,7 @@ UniValue combinepsbt(const JSONRPCRequest& request) }, }, RPCResult{ - " \"psbt\" (string) The base64-encoded partially signed transaction\n" + RPCResult::Type::STR, "", "The base64-encoded partially signed transaction" }, RPCExamples{ HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')") @@ -1292,11 +1334,12 @@ UniValue finalizepsbt(const JSONRPCRequest& request) " extract and return the complete transaction in normal network serialization instead of the PSBT."}, }, RPCResult{ - "{ (json object)\n" - " \"psbt\" : \"str\", (string) The base64-encoded partially signed transaction if not extracted\n" - " \"hex\" : \"hex\", (string) The hex-encoded network transaction if extracted\n" - " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction if not extracted"}, + {RPCResult::Type::STR_HEX, "hex", "The hex-encoded network transaction if extracted"}, + {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"}, + } }, RPCExamples{ HelpExampleCli("finalizepsbt", "\"psbt\"") @@ -1374,7 +1417,7 @@ UniValue createpsbt(const JSONRPCRequest& request) " Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."}, }, RPCResult{ - " \"psbt\" (string) The resulting raw transaction (base64-encoded string)\n" + RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)" }, RPCExamples{ HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") @@ -1431,7 +1474,7 @@ UniValue converttopsbt(const JSONRPCRequest& request) }, }, RPCResult{ - " \"psbt\" (string) The resulting raw transaction (base64-encoded string)\n" + RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)" }, RPCExamples{ "\nCreate a transaction\n" @@ -1495,7 +1538,7 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request) }}, }, RPCResult { - " \"psbt\" (string) The base64-encoded partially signed transaction with inputs updated\n" + RPCResult::Type::STR, "", "The base64-encoded partially signed transaction with inputs updated" }, RPCExamples { HelpExampleCli("utxoupdatepsbt", "\"psbt\"") @@ -1580,7 +1623,7 @@ UniValue joinpsbts(const JSONRPCRequest& request) }} }, RPCResult { - " \"psbt\" (string) The base64-encoded partially signed transaction\n" + RPCResult::Type::STR, "", "The base64-encoded partially signed transaction" }, RPCExamples { HelpExampleCli("joinpsbts", "\"psbt\"") @@ -1669,31 +1712,36 @@ UniValue analyzepsbt(const JSONRPCRequest& request) {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"} }, RPCResult { - "{\n" - " \"inputs\" : [ (array of json objects)\n" - " {\n" - " \"has_utxo\" : true|false (boolean) Whether a UTXO is provided\n" - " \"is_final\" : true|false (boolean) Whether the input is finalized\n" - " \"missing\" : { (json object, optional) Things that are missing that are required to complete this input\n" - " \"pubkeys\" : [ (array, optional)\n" - " \"keyid\" (string) Public key ID, hash160 of the public key, of a public key whose BIP 32 derivation path is missing\n" - " ]\n" - " \"signatures\" : [ (array, optional)\n" - " \"keyid\" (string) Public key ID, hash160 of the public key, of a public key whose signature is missing\n" - " ]\n" - " \"redeemscript\" : \"hash\" (string, optional) Hash160 of the redeemScript that is missing\n" - " \"witnessscript\" : \"hash\" (string, optional) SHA256 of the witnessScript that is missing\n" - " }\n" - " \"next\" : \"role\" (string, optional) Role of the next person that this input needs to go to\n" - " }\n" - " ,...\n" - " ]\n" - " \"estimated_vsize\" : vsize (numeric, optional) Estimated vsize of the final signed transaction\n" - " \"estimated_feerate\" : feerate (numeric, optional) Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kB. Shown only if all UTXO slots in the PSBT have been filled.\n" - " \"fee\" : fee (numeric, optional) The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled.\n" - " \"next\" : \"role\" (string) Role of the next person that this psbt needs to go to\n" - " \"error\" : \"error\" (string) Error message if there is one\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ARR, "inputs", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "has_utxo", "Whether a UTXO is provided"}, + {RPCResult::Type::BOOL, "is_final", "Whether the input is finalized"}, + {RPCResult::Type::OBJ, "missing", /* optional */ true, "Things that are missing that are required to complete this input", + { + {RPCResult::Type::ARR, "pubkeys", /* optional */ true, "", + { + {RPCResult::Type::STR_HEX, "keyid", "Public key ID, hash160 of the public key, of a public key whose BIP 32 derivation path is missing"}, + }}, + {RPCResult::Type::ARR, "signatures", /* optional */ true, "", + { + {RPCResult::Type::STR_HEX, "keyid", "Public key ID, hash160 of the public key, of a public key whose signature is missing"}, + }}, + {RPCResult::Type::STR_HEX, "redeemscript", /* optional */ true, "Hash160 of the redeemScript that is missing"}, + {RPCResult::Type::STR_HEX, "witnessscript", /* optional */ true, "SHA256 of the witnessScript that is missing"}, + }}, + {RPCResult::Type::STR, "next", /* optional */ true, "Role of the next person that this input needs to go to"}, + }}, + }}, + {RPCResult::Type::NUM, "estimated_vsize", /* optional */ true, "Estimated vsize of the final signed transaction"}, + {RPCResult::Type::STR_AMOUNT, "estimated_feerate", /* optional */ true, "Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kB. Shown only if all UTXO slots in the PSBT have been filled"}, + {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled"}, + {RPCResult::Type::STR, "next", "Role of the next person that this psbt needs to go to"}, + {RPCResult::Type::STR, "error", "Error message if there is one"}, + } }, RPCExamples { HelpExampleCli("analyzepsbt", "\"psbt\"") diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index b62490ed29..75baacd6f2 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -137,7 +137,7 @@ UniValue help(const JSONRPCRequest& jsonRequest) {"command", RPCArg::Type::STR, /* default */ "all commands", "The command to get help on"}, }, RPCResult{ - "\"text\" (string) The help text\n" + RPCResult::Type::STR, "", "The help text" }, RPCExamples{""}, }.ToString() @@ -180,7 +180,7 @@ static UniValue uptime(const JSONRPCRequest& jsonRequest) "\nReturns the total uptime of the server.\n", {}, RPCResult{ - "ttt (numeric) The number of seconds that the server has been running\n" + RPCResult::Type::NUM, "", "The number of seconds that the server has been running" }, RPCExamples{ HelpExampleCli("uptime", "") @@ -197,16 +197,18 @@ static UniValue getrpcinfo(const JSONRPCRequest& request) "\nReturns details of the RPC server.\n", {}, RPCResult{ - "{\n" - " \"active_commands\" (json array) All active commands\n" - " [\n" - " { (json object) Information about an active command\n" - " \"method\" (string) The name of the RPC command \n" - " \"duration\" (numeric) The running time in microseconds\n" - " },...\n" - " ],\n" - " \"logpath\" : \"xxx\" (string) The complete file path to the debug log\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ARR, "active_commands", "All active commands", + { + {RPCResult::Type::OBJ, "", "Information about an active command", + { + {RPCResult::Type::STR, "method", "The name of the RPC command"}, + {RPCResult::Type::NUM, "duration", "The running time in microseconds"}, + }}, + }}, + {RPCResult::Type::STR, "logpath", "The complete file path to the debug log"}, + } }, RPCExamples{ HelpExampleCli("getrpcinfo", "") diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 7cefb2db96..a4e67c8da8 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -312,20 +312,9 @@ struct Sections { } /** - * Serializing RPCArgs depends on the outer type. Only arrays and - * dictionaries can be nested in json. The top-level outer type is "named - * arguments", a mix between a dictionary and arrays. - */ - enum class OuterType { - ARR, - OBJ, - NAMED_ARG, // Only set on first recursion - }; - - /** * Recursive helper to translate an RPCArg into sections */ - void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NAMED_ARG) + void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NONE) { const auto indent = std::string(current_indent, ' '); const auto indent_next = std::string(current_indent + 2, ' '); @@ -338,7 +327,7 @@ struct Sections { case RPCArg::Type::AMOUNT: case RPCArg::Type::RANGE: case RPCArg::Type::BOOL: { - if (outer_type == OuterType::NAMED_ARG) return; // Nothing more to do for non-recursive types on first recursion + if (outer_type == OuterType::NONE) return; // Nothing more to do for non-recursive types on first recursion auto left = indent; if (arg.m_type_str.size() != 0 && push_name) { left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0); @@ -351,7 +340,7 @@ struct Sections { } case RPCArg::Type::OBJ: case RPCArg::Type::OBJ_USER_KEYS: { - const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString(); + const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString(); PushSection({indent + (push_name ? "\"" + arg.m_name + "\": " : "") + "{", right}); for (const auto& arg_inner : arg.m_inner) { Push(arg_inner, current_indent + 2, OuterType::OBJ); @@ -359,20 +348,20 @@ struct Sections { if (arg.m_type != RPCArg::Type::OBJ) { PushSection({indent_next + "...", ""}); } - PushSection({indent + "}" + (outer_type != OuterType::NAMED_ARG ? "," : ""), ""}); + PushSection({indent + "}" + (outer_type != OuterType::NONE ? "," : ""), ""}); break; } case RPCArg::Type::ARR: { auto left = indent; left += push_name ? "\"" + arg.m_name + "\": " : ""; left += "["; - const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString(); + const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString(); PushSection({left, right}); for (const auto& arg_inner : arg.m_inner) { Push(arg_inner, current_indent + 2, OuterType::ARR); } PushSection({indent_next + "...", ""}); - PushSection({indent + "]" + (outer_type != OuterType::NAMED_ARG ? "," : ""), ""}); + PushSection({indent + "]" + (outer_type != OuterType::NONE ? "," : ""), ""}); break; } @@ -444,7 +433,9 @@ std::string RPCResults::ToDescriptionString() const } else { result += "\nResult (" + r.m_cond + "):\n"; } - result += r.m_result; + Sections sections; + r.ToSections(sections); + result += sections.ToString(); } return result; } @@ -591,6 +582,93 @@ std::string RPCArg::ToDescriptionString() const return ret; } +void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const int current_indent) const +{ + // Indentation + const std::string indent(current_indent, ' '); + const std::string indent_next(current_indent + 2, ' '); + + // Elements in a JSON structure (dictionary or array) are separated by a comma + const std::string maybe_separator{outer_type != OuterType::NONE ? "," : ""}; + + // The key name if recursed into an dictionary + const std::string maybe_key{ + outer_type == OuterType::OBJ ? + "\"" + this->m_key_name + "\" : " : + ""}; + + // Format description with type + const auto Description = [&](const std::string& type) { + return "(" + type + (this->m_optional ? ", optional" : "") + ")" + + (this->m_description.empty() ? "" : " " + this->m_description); + }; + + switch (m_type) { + case Type::ELISION: { + // If the inner result is empty, use three dots for elision + sections.PushSection({indent_next + "...", m_description}); + return; + } + case Type::NONE: { + sections.PushSection({indent + "None", Description("json null")}); + return; + } + case Type::STR: { + sections.PushSection({indent + maybe_key + "\"str\"" + maybe_separator, Description("string")}); + return; + } + case Type::STR_AMOUNT: { + sections.PushSection({indent + maybe_key + "n" + maybe_separator, Description("numeric")}); + return; + } + case Type::STR_HEX: { + sections.PushSection({indent + maybe_key + "\"hex\"" + maybe_separator, Description("string")}); + return; + } + case Type::NUM: { + sections.PushSection({indent + maybe_key + "n" + maybe_separator, Description("numeric")}); + return; + } + case Type::NUM_TIME: { + sections.PushSection({indent + maybe_key + "xxx" + maybe_separator, Description("numeric")}); + return; + } + case Type::BOOL: { + sections.PushSection({indent + maybe_key + "true|false" + maybe_separator, Description("boolean")}); + return; + } + case Type::ARR_FIXED: + case Type::ARR: { + sections.PushSection({indent + maybe_key + "[", Description("json array")}); + for (const auto& i : m_inner) { + i.ToSections(sections, OuterType::ARR, current_indent + 2); + } + if (m_type == Type::ARR) { + sections.PushSection({indent_next + "...", ""}); + } + sections.PushSection({indent + "]" + maybe_separator, ""}); + return; + } + case Type::OBJ_DYN: + case Type::OBJ: { + sections.PushSection({indent + maybe_key + "{", Description("json object")}); + for (const auto& i : m_inner) { + i.ToSections(sections, OuterType::OBJ, current_indent + 2); + } + if (m_type == Type::OBJ_DYN) { + // If the dictionary keys are dynamic, use three dots for continuation + sections.PushSection({indent_next + "...", ""}); + } + sections.PushSection({indent + "}" + maybe_separator, ""}); + return; + } + + // no default case, so the compiler can warn about missing cases + } + + CHECK_NONFATAL(false); +} + std::string RPCArg::ToStringObj(const bool oneline) const { std::string res; diff --git a/src/rpc/util.h b/src/rpc/util.h index f5edf69713..b5eebf0915 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -37,6 +37,7 @@ extern const std::string EXAMPLE_ADDRESS; class FillableSigningProvider; class CPubKey; class CScript; +struct Sections; /** Wrapper for UniValue::VType, which includes typeAny: * Used to denote don't care type. */ @@ -101,6 +102,16 @@ std::vector<CScript> EvalDescriptorStringOrObject(const UniValue& scanobject, Fl /** Returns, given services flags, a list of humanly readable (known) network services */ UniValue GetServicesNames(ServiceFlags services); +/** + * Serializing JSON objects depends on the outer type. Only arrays and + * dictionaries can be nested in json. The top-level outer type is "NONE". + */ +enum class OuterType { + ARR, + OBJ, + NONE, // Only set on first recursion +}; + struct RPCArg { enum class Type { OBJ, @@ -140,37 +151,37 @@ struct RPCArg { const std::vector<std::string> m_type_str; //!< Should be empty unless it is supposed to override the auto-generated type strings. Vector length is either 0 or 2, m_type_str.at(0) will override the type of the value in a key-value pair, m_type_str.at(1) will override the type in the argument description. RPCArg( - const std::string& name, - const Type& type, - const Fallback& fallback, - const std::string& description, - const std::string& oneline_description = "", - const std::vector<std::string>& type_str = {}) - : m_name{name}, - m_type{type}, - m_fallback{fallback}, - m_description{description}, - m_oneline_description{oneline_description}, - m_type_str{type_str} + const std::string name, + const Type type, + const Fallback fallback, + const std::string description, + const std::string oneline_description = "", + const std::vector<std::string> type_str = {}) + : m_name{std::move(name)}, + m_type{std::move(type)}, + m_fallback{std::move(fallback)}, + m_description{std::move(description)}, + m_oneline_description{std::move(oneline_description)}, + m_type_str{std::move(type_str)} { CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ); } RPCArg( - const std::string& name, - const Type& type, - const Fallback& fallback, - const std::string& description, - const std::vector<RPCArg>& inner, - const std::string& oneline_description = "", - const std::vector<std::string>& type_str = {}) - : m_name{name}, - m_type{type}, - m_inner{inner}, - m_fallback{fallback}, - m_description{description}, - m_oneline_description{oneline_description}, - m_type_str{type_str} + const std::string name, + const Type type, + const Fallback fallback, + const std::string description, + const std::vector<RPCArg> inner, + const std::string oneline_description = "", + const std::vector<std::string> type_str = {}) + : m_name{std::move(name)}, + m_type{std::move(type)}, + m_inner{std::move(inner)}, + m_fallback{std::move(fallback)}, + m_description{std::move(description)}, + m_oneline_description{std::move(oneline_description)}, + m_type_str{std::move(type_str)} { CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ); } @@ -195,21 +206,85 @@ struct RPCArg { }; struct RPCResult { + enum class Type { + OBJ, + ARR, + STR, + NUM, + BOOL, + NONE, + STR_AMOUNT, //!< Special string to represent a floating point amount + STR_HEX, //!< Special string with only hex chars + OBJ_DYN, //!< Special dictionary with keys that are not literals + ARR_FIXED, //!< Special array that has a fixed number of entries + NUM_TIME, //!< Special numeric to denote unix epoch time + ELISION, //!< Special type to denote elision (...) + }; + + const Type m_type; + const std::string m_key_name; //!< Only used for dicts + const std::vector<RPCResult> m_inner; //!< Only used for arrays or dicts + const bool m_optional; + const std::string m_description; const std::string m_cond; - const std::string m_result; - explicit RPCResult(std::string result) - : m_cond{}, m_result{std::move(result)} + RPCResult( + const std::string cond, + const Type type, + const std::string m_key_name, + const bool optional, + const std::string description, + const std::vector<RPCResult> inner = {}) + : m_type{std::move(type)}, + m_key_name{std::move(m_key_name)}, + m_inner{std::move(inner)}, + m_optional{optional}, + m_description{std::move(description)}, + m_cond{std::move(cond)} { - CHECK_NONFATAL(!m_result.empty()); + CHECK_NONFATAL(!m_cond.empty()); + const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN}; + CHECK_NONFATAL(inner_needed != inner.empty()); } - RPCResult(std::string cond, std::string result) - : m_cond{std::move(cond)}, m_result{std::move(result)} + RPCResult( + const std::string cond, + const Type type, + const std::string m_key_name, + const std::string description, + const std::vector<RPCResult> inner = {}) + : RPCResult{cond, type, m_key_name, false, description, inner} {} + + RPCResult( + const Type type, + const std::string m_key_name, + const bool optional, + const std::string description, + const std::vector<RPCResult> inner = {}) + : m_type{std::move(type)}, + m_key_name{std::move(m_key_name)}, + m_inner{std::move(inner)}, + m_optional{optional}, + m_description{std::move(description)}, + m_cond{} { - CHECK_NONFATAL(!m_cond.empty()); - CHECK_NONFATAL(!m_result.empty()); + const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN}; + CHECK_NONFATAL(inner_needed != inner.empty()); } + + RPCResult( + const Type type, + const std::string m_key_name, + const std::string description, + const std::vector<RPCResult> inner = {}) + : RPCResult{type, m_key_name, false, description, inner} {} + + /** Append the sections of the result. */ + void ToSections(Sections& sections, OuterType outer_type = OuterType::NONE, const int current_indent = 0) const; + /** Return the type string of the result when it is in an object (dict). */ + std::string ToStringObj() const; + /** Return the description string, including the result type. */ + std::string ToDescriptionString() const; }; struct RPCResults { diff --git a/src/txmempool.h b/src/txmempool.h index de11d626b4..0de6f28777 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -753,7 +753,7 @@ public: * determine if that transaction has not yet been visited during the current * traversal's epoch. * Algorithms using std::set can be replaced on a one by one basis. - * Both techniques are not fundamentally incomaptible across the codebase. + * Both techniques are not fundamentally incompatible across the codebase. * Generally speaking, however, the remaining use of std::set for mempool * traversal should be viewed as a TODO for replacement with an epoch based * traversal, rather than a preference for std::set over epochs in that diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 7e704a95fe..4253038090 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -688,7 +688,7 @@ UniValue dumpprivkey(const JSONRPCRequest& request) {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for the private key"}, }, RPCResult{ - "\"key\" (string) The private key\n" + RPCResult::Type::STR, "key", "The private key" }, RPCExamples{ HelpExampleCli("dumpprivkey", "\"myaddress\"") @@ -738,9 +738,10 @@ UniValue dumpwallet(const JSONRPCRequest& request) {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The filename with path (either absolute or relative to bitcoind)"}, }, RPCResult{ - "{ (json object)\n" - " \"filename\" : { (string) The filename with full absolute path\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "filename", "The filename with full absolute path"}, + } }, RPCExamples{ HelpExampleCli("dumpwallet", "\"test\"") @@ -1321,19 +1322,21 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) "\"options\""}, }, RPCResult{ - "[ (json array) Response is an array with the same size as the input that has the execution result\n" - " { (json object)\n" - " \"success\" : true|false, (boolean)\n" - " \"warnings\" : [ (json array, optional)\n" - " \"str\", (string)\n" - " ...\n" - " ],\n" - " \"error\" : { (json object, optional)\n" - " ... JSONRPC error\n" - " },\n" - " },\n" - " ...\n" - "]\n" + RPCResult::Type::ARR, "", "Response is an array with the same size as the input that has the execution result", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "success", ""}, + {RPCResult::Type::ARR, "warnings", /* optional */ true, "", + { + {RPCResult::Type::STR, "", ""}, + }}, + {RPCResult::Type::OBJ, "error", /* optional */ true, "", + { + {RPCResult::Type::ELISION, "", "JSONRPC error"}, + }}, + }}, + } }, RPCExamples{ HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, " diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0a9b739fb9..d9d92f8984 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -24,6 +24,7 @@ #include <util/string.h> #include <util/system.h> #include <util/url.h> +#include <util/vector.h> #include <wallet/coincontrol.h> #include <wallet/feebumper.h> #include <wallet/psbtwallet.h> @@ -205,7 +206,7 @@ static UniValue getnewaddress(const JSONRPCRequest& request) {"address_type", RPCArg::Type::STR, /* default */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, }, RPCResult{ - "\"address\" (string) The new bitcoin address\n" + RPCResult::Type::STR, "address", "The new bitcoin address" }, RPCExamples{ HelpExampleCli("getnewaddress", "") @@ -256,7 +257,7 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request) {"address_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, }, RPCResult{ - "\"address\" (string) The address\n" + RPCResult::Type::STR, "address", "The address" }, RPCExamples{ HelpExampleCli("getrawchangeaddress", "") @@ -390,7 +391,7 @@ static UniValue sendtoaddress(const JSONRPCRequest& request) " dirty if they have previously been used in a transaction."}, }, RPCResult{ - "\"txid\" (string) The transaction id.\n" + RPCResult::Type::STR_HEX, "txid", "The transaction id." }, RPCExamples{ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1") @@ -469,17 +470,18 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request) "in past transactions\n", {}, RPCResult{ - "[\n" - " [\n" - " [\n" - " \"address\", (string) The bitcoin address\n" - " amount, (numeric) The amount in " + CURRENCY_UNIT + "\n" - " \"label\" (string, optional) The label\n" - " ]\n" - " ,...\n" - " ]\n" - " ,...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::STR, "address", "The bitcoin address"}, + {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT}, + {RPCResult::Type::STR, "label", /* optional */ true, "The label"}, + }}, + }}, + } }, RPCExamples{ HelpExampleCli("listaddressgroupings", "") @@ -532,7 +534,7 @@ static UniValue signmessage(const JSONRPCRequest& request) {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."}, }, RPCResult{ - "\"signature\" (string) The signature of the message encoded in base 64\n" + RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64" }, RPCExamples{ "\nUnlock the wallet for 30 seconds\n" @@ -601,7 +603,7 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request) {"minconf", RPCArg::Type::NUM, /* default */ "1", "Only include transactions confirmed at least this many times."}, }, RPCResult{ - "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n" + RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received at this address." }, RPCExamples{ "\nThe amount from transactions with at least 1 confirmation\n" @@ -671,7 +673,7 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request) {"minconf", RPCArg::Type::NUM, /* default */ "1", "Only include transactions confirmed at least this many times."}, }, RPCResult{ - "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this label.\n" + RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received for this label." }, RPCExamples{ "\nAmount received by the default label with at least 1 confirmation\n" @@ -743,7 +745,7 @@ static UniValue getbalance(const JSONRPCRequest& request) {"avoid_reuse", RPCArg::Type::BOOL, /* default */ "true", "(only available if avoid_reuse wallet flag is set) Do not include balance in dirty outputs; addresses are considered dirty if they have previously been used in a transaction."}, }, RPCResult{ - "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this wallet.\n" + RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received for this wallet." }, RPCExamples{ "\nThe total amount in the wallet with 1 or more confirmations\n" @@ -845,8 +847,8 @@ static UniValue sendmany(const JSONRPCRequest& request) " \"CONSERVATIVE\""}, }, RPCResult{ - "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n" - " the number of addresses.\n" + RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of\n" + "the number of addresses." }, RPCExamples{ "\nSend two amounts to two different addresses:\n" @@ -969,11 +971,12 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request) {"address_type", RPCArg::Type::STR, /* default */ "set by -addresstype", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."}, }, RPCResult{ - "{\n" - " \"address\" : \"multisigaddress\", (string) The value of the new multisig address.\n" - " \"redeemScript\" : \"script\" (string) The string value of the hex-encoded redemption script.\n" - " \"descriptor\" : \"descriptor\" (string) The descriptor for this multisig\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", "The value of the new multisig address"}, + {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script"}, + {RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"}, + } }, RPCExamples{ "\nAdd a multisig address from 2 addresses\n" @@ -1202,20 +1205,21 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request) {"address_filter", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If present, only return information on this address."}, }, RPCResult{ - "[\n" - " {\n" - " \"involvesWatchonly\" : true, (boolean) Only returns true if imported addresses were involved in transaction.\n" - " \"address\" : \"receivingaddress\", (string) The receiving address\n" - " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n" - " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n" - " \"label\" : \"label\", (string) The label of the receiving address. The default label is \"\".\n" - " \"txids\" : [\n" - " \"txid\", (string) The ids of transactions received with the address \n" - " ...\n" - " ]\n" - " }\n" - " ,...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction"}, + {RPCResult::Type::STR, "address", "The receiving address"}, + {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " received by the address"}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"}, + {RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""}, + {RPCResult::Type::ARR, "txids", "", + { + {RPCResult::Type::STR_HEX, "txid", "The ids of transactions received with the address"}, + }}, + }}, + } }, RPCExamples{ HelpExampleCli("listreceivedbyaddress", "") @@ -1252,15 +1256,16 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request) {"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Whether to include watch-only addresses (see 'importaddress')"}, }, RPCResult{ - "[\n" - " {\n" - " \"involvesWatchonly\" : true, (boolean) Only returns true if imported addresses were involved in transaction.\n" - " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this label\n" - " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n" - " \"label\" : \"label\" (string) The label of the receiving address. The default label is \"\".\n" - " }\n" - " ,...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction"}, + {RPCResult::Type::STR_AMOUNT, "amount", "The total amount received by addresses with this label"}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations of the most recent transaction included"}, + {RPCResult::Type::STR, "label", "The label of the receiving address. The default label is \"\""}, + }}, + } }, RPCExamples{ HelpExampleCli("listreceivedbylabel", "") @@ -1372,26 +1377,26 @@ static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* con } } -static const std::string TransactionDescriptionString() +static const std::vector<RPCResult> TransactionDescriptionString() { - return " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Negative confirmations means the\n" - " transaction conflicted that many blocks ago.\n" - " \"generated\" : xxx, (boolean) Only present if transaction only input is a coinbase one.\n" - " \"trusted\" : xxx, (boolean) Only present if we consider transaction to be trusted and so safe to spend from.\n" - " \"blockhash\" : \"hashvalue\", (string) The block hash containing the transaction.\n" - " \"blockheight\" : n, (numeric) The block height containing the transaction.\n" - " \"blockindex\" : n, (numeric) The index of the transaction in the block that includes it.\n" - " \"blocktime\" : xxx, (numeric) The block time expressed in " + UNIX_EPOCH_TIME + ".\n" - " \"txid\" : \"transactionid\", (string) The transaction id.\n" - " \"walletconflicts\" : [ (json array) Conflicting transaction ids.\n" - " \"txid\", (string) The transaction id.\n" - " ...\n" - " ],\n" - " \"time\" : xxx, (numeric) The transaction time expressed in " + UNIX_EPOCH_TIME + ".\n" - " \"timereceived\" : xxx, (numeric) The time received expressed in " + UNIX_EPOCH_TIME + ".\n" - " \"comment\" : \"...\", (string) If a comment is associated with the transaction, only present if not empty.\n" - " \"bip125-replaceable\" : \"str\", (string) (\"yes|no|unknown\") Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" - " may be unknown for unconfirmed transactions not in the mempool\n"; + return{{RPCResult::Type::NUM, "confirmations", "The number of confirmations for the transaction. Negative confirmations means the\n" + "transaction conflicted that many blocks ago."}, + {RPCResult::Type::BOOL, "generated", "Only present if transaction only input is a coinbase one."}, + {RPCResult::Type::BOOL, "trusted", "Only present if we consider transaction to be trusted and so safe to spend from."}, + {RPCResult::Type::STR_HEX, "blockhash", "The block hash containing the transaction."}, + {RPCResult::Type::NUM, "blockheight", "The block height containing the transaction."}, + {RPCResult::Type::NUM, "blockindex", "The index of the transaction in the block that includes it."}, + {RPCResult::Type::NUM_TIME, "blocktime", "The block time expressed in " + UNIX_EPOCH_TIME + "."}, + {RPCResult::Type::STR_HEX, "txid", "The transaction id."}, + {RPCResult::Type::ARR, "walletconflicts", "Conflicting transaction ids.", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id."}, + }}, + {RPCResult::Type::NUM_TIME, "time", "The transaction time expressed in " + UNIX_EPOCH_TIME + "."}, + {RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."}, + {RPCResult::Type::STR, "comment", "If a comment is associated with the transaction, only present if not empty."}, + {RPCResult::Type::STR, "bip125-replaceable", "(\"yes|no|unknown\") Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" + "may be unknown for unconfirmed transactions not in the mempool"}}; } UniValue listtransactions(const JSONRPCRequest& request) @@ -1414,27 +1419,31 @@ UniValue listtransactions(const JSONRPCRequest& request) {"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Include transactions to watch-only addresses (see 'importaddress')"}, }, RPCResult{ - "[\n" - " {\n" - " \"involvesWatchonly\" : xxx, (boolean) Only returns true if imported addresses were involved in transaction.\n" - " \"address\" : \"address\", (string) The bitcoin address of the transaction.\n" - " \"category\" : (string) The transaction category.\n" - " \"send\" Transactions sent.\n" - " \"receive\" Non-coinbase transactions received.\n" - " \"generate\" Coinbase transactions received with more than 100 confirmations.\n" - " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" - " \"orphan\" Orphaned coinbase transactions received.\n" - " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n" - " for all other categories\n" - " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n" - " \"vout\" : n, (numeric) the vout value\n" - " \"fee\" : x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" - " 'send' category of transactions.\n" - + TransactionDescriptionString() - + " \"abandoned\": xxx (boolean) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" - " 'send' category of transactions.\n" - " }\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>( + { + {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."}, + {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."}, + {RPCResult::Type::STR, "category", "The transaction category.\n" + "\"send\" Transactions sent.\n" + "\"receive\" Non-coinbase transactions received.\n" + "\"generate\" Coinbase transactions received with more than 100 confirmations.\n" + "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" + "\"orphan\" Orphaned coinbase transactions received."}, + {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n" + "for all other categories"}, + {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"}, + {RPCResult::Type::NUM, "vout", "the vout value"}, + {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n" + "'send' category of transactions."}, + }, + TransactionDescriptionString()), + { + {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" + "'send' category of transactions."}, + })}, + } }, RPCExamples{ "\nList the most recent 10 transactions in the systems\n" @@ -1525,34 +1534,39 @@ static UniValue listsinceblock(const JSONRPCRequest& request) " (not guaranteed to work on pruned nodes)"}, }, RPCResult{ - "{ (json object)\n" - " \"transactions\" : [ (json array)\n" - " { (json object)\n" - " \"involvesWatchonly\" : xxx, (boolean) Only returns true if imported addresses were involved in transaction.\n" - " \"address\" : \"str\", (string) The bitcoin address of the transaction.\n" - " \"category\" : \"str\", (string) The transaction category.\n" - " \"send\" Transactions sent.\n" - " \"receive\" Non-coinbase transactions received.\n" - " \"generate\" Coinbase transactions received with more than 100 confirmations.\n" - " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" - " \"orphan\" Orphaned coinbase transactions received.\n" - " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n" - " for all other categories\n" - " \"vout\" : n, (numeric) the vout value\n" - " \"fee\" : x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n" - + TransactionDescriptionString() - + " \"abandoned\": xxx, (boolean) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions.\n" - " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n" - " \"to\" : \"...\", (string) If a comment to is associated with the transaction.\n" - " },\n" - " ...\n" - " ],\n" - " \"removed\" : [ (json array)\n" - " <structure is the same as \"transactions\" above, only present if include_removed=true>\n" - " Note: transactions that were re-added in the active chain will appear as-is in this array, and may thus have a positive confirmation count.\n" - " ],\n" - " \"lastblock\" : \"hex\" (string) The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ARR, "transactions", "", + { + {RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>( + { + {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."}, + {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."}, + {RPCResult::Type::STR, "category", "The transaction category.\n" + "\"send\" Transactions sent.\n" + "\"receive\" Non-coinbase transactions received.\n" + "\"generate\" Coinbase transactions received with more than 100 confirmations.\n" + "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" + "\"orphan\" Orphaned coinbase transactions received."}, + {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n" + "for all other categories"}, + {RPCResult::Type::NUM, "vout", "the vout value"}, + {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n" + "'send' category of transactions."}, + }, + TransactionDescriptionString()), + { + {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" + "'send' category of transactions."}, + {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"}, + {RPCResult::Type::STR, "to", "If a comment to is associated with the transaction."}, + })}, + }}, + {RPCResult::Type::ARR, "removed", "<structure is the same as \"transactions\" above, only present if include_removed=true>\n" + "Note: transactions that were re-added in the active chain will appear as-is in this array, and may thus have a positive confirmation count." + , {{RPCResult::Type::ELISION, "", ""},}}, + {RPCResult::Type::STR_HEX, "lastblock", "The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones"}, + } }, RPCExamples{ HelpExampleCli("listsinceblock", "") @@ -1660,35 +1674,41 @@ static UniValue gettransaction(const JSONRPCRequest& request) "Whether to include a `decoded` field containing the decoded transaction (equivalent to RPC decoderawtransaction)"}, }, RPCResult{ - "{\n" - " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n" - " \"fee\" : x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" - " 'send' category of transactions.\n" - + TransactionDescriptionString() - + " \"details\" : [\n" - " {\n" - " \"involvesWatchonly\" : xxx, (boolean) Only returns true if imported addresses were involved in transaction.\n" - " \"address\" : \"address\", (string) The bitcoin address involved in the transaction\n" - " \"category\" : (string) The transaction category.\n" - " \"send\" Transactions sent.\n" - " \"receive\" Non-coinbase transactions received.\n" - " \"generate\" Coinbase transactions received with more than 100 confirmations.\n" - " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" - " \"orphan\" Orphaned coinbase transactions received.\n" - " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n" - " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n" - " \"vout\" : n, (numeric) the vout value\n" - " \"fee\" : x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" - " 'send' category of transactions.\n" - " \"abandoned\" : xxx (boolean) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" - " 'send' category of transactions.\n" - " }\n" - " ,...\n" - " ],\n" - " \"hex\" : \"data\" (string) Raw data for transaction\n" - " \"decoded\" : transaction (json object) Optional, the decoded transaction (only present when `verbose` is passed), equivalent to the\n" - " RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed.\n" - "}\n" + RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>( + { + {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT}, + {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the\n" + "'send' category of transactions."}, + }, + TransactionDescriptionString()), + { + {RPCResult::Type::ARR, "details", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "involvesWatchonly", "Only returns true if imported addresses were involved in transaction."}, + {RPCResult::Type::STR, "address", "The bitcoin address involved in the transaction."}, + {RPCResult::Type::STR, "category", "The transaction category.\n" + "\"send\" Transactions sent.\n" + "\"receive\" Non-coinbase transactions received.\n" + "\"generate\" Coinbase transactions received with more than 100 confirmations.\n" + "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" + "\"orphan\" Orphaned coinbase transactions received."}, + {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT}, + {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"}, + {RPCResult::Type::NUM, "vout", "the vout value"}, + {RPCResult::Type::STR_AMOUNT, "fee", "The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" + "'send' category of transactions."}, + {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" + "'send' category of transactions."}, + }}, + }}, + {RPCResult::Type::STR_HEX, "hex", "Raw data for transaction"}, + {RPCResult::Type::OBJ, "decoded", "Optional, the decoded transaction (only present when `verbose` is passed)", + { + {RPCResult::Type::ELISION, "", "Equivalent to the RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed."}, + }}, + }) }, RPCExamples{ HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") @@ -2147,7 +2167,7 @@ static UniValue lockunspent(const JSONRPCRequest& request) }, }, RPCResult{ - "true|false (boolean) Whether the command was successful or not\n" + RPCResult::Type::BOOL, "", "Whether the command was successful or not" }, RPCExamples{ "\nList the unspent transactions\n" @@ -2257,13 +2277,14 @@ static UniValue listlockunspent(const JSONRPCRequest& request) "See the lockunspent call to lock and unlock transactions for spending.\n", {}, RPCResult{ - "[\n" - " {\n" - " \"txid\" : \"transactionid\", (string) The transaction id locked\n" - " \"vout\" : n (numeric) The vout value\n" - " }\n" - " ,...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id locked"}, + {RPCResult::Type::NUM, "vout", "The vout value"}, + }}, + } }, RPCExamples{ "\nList the unspent transactions\n" @@ -2313,7 +2334,7 @@ static UniValue settxfee(const JSONRPCRequest& request) {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kB"}, }, RPCResult{ - "true|false (boolean) Returns true if successful\n" + RPCResult::Type::BOOL, "", "Returns true if successful" }, RPCExamples{ HelpExampleCli("settxfee", "0.00001") @@ -2351,19 +2372,23 @@ static UniValue getbalances(const JSONRPCRequest& request) "Returns an object with all balances in " + CURRENCY_UNIT + ".\n", {}, RPCResult{ - "{\n" - " \"mine\" : { (json object) balances from outputs that the wallet can sign\n" - " \"trusted\" : xxx (numeric) trusted balance (outputs created by the wallet or confirmed outputs)\n" - " \"untrusted_pending\" : xxx (numeric) untrusted pending balance (outputs created by others that are in the mempool)\n" - " \"immature\" : xxx (numeric) balance from immature coinbase outputs\n" - " \"used\" : xxx (numeric) (only present if avoid_reuse is set) balance from coins sent to addresses that were previously spent from (potentially privacy violating)\n" - " },\n" - " \"watchonly\" : { (json object) watchonly balances (not present if wallet does not watch anything)\n" - " \"trusted\" : xxx (numeric) trusted balance (outputs created by the wallet or confirmed outputs)\n" - " \"untrusted_pending\" : xxx (numeric) untrusted pending balance (outputs created by others that are in the mempool)\n" - " \"immature\" : xxx (numeric) balance from immature coinbase outputs\n" - " },\n" - "}\n"}, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ, "mine", "balances from outputs that the wallet can sign", + { + {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"}, + {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"}, + {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"}, + {RPCResult::Type::STR_AMOUNT, "used", "(only present if avoid_reuse is set) balance from coins sent to addresses that were previously spent from (potentially privacy violating)"}, + }}, + {RPCResult::Type::OBJ, "watchonly", "watchonly balances (not present if wallet does not watch anything)", + { + {RPCResult::Type::STR_AMOUNT, "trusted", "trusted balance (outputs created by the wallet or confirmed outputs)"}, + {RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"}, + {RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"}, + }}, + } + }, RPCExamples{ HelpExampleCli("getbalances", "") + HelpExampleRpc("getbalances", "")}, @@ -2417,27 +2442,29 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) "Returns an object containing various wallet state info.\n", {}, RPCResult{ - "{\n" - " \"walletname\" : xxxxx, (string) the wallet name\n" - " \"walletversion\" : xxxxx, (numeric) the wallet version\n" - " \"balance\" : xxxxxxx, (numeric) DEPRECATED. Identical to getbalances().mine.trusted\n" - " \"unconfirmed_balance\" : xxx, (numeric) DEPRECATED. Identical to getbalances().mine.untrusted_pending\n" - " \"immature_balance\" : xxxxxx, (numeric) DEPRECATED. Identical to getbalances().mine.immature\n" - " \"txcount\" : xxxxxxx, (numeric) the total number of transactions in the wallet\n" - " \"keypoololdest\" : xxxxxx, (numeric) the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool\n" - " \"keypoolsize\" : xxxx, (numeric) how many new keys are pre-generated (only counts external keys)\n" - " \"keypoolsize_hd_internal\" : xxxx, (numeric) how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)\n" - " \"unlocked_until\" : ttt, (numeric) the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked\n" - " \"paytxfee\" : x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" - " \"hdseedid\" : \"<hash160>\" (string, optional) the Hash160 of the HD seed (only present when HD is enabled)\n" - " \"private_keys_enabled\" : true|false (boolean) false if privatekeys are disabled for this wallet (enforced watch-only wallet)\n" - " \"avoid_reuse\" : true|false (boolean) whether this wallet tracks clean/dirty coins in terms of reuse\n" - " \"scanning\" : (json object) current scanning details, or false if no scan is in progress\n" - " {\n" - " \"duration\" : xxxx (numeric) elapsed seconds since scan start\n" - " \"progress\" : x.xxxx, (numeric) scanning progress percentage [0.0, 1.0]\n" - " }\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + { + {RPCResult::Type::STR, "walletname", "the wallet name"}, + {RPCResult::Type::NUM, "walletversion", "the wallet version"}, + {RPCResult::Type::STR_AMOUNT, "balance", "DEPRECATED. Identical to getbalances().mine.trusted"}, + {RPCResult::Type::STR_AMOUNT, "unconfirmed_balance", "DEPRECATED. Identical to getbalances().mine.untrusted_pending"}, + {RPCResult::Type::STR_AMOUNT, "immature_balance", "DEPRECATED. Identical to getbalances().mine.immature"}, + {RPCResult::Type::NUM, "txcount", "the total number of transactions in the wallet"}, + {RPCResult::Type::NUM_TIME, "keypoololdest", "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool"}, + {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"}, + {RPCResult::Type::NUM, "keypoolsize_hd_internal", "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"}, + {RPCResult::Type::NUM_TIME, "unlocked_until", "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked"}, + {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB"}, + {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true, "the Hash160 of the HD seed (only present when HD is enabled)"}, + {RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"}, + {RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"}, + {RPCResult::Type::OBJ, "scanning", "current scanning details, or false if no scan is in progress", + { + {RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"}, + {RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"}, + }}, + }}, }, RPCExamples{ HelpExampleCli("getwalletinfo", "") @@ -2499,14 +2526,16 @@ static UniValue listwalletdir(const JSONRPCRequest& request) "Returns a list of wallets in the wallet directory.\n", {}, RPCResult{ - "{\n" - " \"wallets\" : [ (json array of objects)\n" - " {\n" - " \"name\" : \"name\" (string) The wallet name\n" - " }\n" - " ,...\n" - " ]\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ARR, "wallets", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "name", "The wallet name"}, + }}, + }}, + } }, RPCExamples{ HelpExampleCli("listwalletdir", "") @@ -2533,10 +2562,10 @@ static UniValue listwallets(const JSONRPCRequest& request) "For full information on the wallet, use \"getwalletinfo\"\n", {}, RPCResult{ - "[ (json array of strings)\n" - " \"walletname\" (string) the wallet name\n" - " ...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::STR, "walletname", "the wallet name"}, + } }, RPCExamples{ HelpExampleCli("listwallets", "") @@ -2569,10 +2598,11 @@ static UniValue loadwallet(const JSONRPCRequest& request) {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet directory or .dat file."}, }, RPCResult{ - "{\n" - " \"name\" : <wallet_name>, (string) The wallet name if loaded successfully.\n" - " \"warning\" : <warning>, (string) Warning message if wallet was not loaded cleanly.\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "name", "The wallet name if loaded successfully."}, + {RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."}, + } }, RPCExamples{ HelpExampleCli("loadwallet", "\"test.dat\"") @@ -2624,11 +2654,12 @@ static UniValue setwalletflag(const JSONRPCRequest& request) {"value", RPCArg::Type::BOOL, /* default */ "true", "The new state."}, }, RPCResult{ - "{\n" - " \"flag_name\" : string (string) The name of the flag that was modified\n" - " \"flag_state\" : bool (boolean) The new state of the flag\n" - " \"warnings\" : string (string) Any warnings associated with the change\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "flag_name", "The name of the flag that was modified"}, + {RPCResult::Type::BOOL, "flag_state", "The new state of the flag"}, + {RPCResult::Type::STR, "warnings", "Any warnings associated with the change"}, + } }, RPCExamples{ HelpExampleCli("setwalletflag", "avoid_reuse") @@ -2684,10 +2715,11 @@ static UniValue createwallet(const JSONRPCRequest& request) {"avoid_reuse", RPCArg::Type::BOOL, /* default */ "false", "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."}, }, RPCResult{ - "{\n" - " \"name\" : <wallet_name>, (string) The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path.\n" - " \"warning\" : <warning>, (string) Warning message if wallet was not loaded cleanly.\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "name", "The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path."}, + {RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."}, + } }, RPCExamples{ HelpExampleCli("createwallet", "\"testwallet\"") @@ -2813,27 +2845,28 @@ static UniValue listunspent(const JSONRPCRequest& request) "query_options"}, }, RPCResult{ - "[ (array of json object)\n" - " {\n" - " \"txid\" : \"txid\", (string) the transaction id \n" - " \"vout\" : n, (numeric) the vout value\n" - " \"address\" : \"address\", (string) the bitcoin address\n" - " \"label\" : \"label\", (string) The associated label, or \"\" for the default label\n" - " \"scriptPubKey\" : \"key\", (string) the script key\n" - " \"amount\" : x.xxx, (numeric) the transaction output amount in " + CURRENCY_UNIT + "\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"redeemScript\" : \"script\" (string) The redeemScript if scriptPubKey is P2SH\n" - " \"witnessScript\" : \"script\" (string) witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH\n" - " \"spendable\" : xxx, (boolean) Whether we have the private keys to spend this output\n" - " \"solvable\" : xxx, (boolean) Whether we know how to spend this output, ignoring the lack of keys\n" - " \"reused\" : xxx, (boolean) (only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)\n" - " \"desc\" : xxx, (string, only when solvable) A descriptor for spending this output\n" - " \"safe\" : xxx (boolean) Whether this output is considered safe to spend. Unconfirmed transactions\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "the transaction id"}, + {RPCResult::Type::NUM, "vout", "the vout value"}, + {RPCResult::Type::STR, "address", "the bitcoin address"}, + {RPCResult::Type::STR, "label", "The associated label, or \"\" for the default label"}, + {RPCResult::Type::STR, "scriptPubKey", "the script key"}, + {RPCResult::Type::STR_AMOUNT, "amount", "the transaction output amount in " + CURRENCY_UNIT}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations"}, + {RPCResult::Type::STR_HEX, "redeemScript", "The redeemScript if scriptPubKey is P2SH"}, + {RPCResult::Type::STR, "witnessScript", "witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH"}, + {RPCResult::Type::BOOL, "spendable", "Whether we have the private keys to spend this output"}, + {RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"}, + {RPCResult::Type::BOOL, "reused", "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"}, + {RPCResult::Type::STR, "desc", "(only when solvable) A descriptor for spending this output"}, + {RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions" " from outside keys and unconfirmed replacement transactions are considered unsafe\n" - " and are not eligible for spending by fundrawtransaction and sendtoaddress.\n" - " }\n" - " ,...\n" - "]\n" + "and are not eligible for spending by fundrawtransaction and sendtoaddress."}, + }}, + } }, RPCExamples{ HelpExampleCli("listunspent", "") @@ -3171,11 +3204,12 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request) }, }, RPCResult{ - "{\n" - " \"hex\" : \"value\", (string) The resulting raw transaction (hex-encoded string)\n" - " \"fee\" : n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n" - " \"changepos\" : n (numeric) The position of the added change output, or -1\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hex", "The resulting raw transaction (hex-encoded string)"}, + {RPCResult::Type::STR_AMOUNT, "fee", "Fee in " + CURRENCY_UNIT + " the resulting transaction pays"}, + {RPCResult::Type::NUM, "changepos", "The position of the added change output, or -1"}, + } }, RPCExamples{ "\nCreate a transaction with no inputs\n" @@ -3250,20 +3284,22 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request) " \"SINGLE|ANYONECANPAY\""}, }, RPCResult{ - "{\n" - " \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n" - " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n" - " \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n" - " {\n" - " \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n" - " \"vout\" : n, (numeric) The index of the output to spent and used as input\n" - " \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n" - " \"sequence\" : n, (numeric) Script sequence number\n" - " \"error\" : \"text\" (string) Verification or signing error related to the input\n" - " }\n" - " ,...\n" - " ]\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"}, + {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"}, + {RPCResult::Type::ARR, "errors", "Script verification errors (if there are any)", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"}, + {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"}, + {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"}, + {RPCResult::Type::NUM, "sequence", "Script sequence number"}, + {RPCResult::Type::STR, "error", "Verification or signing error related to the input"}, + }}, + }}, + } }, RPCExamples{ HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") @@ -3360,13 +3396,16 @@ static UniValue bumpfee(const JSONRPCRequest& request) "options"}, }, RPCResult{ - "{\n" - " \"psbt\" : \"psbt\", (string) The base64-encoded unsigned PSBT of the new transaction. Only returned when wallet private keys are disabled.\n" - " \"txid\" : \"value\", (string) The id of the new transaction. Only returned when wallet private keys are enabled.\n" - " \"origfee\" : n, (numeric) The fee of the replaced transaction.\n" - " \"fee\" : n, (numeric) The fee of the new transaction.\n" - " \"errors\" : [ str... ] (json array of strings) Errors encountered during processing (may be empty).\n" - "}\n" + RPCResult::Type::OBJ, "", "", { + {RPCResult::Type::STR, "psbt", "The base64-encoded unsigned PSBT of the new transaction. Only returned when wallet private keys are disabled."}, + {RPCResult::Type::STR_HEX, "txid", "The id of the new transaction. Only returned when wallet private keys are enabled."}, + {RPCResult::Type::STR_AMOUNT, "origfee", "The fee of the replaced transaction."}, + {RPCResult::Type::STR_AMOUNT, "fee", "The fee of the new transaction."}, + {RPCResult::Type::ARR, "errors", "Errors encountered during processing (may be empty).", + { + {RPCResult::Type::STR, "", ""}, + }}, + } }, RPCExamples{ "\nBump the fee, get the new transaction\'s txid\n" + @@ -3521,10 +3560,11 @@ UniValue rescanblockchain(const JSONRPCRequest& request) {"stop_height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "the last block height that should be scanned. If none is provided it will rescan up to the tip at return time of this call."}, }, RPCResult{ - "{\n" - " \"start_height\" (numeric) The block height where the rescan started (the requested height or 0)\n" - " \"stop_height\" (numeric) The height of the last rescanned block. May be null in rare cases if there was a reorg and the call didn't scan any blocks because they were already scanned in the background.\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "start_height", "The block height where the rescan started (the requested height or 0)"}, + {RPCResult::Type::NUM, "stop_height", "The height of the last rescanned block. May be null in rare cases if there was a reorg and the call didn't scan any blocks because they were already scanned in the background."}, + } }, RPCExamples{ HelpExampleCli("rescanblockchain", "100000 120000") @@ -3729,49 +3769,52 @@ UniValue getaddressinfo(const JSONRPCRequest& request) {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for which to get information."}, }, RPCResult{ - "{\n" - " \"address\" : \"address\", (string) The bitcoin address validated.\n" - " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address.\n" - " \"ismine\" : true|false, (boolean) If the address is yours.\n" - " \"iswatchonly\" : true|false, (boolean) If the address is watchonly.\n" - " \"solvable\" : true|false, (boolean) If we know how to spend coins sent to this address, ignoring the possible lack of private keys.\n" - " \"desc\" : \"desc\", (string, optional) A descriptor for spending coins sent to this address (only when solvable).\n" - " \"isscript\" : true|false, (boolean) If the key is a script.\n" - " \"ischange\" : true|false, (boolean) If the address was used for change output.\n" - " \"iswitness\" : true|false, (boolean) If the address is a witness address.\n" - " \"witness_version\" : version (numeric, optional) The version number of the witness program.\n" - " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program.\n" - " \"script\" : \"type\" (string, optional) The output script type. Only if isscript is true and the redeemscript is known. Possible\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", "The bitcoin address validated."}, + {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address."}, + {RPCResult::Type::BOOL, "ismine", "If the address is yours."}, + {RPCResult::Type::BOOL, "iswatchonly", "If the address is watchonly."}, + {RPCResult::Type::BOOL, "solvable", "If we know how to spend coins sent to this address, ignoring the possible lack of private keys."}, + {RPCResult::Type::STR, "desc", /* optional */ true, "A descriptor for spending coins sent to this address (only when solvable)."}, + {RPCResult::Type::BOOL, "isscript", "If the key is a script."}, + {RPCResult::Type::BOOL, "ischange", "If the address was used for change output."}, + {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address."}, + {RPCResult::Type::NUM, "witness_version", /* optional */ true, "The version number of the witness program."}, + {RPCResult::Type::STR_HEX, "witness_program", /* optional */ true, "The hex value of the witness program."}, + {RPCResult::Type::STR, "script", /* optional */ true, "The output script type. Only if isscript is true and the redeemscript is known. Possible\n" " types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash,\n" - " witness_v0_scripthash, witness_unknown.\n" - " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address.\n" - " \"pubkeys\" (array, optional) Array of pubkeys associated with the known redeemscript (only if script is multisig).\n" - " [\n" - " \"pubkey\" (string)\n" - " ,...\n" - " ]\n" - " \"sigsrequired\" : xxxxx (numeric, optional) The number of signatures required to spend multisig output (only if script is multisig).\n" - " \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key for single-key addresses (possibly embedded in P2SH or P2WSH).\n" - " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. Includes all\n" + "witness_v0_scripthash, witness_unknown."}, + {RPCResult::Type::STR_HEX, "hex", /* optional */ true, "The redeemscript for the p2sh address."}, + {RPCResult::Type::ARR, "pubkeys", /* optional */ true, "Array of pubkeys associated with the known redeemscript (only if script is multisig).", + { + {RPCResult::Type::STR, "pubkey", ""}, + }}, + {RPCResult::Type::NUM, "sigsrequired", /* optional */ true, "The number of signatures required to spend multisig output (only if script is multisig)."}, + {RPCResult::Type::STR_HEX, "pubkey", /* optional */ true, "The hex value of the raw public key for single-key addresses (possibly embedded in P2SH or P2WSH)."}, + {RPCResult::Type::OBJ, "embedded", /* optional */ true, "Information about the address embedded in P2SH or P2WSH, if relevant and known.", + { + {RPCResult::Type::ELISION, "", "Includes all\n" " getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath,\n" - " hdseedid) and relation to the wallet (ismine, iswatchonly).\n" - " \"iscompressed\" : true|false, (boolean, optional) If the pubkey is compressed.\n" - " \"label\" : \"label\" (string) DEPRECATED. The label associated with the address. Defaults to \"\". Replaced by the labels array below.\n" - " \"timestamp\" : timestamp, (number, optional) The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + ".\n" - " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath, if the key is HD and available.\n" - " \"hdseedid\" : \"<hash160>\" (string, optional) The Hash160 of the HD seed.\n" - " \"hdmasterfingerprint\" : \"<hash160>\" (string, optional) The fingerprint of the master key.\n" - " \"labels\" (json array) Array of labels associated with the address. Currently limited to one label but returned\n" - " as an array to keep the API stable if multiple labels are enabled in the future.\n" - " [\n" - " \"label name\" (string) The label name. Defaults to \"\".\n" - " DEPRECATED, will be removed in 0.21. To re-enable, launch bitcoind with `-deprecatedrpc=labelspurpose`:\n" - " {\n" - " \"name\" : \"label name\" (string) The label name. Defaults to \"\".\n" - " \"purpose\" : \"purpose\" (string) The purpose of the associated address (send or receive).\n" - " }\n" - " ]\n" - "}\n" + "hdseedid) and relation to the wallet (ismine, iswatchonly)."}, + }}, + {RPCResult::Type::BOOL, "iscompressed", /* optional */ true, "If the pubkey is compressed."}, + {RPCResult::Type::STR, "label", "DEPRECATED. The label associated with the address. Defaults to \"\". Replaced by the labels array below."}, + {RPCResult::Type::NUM_TIME, "timestamp", /* optional */ true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."}, + {RPCResult::Type::STR, "hdkeypath", /* optional */ true, "The HD keypath, if the key is HD and available."}, + {RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true, "The Hash160 of the HD seed."}, + {RPCResult::Type::STR_HEX, "hdmasterfingerprint", /* optional */ true, "The fingerprint of the master key."}, + {RPCResult::Type::ARR, "labels", "Array of labels associated with the address. Currently limited to one label but returned\n" + "as an array to keep the API stable if multiple labels are enabled in the future.", + { + {RPCResult::Type::STR, "label name", "The label name. Defaults to \"\"."}, + {RPCResult::Type::OBJ, "", "label data, DEPRECATED, will be removed in 0.21. To re-enable, launch bitcoind with `-deprecatedrpc=labelspurpose`", + { + {RPCResult::Type::STR, "name", "The label name. Defaults to \"\"."}, + {RPCResult::Type::STR, "purpose", "The purpose of the associated address (send or receive)."}, + }}, + }}, + } }, RPCExamples{ HelpExampleCli("getaddressinfo", EXAMPLE_ADDRESS) + @@ -3868,11 +3911,13 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request) {"label", RPCArg::Type::STR, RPCArg::Optional::NO, "The label."}, }, RPCResult{ - "{ (json object with addresses as keys)\n" - " \"address\" : { (json object with information about address)\n" - " \"purpose\" : \"string\" (string) Purpose of address (\"send\" for sending address, \"receive\" for receiving address)\n" - " },...\n" - "}\n" + RPCResult::Type::OBJ_DYN, "", "json object with addresses as keys", + { + {RPCResult::Type::OBJ, "address", "json object with information about address", + { + {RPCResult::Type::STR, "purpose", "Purpose of address (\"send\" for sending address, \"receive\" for receiving address)"}, + }}, + } }, RPCExamples{ HelpExampleCli("getaddressesbylabel", "\"tabby\"") @@ -3925,10 +3970,10 @@ static UniValue listlabels(const JSONRPCRequest& request) {"purpose", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Address purpose to list labels for ('send','receive'). An empty string is the same as not providing this argument."}, }, RPCResult{ - "[ (json array of string)\n" - " \"label\", (string) Label name\n" - " ...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::STR, "label", "Label name"}, + } }, RPCExamples{ "\nList all labels\n" @@ -4069,10 +4114,11 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request) {"bip32derivs", RPCArg::Type::BOOL, /* default */ "true", "Include BIP 32 derivation paths for public keys if we know them"}, }, RPCResult{ - "{ (json object)\n" - " \"psbt\" : \"str\", (string) The base64-encoded partially signed transaction\n" - " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction"}, + {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"}, + } }, RPCExamples{ HelpExampleCli("walletprocesspsbt", "\"psbt\"") @@ -4179,11 +4225,12 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request) {"bip32derivs", RPCArg::Type::BOOL, /* default */ "true", "Include BIP 32 derivation paths for public keys if we know them"}, }, RPCResult{ - "{\n" - " \"psbt\" : \"value\", (string) The resulting raw transaction (base64-encoded string)\n" - " \"fee\" : n, (numeric) Fee in " + CURRENCY_UNIT + " the resulting transaction pays\n" - " \"changepos\" : n (numeric) The position of the added change output, or -1\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "psbt", "The resulting raw transaction (base64-encoded string)"}, + {RPCResult::Type::STR_AMOUNT, "fee", "Fee in " + CURRENCY_UNIT + " the resulting transaction pays"}, + {RPCResult::Type::NUM, "changepos", "The position of the added change output, or -1"}, + } }, RPCExamples{ "\nCreate a transaction with no inputs\n" diff --git a/src/zmq/zmqrpc.cpp b/src/zmq/zmqrpc.cpp index 9c9b27a413..0fbefb6023 100644 --- a/src/zmq/zmqrpc.cpp +++ b/src/zmq/zmqrpc.cpp @@ -19,14 +19,15 @@ UniValue getzmqnotifications(const JSONRPCRequest& request) "\nReturns information about the active ZeroMQ notifications.\n", {}, RPCResult{ - "[\n" - " { (json object)\n" - " \"type\" : \"pubhashtx\", (string) Type of notification\n" - " \"address\" : \"...\", (string) Address of the publisher\n" - " \"hwm\" : n (numeric) Outbound message high water mark\n" - " },\n" - " ...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "type", "Type of notification"}, + {RPCResult::Type::STR, "address", "Address of the publisher"}, + {RPCResult::Type::NUM, "hwm", "Outbound message high water mark"}, + }}, + } }, RPCExamples{ HelpExampleCli("getzmqnotifications", "") diff --git a/test/functional/feature_backwards_compatibility.py b/test/functional/feature_backwards_compatibility.py index 7a6e3df702..0db74432e2 100755 --- a/test/functional/feature_backwards_compatibility.py +++ b/test/functional/feature_backwards_compatibility.py @@ -113,7 +113,7 @@ class BackwardsCompatibilityTest(BitcoinTestFramework): # Create another conflicting transaction using RBF tx3_id = self.nodes[1].sendtoaddress(return_address, 1) tx4_id = self.nodes[1].bumpfee(tx3_id)["txid"] - # Abondon transaction, but don't confirm + # Abandon transaction, but don't confirm self.nodes[1].abandontransaction(tx3_id) # w1_v19: regular wallet, created with v0.19 diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh index 63624e3ae0..f59b2c9945 100755 --- a/test/lint/lint-shell.sh +++ b/test/lint/lint-shell.sh @@ -41,7 +41,7 @@ if ! shellcheck "$EXCLUDE" $(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|sec fi if ! command -v yq > /dev/null; then - echo "Skipping Gitian desriptor scripts checking since yq is not installed." + echo "Skipping Gitian descriptor scripts checking since yq is not installed." exit $EXIT_CODE fi diff --git a/test/lint/lint-spelling.ignore-words.txt b/test/lint/lint-spelling.ignore-words.txt index 576ae94098..a7a97eb41f 100644 --- a/test/lint/lint-spelling.ignore-words.txt +++ b/test/lint/lint-spelling.ignore-words.txt @@ -12,3 +12,5 @@ keyserver homogenous setban hist +ser +unselect |