rpc: Document all aliases for second arg of getblock

This commit is contained in:
MarcoFalke
2020-04-12 17:09:23 -04:00
parent fa86a4bbfc
commit fa5b1f067f
4 changed files with 39 additions and 14 deletions

View File

@ -812,7 +812,7 @@ static UniValue getblock(const JSONRPCRequest& request)
"If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n", "If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n",
{ {
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
{"verbosity", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"}, {"verbosity|verbose", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"},
}, },
{ {
RPCResult{"for verbosity = 0", RPCResult{"for verbosity = 0",

View File

@ -13,6 +13,9 @@
#include <tuple> #include <tuple>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
const std::string UNIX_EPOCH_TIME = "UNIX epoch time"; const std::string UNIX_EPOCH_TIME = "UNIX epoch time";
const std::string EXAMPLE_ADDRESS[2] = {"bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl", "bc1q02ad21edsxd23d32dfgqqsz4vv4nmtfzuklhy3"}; const std::string EXAMPLE_ADDRESS[2] = {"bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl", "bc1q02ad21edsxd23d32dfgqqsz4vv4nmtfzuklhy3"};
@ -330,7 +333,7 @@ struct Sections {
if (outer_type == OuterType::NONE) 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; auto left = indent;
if (arg.m_type_str.size() != 0 && push_name) { if (arg.m_type_str.size() != 0 && push_name) {
left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0); left += "\"" + arg.GetName() + "\": " + arg.m_type_str.at(0);
} else { } else {
left += push_name ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false); left += push_name ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false);
} }
@ -341,7 +344,7 @@ struct Sections {
case RPCArg::Type::OBJ: case RPCArg::Type::OBJ:
case RPCArg::Type::OBJ_USER_KEYS: { case RPCArg::Type::OBJ_USER_KEYS: {
const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString(); const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
PushSection({indent + (push_name ? "\"" + arg.m_name + "\": " : "") + "{", right}); PushSection({indent + (push_name ? "\"" + arg.GetName() + "\": " : "") + "{", right});
for (const auto& arg_inner : arg.m_inner) { for (const auto& arg_inner : arg.m_inner) {
Push(arg_inner, current_indent + 2, OuterType::OBJ); Push(arg_inner, current_indent + 2, OuterType::OBJ);
} }
@ -353,7 +356,7 @@ struct Sections {
} }
case RPCArg::Type::ARR: { case RPCArg::Type::ARR: {
auto left = indent; auto left = indent;
left += push_name ? "\"" + arg.m_name + "\": " : ""; left += push_name ? "\"" + arg.GetName() + "\": " : "";
left += "["; left += "[";
const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString(); const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
PushSection({left, right}); PushSection({left, right});
@ -419,8 +422,12 @@ RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RP
{ {
std::set<std::string> named_args; std::set<std::string> named_args;
for (const auto& arg : m_args) { for (const auto& arg : m_args) {
std::vector<std::string> names;
boost::split(names, arg.m_names, boost::is_any_of("|"));
// Should have unique named arguments // Should have unique named arguments
CHECK_NONFATAL(named_args.insert(arg.m_name).second); for (const std::string& name : names) {
CHECK_NONFATAL(named_args.insert(name).second);
}
} }
} }
@ -489,7 +496,7 @@ std::string RPCHelpMan::ToString() const
if (i == 0) ret += "\nArguments:\n"; if (i == 0) ret += "\nArguments:\n";
// Push named argument name and description // Push named argument name and description
sections.m_sections.emplace_back(::ToString(i + 1) + ". " + arg.m_name, arg.ToDescriptionString()); sections.m_sections.emplace_back(::ToString(i + 1) + ". " + arg.GetFirstName(), arg.ToDescriptionString());
sections.m_max_pad = std::max(sections.m_max_pad, sections.m_sections.back().m_left.size()); sections.m_max_pad = std::max(sections.m_max_pad, sections.m_sections.back().m_left.size());
// Recursively push nested args // Recursively push nested args
@ -506,6 +513,17 @@ std::string RPCHelpMan::ToString() const
return ret; return ret;
} }
std::string RPCArg::GetFirstName() const
{
return m_names.substr(0, m_names.find("|"));
}
std::string RPCArg::GetName() const
{
CHECK_NONFATAL(std::string::npos == m_names.find("|"));
return m_names;
}
bool RPCArg::IsOptional() const bool RPCArg::IsOptional() const
{ {
if (m_fallback.which() == 1) { if (m_fallback.which() == 1) {
@ -681,7 +699,7 @@ std::string RPCArg::ToStringObj(const bool oneline) const
{ {
std::string res; std::string res;
res += "\""; res += "\"";
res += m_name; res += GetFirstName();
if (oneline) { if (oneline) {
res += "\":"; res += "\":";
} else { } else {
@ -723,13 +741,13 @@ std::string RPCArg::ToString(const bool oneline) const
switch (m_type) { switch (m_type) {
case Type::STR_HEX: case Type::STR_HEX:
case Type::STR: { case Type::STR: {
return "\"" + m_name + "\""; return "\"" + GetFirstName() + "\"";
} }
case Type::NUM: case Type::NUM:
case Type::RANGE: case Type::RANGE:
case Type::AMOUNT: case Type::AMOUNT:
case Type::BOOL: { case Type::BOOL: {
return m_name; return GetFirstName();
} }
case Type::OBJ: case Type::OBJ:
case Type::OBJ_USER_KEYS: { case Type::OBJ_USER_KEYS: {

View File

@ -142,7 +142,7 @@ struct RPCArg {
OMITTED, OMITTED,
}; };
using Fallback = boost::variant<Optional, /* default value for optional args */ std::string>; using Fallback = boost::variant<Optional, /* default value for optional args */ std::string>;
const std::string m_name; //!< The name of the arg (can be empty for inner args) const std::string m_names; //!< The name of the arg (can be empty for inner args, can contain multiple aliases separated by | for named request arguments)
const Type m_type; const Type m_type;
const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts
const Fallback m_fallback; const Fallback m_fallback;
@ -157,7 +157,7 @@ struct RPCArg {
const std::string description, const std::string description,
const std::string oneline_description = "", const std::string oneline_description = "",
const std::vector<std::string> type_str = {}) const std::vector<std::string> type_str = {})
: m_name{std::move(name)}, : m_names{std::move(name)},
m_type{std::move(type)}, m_type{std::move(type)},
m_fallback{std::move(fallback)}, m_fallback{std::move(fallback)},
m_description{std::move(description)}, m_description{std::move(description)},
@ -175,7 +175,7 @@ struct RPCArg {
const std::vector<RPCArg> inner, const std::vector<RPCArg> inner,
const std::string oneline_description = "", const std::string oneline_description = "",
const std::vector<std::string> type_str = {}) const std::vector<std::string> type_str = {})
: m_name{std::move(name)}, : m_names{std::move(name)},
m_type{std::move(type)}, m_type{std::move(type)},
m_inner{std::move(inner)}, m_inner{std::move(inner)},
m_fallback{std::move(fallback)}, m_fallback{std::move(fallback)},
@ -188,6 +188,12 @@ struct RPCArg {
bool IsOptional() const; bool IsOptional() const;
/** Return the first of all aliases */
std::string GetFirstName() const;
/** Return the name, throws when there are aliases */
std::string GetName() const;
/** /**
* Return the type string of the argument. * Return the type string of the argument.
* Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description). * Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description).

View File

@ -11,6 +11,7 @@ from test_framework.util import (
assert_raises_rpc_error, assert_raises_rpc_error,
) )
class GenerateBlockTest(BitcoinTestFramework): class GenerateBlockTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 1 self.num_nodes = 1
@ -24,13 +25,13 @@ class GenerateBlockTest(BitcoinTestFramework):
self.log.info('Generate an empty block to address') self.log.info('Generate an empty block to address')
address = node.getnewaddress() address = node.getnewaddress()
hash = node.generateblock(output=address, transactions=[])['hash'] hash = node.generateblock(output=address, transactions=[])['hash']
block = node.getblock(hash, 2) block = node.getblock(blockhash=hash, verbose=2)
assert_equal(len(block['tx']), 1) assert_equal(len(block['tx']), 1)
assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address) assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)
self.log.info('Generate an empty block to a descriptor') self.log.info('Generate an empty block to a descriptor')
hash = node.generateblock('addr(' + address + ')', [])['hash'] hash = node.generateblock('addr(' + address + ')', [])['hash']
block = node.getblock(hash, 2) block = node.getblock(blockhash=hash, verbosity=2)
assert_equal(len(block['tx']), 1) assert_equal(len(block['tx']), 1)
assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address) assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)