diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 51c88cc1ba..370fd8cfb3 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -807,9 +807,15 @@ UniValue RPCHelpMan::GetArgMap() const for (int i{0}; i < int(m_args.size()); ++i) { const auto& arg = m_args.at(i); std::vector arg_names = SplitString(arg.m_names, '|'); + RPCArg::Type argtype = arg.m_type; + size_t arg_num = 0; for (const auto& arg_name : arg_names) { - push_back_arg_info(m_name, i, arg_name, arg.m_type); - if (arg.m_type == RPCArg::Type::OBJ_NAMED_PARAMS) { + if (!arg.m_type_per_name.empty()) { + argtype = arg.m_type_per_name.at(arg_num++); + } + + push_back_arg_info(m_name, i, arg_name, argtype); + if (argtype == RPCArg::Type::OBJ_NAMED_PARAMS) { for (const auto& inner : arg.m_inner) { std::vector inner_names = SplitString(inner.m_names, '|'); for (const std::string& inner_name : inner_names) { @@ -860,13 +866,15 @@ UniValue RPCArg::MatchesType(const UniValue& request) const { if (m_opts.skip_type_check) return true; if (IsOptional() && request.isNull()) return true; - const auto exp_type{ExpectedType(m_type)}; - if (!exp_type) return true; // nothing to check + for (auto type : m_type_per_name.empty() ? std::vector{m_type} : m_type_per_name) { + const auto exp_type{ExpectedType(type)}; + if (!exp_type) return true; // nothing to check - if (*exp_type != request.getType()) { - return strprintf("JSON value of type %s is not of expected type %s", uvTypeName(request.getType()), uvTypeName(*exp_type)); + if (*exp_type == request.getType()) { + return true; + } } - return true; + return strprintf("JSON value of type %s is not of expected type %s", uvTypeName(request.getType()), uvTypeName(*ExpectedType(m_type))); } std::string RPCArg::GetFirstName() const diff --git a/src/rpc/util.h b/src/rpc/util.h index ad3ed97b2e..9b48141d5d 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -203,6 +204,7 @@ struct RPCArg { 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 std::vector m_type_per_name; const std::vector m_inner; //!< Only used for arrays or dicts const Fallback m_fallback; const std::string m_description; @@ -223,6 +225,24 @@ struct RPCArg { CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ && type != Type::OBJ_NAMED_PARAMS && type != Type::OBJ_USER_KEYS); } + RPCArg( + std::string name, + std::vector types, + Fallback fallback, + std::string description, + std::vector inner = {}, + RPCArgOptions opts = {}) + : m_names{std::move(name)}, + m_type{types.at(0)}, + m_type_per_name{std::move(types)}, + m_inner{std::move(inner)}, + m_fallback{std::move(fallback)}, + m_description{std::move(description)}, + m_opts{std::move(opts)} + { + CHECK_NONFATAL(m_type_per_name.size() == size_t(std::count(m_names.begin(), m_names.end(), '|')) + 1); + } + RPCArg( std::string name, Type type,