0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-08 10:31:50 -05:00

Merge bitcoin/bitcoin#26074: refactor: Set RPCArg options with designated initializers

fa2c72dda0 rpc: Set RPCArg options with designated initializers (MacroFake)

Pull request description:

  For optional constructor arguments, use a new struct. This comes with two benefits:
  * Earlier unused optional arguments can be omitted
  * Designated initializers can be used

ACKs for top commit:
  stickies-v:
    re-ACK fa2c72dda0

Tree-SHA512: 2a0619548187cc7437fee2466ac4780746490622f202659f53641be01bc2a1fea4416d1a77f3e963bf7c4cce62899b61fab0b9683440cf82f68be44f63826658
This commit is contained in:
MacroFake 2022-09-30 10:03:27 +02:00
commit 33eef562a3
No known key found for this signature in database
GPG key ID: CE2B75697E69A548
8 changed files with 47 additions and 49 deletions

View file

@ -856,7 +856,7 @@ static RPCHelpMan gettxoutsetinfo()
"Note this call may take some time if you are not using coinstatsindex.\n", "Note this call may take some time if you are not using coinstatsindex.\n",
{ {
{"hash_type", RPCArg::Type::STR, RPCArg::Default{"hash_serialized_2"}, "Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'."}, {"hash_type", RPCArg::Type::STR, RPCArg::Default{"hash_serialized_2"}, "Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'."},
{"hash_or_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"the current best block"}, "The block hash or height of the target height (only available with coinstatsindex).", "", {"", "string or numeric"}}, {"hash_or_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"the current best block"}, "The block hash or height of the target height (only available with coinstatsindex).", RPCArgOptions{.type_str={"", "string or numeric"}}},
{"use_index", RPCArg::Type::BOOL, RPCArg::Default{true}, "Use coinstatsindex, if available."}, {"use_index", RPCArg::Type::BOOL, RPCArg::Default{true}, "Use coinstatsindex, if available."},
}, },
RPCResult{ RPCResult{
@ -1726,13 +1726,13 @@ static RPCHelpMan getblockstats()
"\nCompute per block statistics for a given window. All amounts are in satoshis.\n" "\nCompute per block statistics for a given window. All amounts are in satoshis.\n"
"It won't work for some heights with pruning.\n", "It won't work for some heights with pruning.\n",
{ {
{"hash_or_height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block hash or height of the target block", "", {"", "string or numeric"}}, {"hash_or_height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block hash or height of the target block", RPCArgOptions{.type_str={"", "string or numeric"}}},
{"stats", RPCArg::Type::ARR, RPCArg::DefaultHint{"all values"}, "Values to plot (see result below)", {"stats", RPCArg::Type::ARR, RPCArg::DefaultHint{"all values"}, "Values to plot (see result below)",
{ {
{"height", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"}, {"height", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"},
{"time", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"}, {"time", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"},
}, },
"stats"}, RPCArgOptions{.oneline_description="stats"}},
}, },
RPCResult{ RPCResult{
RPCResult::Type::OBJ, "", "", RPCResult::Type::OBJ, "", "",
@ -2052,7 +2052,7 @@ static RPCHelpMan scantxoutset()
{"range", RPCArg::Type::RANGE, RPCArg::Default{1000}, "The range of HD chain indexes to explore (either end or [begin,end])"}, {"range", RPCArg::Type::RANGE, RPCArg::Default{1000}, "The range of HD chain indexes to explore (either end or [begin,end])"},
}}, }},
}, },
"[scanobjects,...]"}, RPCArgOptions{.oneline_description="[scanobjects,...]"}},
}, },
{ {
RPCResult{"when action=='start'; only returns after scan completes", RPCResult::Type::OBJ, "", "", { RPCResult{"when action=='start'; only returns after scan completes", RPCResult::Type::OBJ, "", "", {

View file

@ -524,7 +524,7 @@ static RPCHelpMan getblocktemplate()
{"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "other client side supported softfork deployment"}, {"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "other client side supported softfork deployment"},
}}, }},
}, },
"\"template_request\""}, RPCArgOptions{.oneline_description="\"template_request\""}},
}, },
{ {
RPCResult{"If the proposal was accepted with mode=='proposal'", RPCResult::Type::NONE, "", ""}, RPCResult{"If the proposal was accepted with mode=='proposal'", RPCResult::Type::NONE, "", ""},

View file

@ -168,7 +168,7 @@ static RPCHelpMan stop()
// to the client (intended for testing) // to the client (intended for testing)
"\nRequest a graceful shutdown of " PACKAGE_NAME ".", "\nRequest a graceful shutdown of " PACKAGE_NAME ".",
{ {
{"wait", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "how long to wait in ms", "", {}, /*hidden=*/true}, {"wait", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "how long to wait in ms", RPCArgOptions{.hidden=true}},
}, },
RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"}, RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"},
RPCExamples{""}, RPCExamples{""},

View file

@ -418,8 +418,8 @@ struct Sections {
case RPCArg::Type::BOOL: { case RPCArg::Type::BOOL: {
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_opts.type_str.size() != 0 && push_name) {
left += "\"" + arg.GetName() + "\": " + arg.m_type_str.at(0); left += "\"" + arg.GetName() + "\": " + arg.m_opts.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);
} }
@ -618,7 +618,7 @@ std::string RPCHelpMan::ToString() const
ret += m_name; ret += m_name;
bool was_optional{false}; bool was_optional{false};
for (const auto& arg : m_args) { for (const auto& arg : m_args) {
if (arg.m_hidden) break; // Any arg that follows is also hidden if (arg.m_opts.hidden) break; // Any arg that follows is also hidden
const bool optional = arg.IsOptional(); const bool optional = arg.IsOptional();
ret += " "; ret += " ";
if (optional) { if (optional) {
@ -639,7 +639,7 @@ std::string RPCHelpMan::ToString() const
Sections sections; Sections sections;
for (size_t i{0}; i < m_args.size(); ++i) { for (size_t i{0}; i < m_args.size(); ++i) {
const auto& arg = m_args.at(i); const auto& arg = m_args.at(i);
if (arg.m_hidden) break; // Any arg that follows is also hidden if (arg.m_opts.hidden) break; // Any arg that follows is also hidden
if (i == 0) ret += "\nArguments:\n"; if (i == 0) ret += "\nArguments:\n";
@ -704,8 +704,8 @@ std::string RPCArg::ToDescriptionString() const
{ {
std::string ret; std::string ret;
ret += "("; ret += "(";
if (m_type_str.size() != 0) { if (m_opts.type_str.size() != 0) {
ret += m_type_str.at(1); ret += m_opts.type_str.at(1);
} else { } else {
switch (m_type) { switch (m_type) {
case Type::STR_HEX: case Type::STR_HEX:
@ -991,7 +991,7 @@ std::string RPCArg::ToStringObj(const bool oneline) const
std::string RPCArg::ToString(const bool oneline) const std::string RPCArg::ToString(const bool oneline) const
{ {
if (oneline && !m_oneline_description.empty()) return m_oneline_description; if (oneline && !m_opts.oneline_description.empty()) return m_opts.oneline_description;
switch (m_type) { switch (m_type) {
case Type::STR_HEX: case Type::STR_HEX:

View file

@ -137,6 +137,12 @@ enum class OuterType {
NONE, // Only set on first recursion NONE, // Only set on first recursion
}; };
struct RPCArgOptions {
std::string oneline_description{}; //!< Should be empty unless it is supposed to override the auto-generated summary line
std::vector<std::string> type_str{}; //!< Should be empty unless it is supposed to override the auto-generated type strings. Vector length is either 0 or 2, m_opts.type_str.at(0) will override the type of the value in a key-value pair, m_opts.type_str.at(1) will override the type in the argument description.
bool hidden{false}; //!< For testing only
};
struct RPCArg { struct RPCArg {
enum class Type { enum class Type {
OBJ, OBJ,
@ -169,30 +175,25 @@ struct RPCArg {
using DefaultHint = std::string; using DefaultHint = std::string;
using Default = UniValue; using Default = UniValue;
using Fallback = std::variant<Optional, /* hint for default value */ DefaultHint, /* default constant value */ Default>; using Fallback = std::variant<Optional, /* hint for default value */ DefaultHint, /* default constant value */ Default>;
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 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 bool m_hidden;
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;
const std::string m_description; const std::string m_description;
const std::string m_oneline_description; //!< Should be empty unless it is supposed to override the auto-generated summary line const RPCArgOptions m_opts;
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( RPCArg(
const std::string name, const std::string name,
const Type type, const Type type,
const Fallback fallback, const Fallback fallback,
const std::string description, const std::string description,
const std::string oneline_description = "", RPCArgOptions opts = {})
const std::vector<std::string> type_str = {},
const bool hidden = false)
: m_names{std::move(name)}, : m_names{std::move(name)},
m_type{std::move(type)}, m_type{std::move(type)},
m_hidden{hidden},
m_fallback{std::move(fallback)}, m_fallback{std::move(fallback)},
m_description{std::move(description)}, m_description{std::move(description)},
m_oneline_description{std::move(oneline_description)}, m_opts{std::move(opts)}
m_type_str{std::move(type_str)}
{ {
CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ && type != Type::OBJ_USER_KEYS); CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ && type != Type::OBJ_USER_KEYS);
} }
@ -203,16 +204,13 @@ struct RPCArg {
const Fallback fallback, const Fallback fallback,
const std::string description, const std::string description,
const std::vector<RPCArg> inner, const std::vector<RPCArg> inner,
const std::string oneline_description = "", RPCArgOptions opts = {})
const std::vector<std::string> type_str = {})
: m_names{std::move(name)}, : m_names{std::move(name)},
m_type{std::move(type)}, m_type{std::move(type)},
m_hidden{false},
m_inner{std::move(inner)}, m_inner{std::move(inner)},
m_fallback{std::move(fallback)}, m_fallback{std::move(fallback)},
m_description{std::move(description)}, m_description{std::move(description)},
m_oneline_description{std::move(oneline_description)}, m_opts{std::move(opts)}
m_type_str{std::move(type_str)}
{ {
CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ || type == Type::OBJ_USER_KEYS); CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ || type == Type::OBJ_USER_KEYS);
} }
@ -227,7 +225,7 @@ struct RPCArg {
/** /**
* 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_opts.oneline_description).
*/ */
std::string ToString(bool oneline) const; std::string ToString(bool oneline) const;
/** /**

View file

@ -1266,15 +1266,15 @@ RPCHelpMan importmulti()
{ {
{"desc", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Descriptor to import. If using descriptor, do not also provide address/scriptPubKey, scripts, or pubkeys"}, {"desc", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Descriptor to import. If using descriptor, do not also provide address/scriptPubKey, scripts, or pubkeys"},
{"scriptPubKey", RPCArg::Type::STR, RPCArg::Optional::NO, "Type of scriptPubKey (string for script, json for address). Should not be provided if using a descriptor", {"scriptPubKey", RPCArg::Type::STR, RPCArg::Optional::NO, "Type of scriptPubKey (string for script, json for address). Should not be provided if using a descriptor",
/*oneline_description=*/"", {"\"<script>\" | { \"address\":\"<address>\" }", "string / json"} RPCArgOptions{.type_str={"\"<script>\" | { \"address\":\"<address>\" }", "string / json"}}
}, },
{"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Creation time of the key expressed in " + UNIX_EPOCH_TIME + ",\n" {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Creation time of the key expressed in " + UNIX_EPOCH_TIME + ",\n"
" or the string \"now\" to substitute the current synced blockchain time. The timestamp of the oldest\n" "or the string \"now\" to substitute the current synced blockchain time. The timestamp of the oldest\n"
" key will determine how far back blockchain rescans need to begin for missing wallet transactions.\n" "key will determine how far back blockchain rescans need to begin for missing wallet transactions.\n"
" \"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n" "\"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n"
" 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n" "0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n"
" creation time of all keys being imported by the importmulti call will be scanned.", "creation time of all keys being imported by the importmulti call will be scanned.",
/*oneline_description=*/"", {"timestamp | \"now\"", "integer / string"} RPCArgOptions{.type_str={"timestamp | \"now\"", "integer / string"}}
}, },
{"redeemscript", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Allowed only if the scriptPubKey is a P2SH or P2SH-P2WSH address/scriptPubKey"}, {"redeemscript", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Allowed only if the scriptPubKey is a P2SH or P2SH-P2WSH address/scriptPubKey"},
{"witnessscript", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Allowed only if the scriptPubKey is a P2SH-P2WSH or P2WSH address/scriptPubKey"}, {"witnessscript", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Allowed only if the scriptPubKey is a P2SH-P2WSH or P2WSH address/scriptPubKey"},
@ -1296,12 +1296,12 @@ RPCHelpMan importmulti()
}, },
}, },
}, },
"\"requests\""}, RPCArgOptions{.oneline_description="\"requests\""}},
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "", {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
{ {
{"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Scan the chain and mempool for wallet transactions after all imports."}, {"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Scan the chain and mempool for wallet transactions after all imports."},
}, },
"\"options\""}, RPCArgOptions{.oneline_description="\"options\""}},
}, },
RPCResult{ RPCResult{
RPCResult::Type::ARR, "", "Response is an array with the same size as the input that has the execution result", RPCResult::Type::ARR, "", "Response is an array with the same size as the input that has the execution result",
@ -1609,18 +1609,18 @@ RPCHelpMan importdescriptors()
{"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED, "If a ranged descriptor is used, this specifies the end or the range (in the form [begin,end]) to import"}, {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED, "If a ranged descriptor is used, this specifies the end or the range (in the form [begin,end]) to import"},
{"next_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If a ranged descriptor is set to active, this specifies the next index to generate addresses from"}, {"next_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "If a ranged descriptor is set to active, this specifies the next index to generate addresses from"},
{"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Time from which to start rescanning the blockchain for this descriptor, in " + UNIX_EPOCH_TIME + "\n" {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Time from which to start rescanning the blockchain for this descriptor, in " + UNIX_EPOCH_TIME + "\n"
" Use the string \"now\" to substitute the current synced blockchain time.\n" "Use the string \"now\" to substitute the current synced blockchain time.\n"
" \"now\" can be specified to bypass scanning, for outputs which are known to never have been used, and\n" "\"now\" can be specified to bypass scanning, for outputs which are known to never have been used, and\n"
" 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest timestamp\n" "0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest timestamp\n"
"of all descriptors being imported will be scanned as well as the mempool.", "of all descriptors being imported will be scanned as well as the mempool.",
/*oneline_description=*/"", {"timestamp | \"now\"", "integer / string"} RPCArgOptions{.type_str={"timestamp | \"now\"", "integer / string"}}
}, },
{"internal", RPCArg::Type::BOOL, RPCArg::Default{false}, "Whether matching outputs should be treated as not incoming payments (e.g. change)"}, {"internal", RPCArg::Type::BOOL, RPCArg::Default{false}, "Whether matching outputs should be treated as not incoming payments (e.g. change)"},
{"label", RPCArg::Type::STR, RPCArg::Default{""}, "Label to assign to the address, only allowed with internal=false. Disabled for ranged descriptors"}, {"label", RPCArg::Type::STR, RPCArg::Default{""}, "Label to assign to the address, only allowed with internal=false. Disabled for ranged descriptors"},
}, },
}, },
}, },
"\"requests\""}, RPCArgOptions{.oneline_description="\"requests\""}},
}, },
RPCResult{ RPCResult{
RPCResult::Type::ARR, "", "Response is an array with the same size as the input that has the execution result", RPCResult::Type::ARR, "", "Response is an array with the same size as the input that has the execution result",

View file

@ -516,7 +516,7 @@ RPCHelpMan listunspent()
{"maximumCount", RPCArg::Type::NUM, RPCArg::DefaultHint{"unlimited"}, "Maximum number of UTXOs"}, {"maximumCount", RPCArg::Type::NUM, RPCArg::DefaultHint{"unlimited"}, "Maximum number of UTXOs"},
{"minimumSumAmount", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"unlimited"}, "Minimum sum value of all UTXOs in " + CURRENCY_UNIT + ""}, {"minimumSumAmount", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"unlimited"}, "Minimum sum value of all UTXOs in " + CURRENCY_UNIT + ""},
}, },
"query_options"}, RPCArgOptions{.oneline_description="query_options"}},
}, },
RPCResult{ RPCResult{
RPCResult::Type::ARR, "", "", RPCResult::Type::ARR, "", "",

View file

@ -317,7 +317,7 @@ RPCHelpMan sendmany()
"\nSend multiple times. Amounts are double-precision floating point numbers." + "\nSend multiple times. Amounts are double-precision floating point numbers." +
HELP_REQUIRING_PASSPHRASE, HELP_REQUIRING_PASSPHRASE,
{ {
{"dummy", RPCArg::Type::STR, RPCArg::Optional::NO, "Must be set to \"\" for backwards compatibility.", "\"\""}, {"dummy", RPCArg::Type::STR, RPCArg::Optional::NO, "Must be set to \"\" for backwards compatibility.", RPCArgOptions{.oneline_description="\"\""}},
{"amounts", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::NO, "The addresses and amounts", {"amounts", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::NO, "The addresses and amounts",
{ {
{"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"}, {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value"},
@ -774,7 +774,7 @@ RPCHelpMan fundrawtransaction()
}, },
}, },
FundTxDoc()), FundTxDoc()),
"options"}, RPCArgOptions{.oneline_description="options"}},
{"iswitness", RPCArg::Type::BOOL, RPCArg::DefaultHint{"depends on heuristic tests"}, "Whether the transaction hex is a serialized witness transaction.\n" {"iswitness", RPCArg::Type::BOOL, RPCArg::DefaultHint{"depends on heuristic tests"}, "Whether the transaction hex is a serialized witness transaction.\n"
"If iswitness is not present, heuristic tests will be used in decoding.\n" "If iswitness is not present, heuristic tests will be used in decoding.\n"
"If true, only witness deserialization will be tried.\n" "If true, only witness deserialization will be tried.\n"
@ -968,7 +968,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
{"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n" {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
"\"" + FeeModes("\"\n\"") + "\""}, "\"" + FeeModes("\"\n\"") + "\""},
}, },
"options"}, RPCArgOptions{.oneline_description="options"}},
}, },
RPCResult{ RPCResult{
RPCResult::Type::OBJ, "", "", Cat( RPCResult::Type::OBJ, "", "", Cat(
@ -1173,7 +1173,7 @@ RPCHelpMan send()
}, },
}, },
FundTxDoc()), FundTxDoc()),
"options"}, RPCArgOptions{.oneline_description="options"}},
}, },
RPCResult{ RPCResult{
RPCResult::Type::OBJ, "", "", RPCResult::Type::OBJ, "", "",
@ -1281,7 +1281,7 @@ RPCHelpMan sendall()
}, },
FundTxDoc() FundTxDoc()
), ),
"options" RPCArgOptions{.oneline_description="options"}
}, },
}, },
RPCResult{ RPCResult{
@ -1611,7 +1611,7 @@ RPCHelpMan walletcreatefundedpsbt()
}, },
}, },
FundTxDoc()), FundTxDoc()),
"options"}, RPCArgOptions{.oneline_description="options"}},
{"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"}, {"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},
}, },
RPCResult{ RPCResult{