aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2018-10-23 15:22:28 -0400
committerMarcoFalke <falke.marco@gmail.com>2018-11-12 11:11:17 -0500
commitfa483e13b387f244c1c72d4dbd709e669335618e (patch)
treeb488e095c893d0f7da0eb5e2744750e7a1e99dcc /src
parentfa0d36f712c50cce82b275e5f5dbb8ed9601a443 (diff)
rpc: Add RPCHelpMan for machine-generated help
Diffstat (limited to 'src')
-rw-r--r--src/rpc/rawtransaction.cpp89
-rw-r--r--src/rpc/util.cpp92
-rw-r--r--src/rpc/util.h49
-rw-r--r--src/wallet/rpcwallet.cpp107
4 files changed, 327 insertions, 10 deletions
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index a8c6a4086b..950f0181ad 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -206,7 +206,16 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
{
if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2))
throw std::runtime_error(
- "gettxoutproof [\"txid\",...] ( blockhash )\n"
+ RPCHelpMan{"gettxoutproof",
+ {
+ {"txids", RPCArg::Type::ARR,
+ {
+ {"txid", RPCArg::Type::STR_HEX, false},
+ },
+ false},
+ {"blockhash", RPCArg::Type::STR_HEX, true},
+ }}
+ .ToString() +
"\nReturns a hex-encoded proof that \"txid\" was included in a block.\n"
"\nNOTE: By default this function only works sometimes. This is when there is an\n"
"unspent output in the utxo for this transaction. To make it always work,\n"
@@ -673,10 +682,17 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::
static UniValue combinerawtransaction(const JSONRPCRequest& request)
{
-
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "combinerawtransaction [\"hexstring\",...]\n"
+ RPCHelpMan{"combinerawtransaction",
+ {
+ {"txs", RPCArg::Type::ARR,
+ {
+ {"hexstring", RPCArg::Type::STR_HEX, false},
+ },
+ false},
+ }}
+ .ToString() +
"\nCombine multiple partially signed transactions into one transaction.\n"
"The combined transaction may be another partially signed transaction or a \n"
"fully signed transaction."
@@ -899,7 +915,30 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
throw std::runtime_error(
- "signrawtransactionwithkey \"hexstring\" [\"privatekey1\",...] ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] sighashtype )\n"
+ RPCHelpMan{"signrawtransactionwithkey",
+ {
+ {"hexstring", RPCArg::Type::STR, false},
+ {"privkyes", RPCArg::Type::ARR,
+ {
+ {"privatekey", RPCArg::Type::STR_HEX, false},
+ },
+ false},
+ {"prevtxs", RPCArg::Type::ARR,
+ {
+ {"", RPCArg::Type::OBJ,
+ {
+ {"txid", RPCArg::Type::STR_HEX, false},
+ {"vout", RPCArg::Type::NUM, false},
+ {"scriptPubKey", RPCArg::Type::STR_HEX, false},
+ {"redeemScript", RPCArg::Type::STR_HEX, false},
+ {"amount", RPCArg::Type::AMOUNT, false},
+ },
+ true},
+ },
+ true},
+ {"sighashtype", RPCArg::Type::STR, true},
+ }}
+ .ToString() +
"\nSign inputs for raw transaction (serialized, hex-encoded).\n"
"The second argument is an array of base58-encoded private\n"
"keys that will be the only keys used to sign the transaction.\n"
@@ -1454,7 +1493,15 @@ UniValue combinepsbt(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
- "combinepsbt [\"psbt\",...]\n"
+ RPCHelpMan{"combinepsbt",
+ {
+ {"txs", RPCArg::Type::ARR,
+ {
+ {"psbt", RPCArg::Type::STR_HEX, false},
+ },
+ false},
+ }}
+ .ToString() +
"\nCombine multiple partially signed Bitcoin transactions into one transaction.\n"
"Implements the Combiner role.\n"
"\nArguments:\n"
@@ -1570,7 +1617,37 @@ UniValue createpsbt(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
throw std::runtime_error(
- "createpsbt [{\"txid\":\"id\",\"vout\":n},...] [{\"address\":amount},{\"data\":\"hex\"},...] ( locktime ) ( replaceable )\n"
+ RPCHelpMan{"createpsbt",
+ {
+ {"inputs", RPCArg::Type::ARR,
+ {
+ {"", RPCArg::Type::OBJ,
+ {
+ {"txid", RPCArg::Type::STR_HEX, false},
+ {"vout", RPCArg::Type::NUM, false},
+ {"sequence", RPCArg::Type::NUM, true},
+ },
+ false},
+ },
+ false},
+ {"outputs", RPCArg::Type::ARR,
+ {
+ {"", RPCArg::Type::OBJ,
+ {
+ {"address", RPCArg::Type::AMOUNT, false},
+ },
+ true},
+ {"", RPCArg::Type::OBJ,
+ {
+ {"data", RPCArg::Type::STR_HEX, false},
+ },
+ true},
+ },
+ false},
+ {"locktime", RPCArg::Type::NUM, true},
+ {"replaceable", RPCArg::Type::BOOL, true},
+ }}
+ .ToString() +
"\nCreates a transaction in the Partially Signed Transaction format.\n"
"Implements the Creator role.\n"
"\nArguments:\n"
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index ef2d14b90e..6f2450708a 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -128,3 +128,95 @@ UniValue DescribeAddress(const CTxDestination& dest)
{
return boost::apply_visitor(DescribeAddressVisitor(), dest);
}
+
+std::string RPCHelpMan::ToString() const
+{
+ std::string ret;
+
+ ret += m_name;
+ bool is_optional{false};
+ for (const auto& arg : m_args) {
+ ret += " ";
+ if (arg.m_optional) {
+ if (!is_optional) ret += "( ";
+ is_optional = true;
+ } else {
+ // Currently we still support unnamed arguments, so any argument following an optional argument must also be optional
+ // If support for positional arguments is deprecated in the future, remove this line
+ assert(!is_optional);
+ }
+ ret += arg.ToString();
+ }
+ if (is_optional) ret += " )";
+ ret += "\n";
+
+ return ret;
+}
+
+std::string RPCArg::ToStringObj() const
+{
+ std::string res = "\"" + m_name + "\":";
+ switch (m_type) {
+ case Type::STR:
+ return res + "\"str\"";
+ case Type::STR_HEX:
+ return res + "\"hex\"";
+ case Type::NUM:
+ return res + "n";
+ case Type::AMOUNT:
+ return res + "amount";
+ case Type::BOOL:
+ return res + "bool";
+ case Type::ARR:
+ res += "[";
+ for (const auto& i : m_inner) {
+ res += i.ToString() + ",";
+ }
+ return res + "...]";
+ case Type::OBJ:
+ case Type::OBJ_USER_KEYS:
+ // Currently unused, so avoid writing dead code
+ assert(false);
+
+ // no default case, so the compiler can warn about missing cases
+ }
+ assert(false);
+}
+
+std::string RPCArg::ToString() const
+{
+ switch (m_type) {
+ case Type::STR_HEX:
+ case Type::STR: {
+ return "\"" + m_name + "\"";
+ }
+ case Type::NUM:
+ case Type::AMOUNT:
+ case Type::BOOL: {
+ return m_name;
+ }
+ case Type::OBJ:
+ case Type::OBJ_USER_KEYS: {
+ std::string res;
+ for (size_t i = 0; i < m_inner.size();) {
+ res += m_inner[i].ToStringObj();
+ if (++i < m_inner.size()) res += ",";
+ }
+ if (m_type == Type::OBJ) {
+ return "{" + res + "}";
+ } else {
+ return "{" + res + ",...}";
+ }
+ }
+ case Type::ARR: {
+ std::string res;
+ for (const auto& i : m_inner) {
+ res += i.ToString() + ",";
+ }
+ return "[" + res + "...]";
+ }
+
+ // no default case, so the compiler can warn about missing cases
+ }
+ assert(false);
+}
diff --git a/src/rpc/util.h b/src/rpc/util.h
index e21b5ba22a..55ae2fa363 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -30,4 +30,53 @@ CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey
UniValue DescribeAddress(const CTxDestination& dest);
+struct RPCArg {
+ enum class Type {
+ OBJ,
+ ARR,
+ STR,
+ NUM,
+ BOOL,
+ OBJ_USER_KEYS, //!< Special type where the user must set the keys e.g. to define multiple addresses; as opposed to e.g. an options object where the keys are predefined
+ AMOUNT, //!< Special type representing a floating point amount (can be either NUM or STR)
+ STR_HEX, //!< Special type that is a STR with only hex chars
+ };
+ const std::string m_name; //!< The name of the arg (can be empty for inner args)
+ const Type m_type;
+ const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts
+ const bool m_optional;
+
+ RPCArg(const std::string& name, const Type& type, const bool optional)
+ : m_name{name}, m_type{type}, m_optional{optional}
+ {
+ assert(type != Type::ARR && type != Type::OBJ);
+ }
+
+ RPCArg(const std::string& name, const Type& type, const std::vector<RPCArg>& inner, const bool optional)
+ : m_name{name}, m_type{type}, m_inner{inner}, m_optional{optional}
+ {
+ assert(type == Type::ARR || type == Type::OBJ);
+ }
+
+ std::string ToString() const;
+
+private:
+ std::string ToStringObj() const;
+};
+
+class RPCHelpMan
+{
+public:
+ RPCHelpMan(const std::string& name, const std::vector<RPCArg>& args)
+ : m_name{name}, m_args{args}
+ {
+ }
+
+ std::string ToString() const;
+
+private:
+ const std::string m_name;
+ const std::vector<RPCArg> m_args;
+};
+
#endif // BITCOIN_RPC_UTIL_H
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 5a89448e02..8261c48c77 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2075,7 +2075,21 @@ static UniValue lockunspent(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "lockunspent unlock ([{\"txid\":\"txid\",\"vout\":n},...])\n"
+ RPCHelpMan{"lockunspent",
+ {
+ {"unlock", RPCArg::Type::BOOL, false},
+ {"transactions", RPCArg::Type::ARR,
+ {
+ {"", RPCArg::Type::OBJ,
+ {
+ {"txid", RPCArg::Type::STR_HEX, false},
+ {"vout", RPCArg::Type::NUM, false},
+ },
+ true},
+ },
+ true},
+ }}
+ .ToString() +
"\nUpdates list of temporarily unspendable outputs.\n"
"Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
"If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
@@ -2620,7 +2634,26 @@ static UniValue listunspent(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 5)
throw std::runtime_error(
- "listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] [query_options])\n"
+ RPCHelpMan{"listunspent",
+ {
+ {"minconf", RPCArg::Type::NUM, true},
+ {"maxconf", RPCArg::Type::NUM, true},
+ {"addresses", RPCArg::Type::ARR,
+ {
+ {"address", RPCArg::Type::STR_HEX, true},
+ },
+ true},
+ {"include_unsafe", RPCArg::Type::BOOL, true},
+ {"query_options", RPCArg::Type::OBJ,
+ {
+ {"minimumAmount", RPCArg::Type::AMOUNT, true},
+ {"maximumAmount", RPCArg::Type::AMOUNT, true},
+ {"maximumCount", RPCArg::Type::NUM, true},
+ {"minimumSumAmount", RPCArg::Type::AMOUNT, true},
+ },
+ true},
+ }}
+ .ToString() +
"\nReturns array of unspent transaction outputs\n"
"with between minconf and maxconf (inclusive) confirmations.\n"
"Optionally filter to only include txouts paid to specified addresses.\n"
@@ -2995,7 +3028,25 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
- "signrawtransactionwithwallet \"hexstring\" ( [{\"txid\":\"id\",\"vout\":n,\"scriptPubKey\":\"hex\",\"redeemScript\":\"hex\"},...] sighashtype )\n"
+ RPCHelpMan{"signrawtransactionwithwallet",
+ {
+ {"hexstring", RPCArg::Type::STR, false},
+ {"prevtxs", RPCArg::Type::ARR,
+ {
+ {"", RPCArg::Type::OBJ,
+ {
+ {"txid", RPCArg::Type::STR_HEX, false},
+ {"vout", RPCArg::Type::NUM, false},
+ {"scriptPubKey", RPCArg::Type::STR_HEX, false},
+ {"redeemScript", RPCArg::Type::STR_HEX, false},
+ {"amount", RPCArg::Type::AMOUNT, false},
+ },
+ false},
+ },
+ true},
+ {"sighashtype", RPCArg::Type::STR, true},
+ }}
+ .ToString() +
"\nSign inputs for raw transaction (serialized, hex-encoded).\n"
"The second optional argument (may be null) is an array of previous transaction outputs that\n"
"this transaction depends on but may not yet be in the block chain.\n"
@@ -3896,7 +3947,55 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
throw std::runtime_error(
- "walletcreatefundedpsbt [{\"txid\":\"id\",\"vout\":n},...] [{\"address\":amount},{\"data\":\"hex\"},...] ( locktime ) ( replaceable ) ( options bip32derivs )\n"
+ RPCHelpMan{"walletcreatefundedpsbt",
+ {
+ {"inputs", RPCArg::Type::ARR,
+ {
+ {"", RPCArg::Type::OBJ,
+ {
+ {"txid", RPCArg::Type::STR_HEX, false},
+ {"vout", RPCArg::Type::NUM, false},
+ {"sequence", RPCArg::Type::NUM, false},
+ },
+ false},
+ },
+ false},
+ {"outputs", RPCArg::Type::ARR,
+ {
+ {"", RPCArg::Type::OBJ,
+ {
+ {"address", RPCArg::Type::AMOUNT, true},
+ },
+ true},
+ {"", RPCArg::Type::OBJ,
+ {
+ {"data", RPCArg::Type::STR_HEX, true},
+ },
+ true},
+ },
+ false},
+ {"locktime", RPCArg::Type::NUM, true},
+ {"options", RPCArg::Type::OBJ,
+ {
+ {"changeAddress", RPCArg::Type::STR_HEX, true},
+ {"changePosition", RPCArg::Type::NUM, true},
+ {"change_type", RPCArg::Type::STR, true},
+ {"includeWatching", RPCArg::Type::BOOL, true},
+ {"lockUnspents", RPCArg::Type::BOOL, true},
+ {"feeRate", RPCArg::Type::NUM, true},
+ {"subtractFeeFromOutputs", RPCArg::Type::ARR,
+ {
+ {"int", RPCArg::Type::NUM, true},
+ },
+ true},
+ {"replaceable", RPCArg::Type::BOOL, true},
+ {"conf_target", RPCArg::Type::NUM, true},
+ {"estimate_mode", RPCArg::Type::STR, true},
+ },
+ true},
+ {"bip32derivs", RPCArg::Type::BOOL, true},
+ }}
+ .ToString() +
"\nCreates and funds a transaction in the Partially Signed Transaction format. Inputs will be added if supplied inputs are not enough\n"
"Implements the Creator and Updater roles.\n"
"\nArguments:\n"