Skip to content

Commit 244daa4

Browse files
author
MarcoFalke
committed
Merge #18607: rpc: Fix named arguments in documentation
fa168d7 rpc: Document all aliases for first arg of listtransactions (MarcoFalke) fa5b1f0 rpc: Document all aliases for second arg of getblock (MarcoFalke) fa86a4b rpc: Rename first arg of generateblock RPC to "output" (MarcoFalke) Pull request description: This fixes a bug found with #18531: * Currently the named argument for `generateblock` is documented as `address/descriptor`, but the server only accepts a named argument of `address`. Fix it by changing the name to `output` for both the documentation and the server code. Also, add tests to prove the server understands the new name `output`. * Unrelated to that, there have been a bunch of aliases in the server code that are not present in the source code of the documentation. Fix that by adding the alias to the source code of the documentation. Only the first alias is displayed in the rendered documentation. Also, add tests to prove the server actually understands all aliases. ACKs for top commit: pierreN: Tested ACK fa168d7 tests, help messages Tree-SHA512: 05e15628e3a667b296f3783d20f764b450b959451b5360c7eaf5993156582d47a0f5882330ca2493b851eb46324d504953b90c875bc88a15c9e8c89eb3ef8d92
2 parents 54f812d + fa168d7 commit 244daa4

File tree

7 files changed

+48
-21
lines changed

7 files changed

+48
-21
lines changed

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ static UniValue getblock(const JSONRPCRequest& request)
809809
"If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n",
810810
{
811811
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
812-
{"verbosity", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"},
812+
{"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"},
813813
},
814814
{
815815
RPCResult{"for verbosity = 0",

src/rpc/mining.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,19 +277,19 @@ static UniValue generateblock(const JSONRPCRequest& request)
277277
RPCHelpMan{"generateblock",
278278
"\nMine a block with a set of ordered transactions immediately to a specified address or descriptor (before the RPC call returns)\n",
279279
{
280-
{"address/descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The address or descriptor to send the newly generated bitcoin to."},
280+
{"output", RPCArg::Type::STR, RPCArg::Optional::NO, "The address or descriptor to send the newly generated bitcoin to."},
281281
{"transactions", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings which are either txids or raw transactions.\n"
282282
"Txids must reference transactions currently in the mempool.\n"
283283
"All transactions must be valid and in valid order, otherwise the block will be rejected.",
284284
{
285285
{"rawtx/txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
286286
},
287-
}
287+
},
288288
},
289289
RPCResult{
290290
RPCResult::Type::OBJ, "", "",
291291
{
292-
{RPCResult::Type::STR_HEX, "hash", "hash of generated block"}
292+
{RPCResult::Type::STR_HEX, "hash", "hash of generated block"},
293293
}
294294
},
295295
RPCExamples{
@@ -1188,7 +1188,7 @@ static const CRPCCommand commands[] =
11881188

11891189
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
11901190
{ "generating", "generatetodescriptor", &generatetodescriptor, {"num_blocks","descriptor","maxtries"} },
1191-
{ "generating", "generateblock", &generateblock, {"address","transactions"} },
1191+
{ "generating", "generateblock", &generateblock, {"output","transactions"} },
11921192

11931193
{ "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
11941194

src/rpc/util.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
#include <tuple>
1515

16+
#include <boost/algorithm/string/classification.hpp>
17+
#include <boost/algorithm/string/split.hpp>
18+
1619
const std::string UNIX_EPOCH_TIME = "UNIX epoch time";
1720
const std::string EXAMPLE_ADDRESS[2] = {"bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl", "bc1q02ad21edsxd23d32dfgqqsz4vv4nmtfzuklhy3"};
1821

@@ -330,7 +333,7 @@ struct Sections {
330333
if (outer_type == OuterType::NONE) return; // Nothing more to do for non-recursive types on first recursion
331334
auto left = indent;
332335
if (arg.m_type_str.size() != 0 && push_name) {
333-
left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0);
336+
left += "\"" + arg.GetName() + "\": " + arg.m_type_str.at(0);
334337
} else {
335338
left += push_name ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false);
336339
}
@@ -341,7 +344,7 @@ struct Sections {
341344
case RPCArg::Type::OBJ:
342345
case RPCArg::Type::OBJ_USER_KEYS: {
343346
const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
344-
PushSection({indent + (push_name ? "\"" + arg.m_name + "\": " : "") + "{", right});
347+
PushSection({indent + (push_name ? "\"" + arg.GetName() + "\": " : "") + "{", right});
345348
for (const auto& arg_inner : arg.m_inner) {
346349
Push(arg_inner, current_indent + 2, OuterType::OBJ);
347350
}
@@ -353,7 +356,7 @@ struct Sections {
353356
}
354357
case RPCArg::Type::ARR: {
355358
auto left = indent;
356-
left += push_name ? "\"" + arg.m_name + "\": " : "";
359+
left += push_name ? "\"" + arg.GetName() + "\": " : "";
357360
left += "[";
358361
const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
359362
PushSection({left, right});
@@ -419,8 +422,12 @@ RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RP
419422
{
420423
std::set<std::string> named_args;
421424
for (const auto& arg : m_args) {
425+
std::vector<std::string> names;
426+
boost::split(names, arg.m_names, boost::is_any_of("|"));
422427
// Should have unique named arguments
423-
CHECK_NONFATAL(named_args.insert(arg.m_name).second);
428+
for (const std::string& name : names) {
429+
CHECK_NONFATAL(named_args.insert(name).second);
430+
}
424431
}
425432
}
426433

@@ -489,7 +496,7 @@ std::string RPCHelpMan::ToString() const
489496
if (i == 0) ret += "\nArguments:\n";
490497

491498
// Push named argument name and description
492-
sections.m_sections.emplace_back(::ToString(i + 1) + ". " + arg.m_name, arg.ToDescriptionString());
499+
sections.m_sections.emplace_back(::ToString(i + 1) + ". " + arg.GetFirstName(), arg.ToDescriptionString());
493500
sections.m_max_pad = std::max(sections.m_max_pad, sections.m_sections.back().m_left.size());
494501

495502
// Recursively push nested args
@@ -506,6 +513,17 @@ std::string RPCHelpMan::ToString() const
506513
return ret;
507514
}
508515

516+
std::string RPCArg::GetFirstName() const
517+
{
518+
return m_names.substr(0, m_names.find("|"));
519+
}
520+
521+
std::string RPCArg::GetName() const
522+
{
523+
CHECK_NONFATAL(std::string::npos == m_names.find("|"));
524+
return m_names;
525+
}
526+
509527
bool RPCArg::IsOptional() const
510528
{
511529
if (m_fallback.which() == 1) {
@@ -681,7 +699,7 @@ std::string RPCArg::ToStringObj(const bool oneline) const
681699
{
682700
std::string res;
683701
res += "\"";
684-
res += m_name;
702+
res += GetFirstName();
685703
if (oneline) {
686704
res += "\":";
687705
} else {
@@ -723,13 +741,13 @@ std::string RPCArg::ToString(const bool oneline) const
723741
switch (m_type) {
724742
case Type::STR_HEX:
725743
case Type::STR: {
726-
return "\"" + m_name + "\"";
744+
return "\"" + GetFirstName() + "\"";
727745
}
728746
case Type::NUM:
729747
case Type::RANGE:
730748
case Type::AMOUNT:
731749
case Type::BOOL: {
732-
return m_name;
750+
return GetFirstName();
733751
}
734752
case Type::OBJ:
735753
case Type::OBJ_USER_KEYS: {

src/rpc/util.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ struct RPCArg {
142142
OMITTED,
143143
};
144144
using Fallback = boost::variant<Optional, /* default value for optional args */ std::string>;
145-
const std::string m_name; //!< The name of the arg (can be empty for inner args)
145+
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)
146146
const Type m_type;
147147
const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts
148148
const Fallback m_fallback;
@@ -157,7 +157,7 @@ struct RPCArg {
157157
const std::string description,
158158
const std::string oneline_description = "",
159159
const std::vector<std::string> type_str = {})
160-
: m_name{std::move(name)},
160+
: m_names{std::move(name)},
161161
m_type{std::move(type)},
162162
m_fallback{std::move(fallback)},
163163
m_description{std::move(description)},
@@ -175,7 +175,7 @@ struct RPCArg {
175175
const std::vector<RPCArg> inner,
176176
const std::string oneline_description = "",
177177
const std::vector<std::string> type_str = {})
178-
: m_name{std::move(name)},
178+
: m_names{std::move(name)},
179179
m_type{std::move(type)},
180180
m_inner{std::move(inner)},
181181
m_fallback{std::move(fallback)},
@@ -188,6 +188,12 @@ struct RPCArg {
188188

189189
bool IsOptional() const;
190190

191+
/** Return the first of all aliases */
192+
std::string GetFirstName() const;
193+
194+
/** Return the name, throws when there are aliases */
195+
std::string GetName() const;
196+
191197
/**
192198
* Return the type string of the argument.
193199
* Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description).

src/wallet/rpcwallet.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,8 +1400,8 @@ UniValue listtransactions(const JSONRPCRequest& request)
14001400
"\nIf a label name is provided, this will return only incoming transactions paying to addresses with the specified label.\n"
14011401
"\nReturns up to 'count' most recent transactions skipping the first 'from' transactions.\n",
14021402
{
1403-
{"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, should be a valid label name to return only incoming transactions\n"
1404-
" with the specified label, or \"*\" to disable filtering and return all transactions."},
1403+
{"label|dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, should be a valid label name to return only incoming transactions\n"
1404+
"with the specified label, or \"*\" to disable filtering and return all transactions."},
14051405
{"count", RPCArg::Type::NUM, /* default */ "10", "The number of transactions to return"},
14061406
{"skip", RPCArg::Type::NUM, /* default */ "0", "The number of transactions to skip"},
14071407
{"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Include transactions to watch-only addresses (see 'importaddress')"},

test/functional/rpc_generateblock.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
assert_raises_rpc_error,
1212
)
1313

14+
1415
class GenerateBlockTest(BitcoinTestFramework):
1516
def set_test_params(self):
1617
self.num_nodes = 1
@@ -23,14 +24,14 @@ def run_test(self):
2324

2425
self.log.info('Generate an empty block to address')
2526
address = node.getnewaddress()
26-
hash = node.generateblock(address, [])['hash']
27-
block = node.getblock(hash, 2)
27+
hash = node.generateblock(output=address, transactions=[])['hash']
28+
block = node.getblock(blockhash=hash, verbose=2)
2829
assert_equal(len(block['tx']), 1)
2930
assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)
3031

3132
self.log.info('Generate an empty block to a descriptor')
3233
hash = node.generateblock('addr(' + address + ')', [])['hash']
33-
block = node.getblock(hash, 2)
34+
block = node.getblock(blockhash=hash, verbosity=2)
3435
assert_equal(len(block['tx']), 1)
3536
assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)
3637

test/functional/wallet_listtransactions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ def run_test(self):
9797
txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
9898
self.nodes[1].generate(1)
9999
self.sync_all()
100+
assert_equal(len(self.nodes[0].listtransactions(label="watchonly", include_watchonly=True)), 1)
101+
assert_equal(len(self.nodes[0].listtransactions(dummy="watchonly", include_watchonly=True)), 1)
100102
assert len(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=False)) == 0
101103
assert_array_result(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=True),
102104
{"category": "receive", "amount": Decimal("0.1")},

0 commit comments

Comments
 (0)