cli: Allow arguments to be both strings and json

This commit is contained in:
Ava Chow 2025-08-20 11:39:20 -07:00
parent ad4a49090d
commit 44a493e150
2 changed files with 24 additions and 12 deletions

View File

@ -18,6 +18,7 @@ public:
std::string methodName; //!< method whose params want conversion
int paramIdx; //!< 0-based idx of param to convert
std::string paramName; //!< parameter name
bool also_string{false}; //!< The parameter is also a string
};
// clang-format off
@ -188,10 +189,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "gettxout", 1, "n" },
{ "gettxout", 2, "include_mempool" },
{ "gettxoutproof", 0, "txids" },
{ "gettxoutsetinfo", 1, "hash_or_height" },
{ "gettxoutsetinfo", 1, "hash_or_height", /*also_string=*/true },
{ "gettxoutsetinfo", 2, "use_index"},
{ "dumptxoutset", 2, "options" },
{ "dumptxoutset", 2, "rollback" },
{ "dumptxoutset", 2, "rollback", /*also_string=*/true },
{ "lockunspent", 0, "unlock" },
{ "lockunspent", 1, "transactions" },
{ "lockunspent", 2, "persistent" },
@ -246,7 +247,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listdescriptors", 0, "private" },
{ "verifychain", 0, "checklevel" },
{ "verifychain", 1, "nblocks" },
{ "getblockstats", 0, "hash_or_height" },
{ "getblockstats", 0, "hash_or_height", /*also_string=*/true },
{ "getblockstats", 1, "stats" },
{ "pruneblockchain", 0, "height" },
{ "keypoolrefill", 0, "newsize" },
@ -318,18 +319,21 @@ static const CRPCConvertParam vRPCConvertParams[] =
// clang-format on
/** Parse string to UniValue or throw runtime_error if string contains invalid JSON */
static UniValue Parse(std::string_view raw)
static UniValue Parse(std::string_view raw, bool also_string)
{
UniValue parsed;
if (!parsed.read(raw)) throw std::runtime_error(tfm::format("Error parsing JSON: %s", raw));
if (!parsed.read(raw)) {
if (!also_string) throw std::runtime_error(tfm::format("Error parsing JSON: %s", raw));
return raw;
}
return parsed;
}
class CRPCConvertTable
{
private:
std::set<std::pair<std::string, int>> members;
std::set<std::pair<std::string, std::string>> membersByName;
std::map<std::pair<std::string, int>, bool> members;
std::map<std::pair<std::string, std::string>, bool> membersByName;
public:
CRPCConvertTable();
@ -337,21 +341,29 @@ public:
/** Return arg_value as UniValue, and first parse it if it is a non-string parameter */
UniValue ArgToUniValue(std::string_view arg_value, const std::string& method, int param_idx)
{
return members.count({method, param_idx}) > 0 ? Parse(arg_value) : arg_value;
const auto& it = members.find({method, param_idx});
if (it != members.end()) {
return Parse(arg_value, it->second);
}
return arg_value;
}
/** Return arg_value as UniValue, and first parse it if it is a non-string parameter */
UniValue ArgToUniValue(std::string_view arg_value, const std::string& method, const std::string& param_name)
{
return membersByName.count({method, param_name}) > 0 ? Parse(arg_value) : arg_value;
const auto& it = membersByName.find({method, param_name});
if (it != membersByName.end()) {
return Parse(arg_value, it->second);
}
return arg_value;
}
};
CRPCConvertTable::CRPCConvertTable()
{
for (const auto& cp : vRPCConvertParams) {
members.emplace(cp.methodName, cp.paramIdx);
membersByName.emplace(cp.methodName, cp.paramName);
members.emplace(std::make_pair(cp.methodName, cp.paramIdx), cp.also_string);
membersByName.emplace(std::make_pair(cp.methodName, cp.paramName), cp.also_string);
}
}

View File

@ -32,7 +32,7 @@ def process_mapping(fname):
if line.startswith('};'):
in_rpcs = False
elif '{' in line and '"' in line:
m = re.search(r'{ *("[^"]*"), *([0-9]+) *, *("[^"]*") *},', line)
m = re.search(r'{ *("[^"]*"), *([0-9]+) *, *("[^"]*") *(, \/\*also_string=\*\/true *)?},', line)
assert m, 'No match to table expression: %s' % line
name = parse_string(m.group(1))
idx = int(m.group(2))