refactor: Add and use RPCResultOptions
What changed, and why it matters
This is a small internal code cleanup in Bitcoin Core's RPC help system. It replaces a single boolean flag (`skip_type_check`) with a small options structure (`RPCResultOptions`) so future options can be added more easily. No behavior changes, no security fixes, and no user-facing changes.
No security action required. Treat as normal code-quality refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors RPCResult constructors to accept an RPCResultOptions struct instead of a raw bool skip_type_check. The MatchesType check now reads m_opts.skip_type_check. Call sites in getdescriptoractivity and getwalletinfo are updated to use designated-initializer syntax {.skip_type_check=true}. This is purely a maintainability refactor with identical runtime semantics.
Changed components
src/rpc/util.hsrc/rpc/util.cppsrc/rpc/blockchain.cppsrc/wallet/rpc/wallet.cppInspect captured patch +17 / −12
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index d97b7c6c..cdbaafe0 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -2739,7 +2739,7 @@ static RPCHelpMan getdescriptoractivity()
{RPCResult::Type::OBJ, "output_spk", "", ScriptPubKeyDoc()},
}},
// TODO is the skip_type_check avoidable with a heterogeneous ARR?
- }, /*skip_type_check=*/true},
+ }, {.skip_type_check=true}, },
},
},
RPCExamples{
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 49569c7b..75cfa8d3 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -1130,7 +1130,7 @@ static std::optional<UniValue::VType> ExpectedType(RPCResult::Type type)
// NOLINTNEXTLINE(misc-no-recursion)
UniValue RPCResult::MatchesType(const UniValue& result) const
{
- if (m_skip_type_check) {
+ if (m_opts.skip_type_check) {
return true;
}
diff --git a/src/rpc/util.h b/src/rpc/util.h
index 37530876..a3f95964 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -292,6 +292,9 @@ struct RPCArg {
std::string ToDescriptionString(bool is_named_arg) const;
};
+struct RPCResultOptions {
+ bool skip_type_check{false};
+};
// NOLINTNEXTLINE(misc-no-recursion)
struct RPCResult {
enum class Type {
@@ -314,7 +317,7 @@ struct RPCResult {
const std::string m_key_name; //!< Only used for dicts
const std::vector<RPCResult> m_inner; //!< Only used for arrays or dicts
const bool m_optional;
- const bool m_skip_type_check;
+ const RPCResultOptions m_opts;
const std::string m_description;
const std::string m_cond;
@@ -324,12 +327,13 @@ struct RPCResult {
std::string m_key_name,
bool optional,
std::string description,
- std::vector<RPCResult> inner = {})
+ std::vector<RPCResult> inner = {},
+ RPCResultOptions opts = {})
: m_type{std::move(type)},
m_key_name{std::move(m_key_name)},
m_inner{std::move(inner)},
m_optional{optional},
- m_skip_type_check{false},
+ m_opts{std::move(opts)},
m_description{std::move(description)},
m_cond{std::move(cond)}
{
@@ -342,8 +346,9 @@ struct RPCResult {
Type type,
std::string m_key_name,
std::string description,
- std::vector<RPCResult> inner = {})
- : RPCResult{std::move(cond), type, std::move(m_key_name), /*optional=*/false, std::move(description), std::move(inner)} {}
+ std::vector<RPCResult> inner = {},
+ RPCResultOptions opts = {})
+ : RPCResult{std::move(cond), type, std::move(m_key_name), /*optional=*/false, std::move(description), std::move(inner), std::move(opts)} {}
RPCResult(
Type type,
@@ -351,12 +356,12 @@ struct RPCResult {
bool optional,
std::string description,
std::vector<RPCResult> inner = {},
- bool skip_type_check = false)
+ RPCResultOptions opts = {})
: m_type{std::move(type)},
m_key_name{std::move(m_key_name)},
m_inner{std::move(inner)},
m_optional{optional},
- m_skip_type_check{skip_type_check},
+ m_opts{std::move(opts)},
m_description{std::move(description)},
m_cond{}
{
@@ -368,8 +373,8 @@ struct RPCResult {
std::string m_key_name,
std::string description,
std::vector<RPCResult> inner = {},
- bool skip_type_check = false)
- : RPCResult{type, std::move(m_key_name), /*optional=*/false, std::move(description), std::move(inner), skip_type_check} {}
+ RPCResultOptions opts = {})
+ : RPCResult{type, std::move(m_key_name), /*optional=*/false, std::move(description), std::move(inner), std::move(opts)} {}
/** Append the sections of the result. */
void ToSections(Sections& sections, OuterType outer_type = OuterType::NONE, int current_indent = 0) const;
diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp
index 9ce27497..c7f03bb3 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -53,7 +53,7 @@ static RPCHelpMan getwalletinfo()
{
{RPCResult::Type::NUM, "duration", "elapsed seconds since scan start"},
{RPCResult::Type::NUM, "progress", "scanning progress percentage [0.0, 1.0]"},
- }, /*skip_type_check=*/true},
+ }, {.skip_type_check=true}, },
{RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for output script management"},
{RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
{RPCResult::Type::BOOL, "blank", "Whether this wallet intentionally does not contain any keys, scripts, or descriptors"},
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.