backport: bitcoin/bitcoin#23083: rpc: Fail to return undocumented or misdocumented JSON - #7502
backport: bitcoin/bitcoin#23083: rpc: Fail to return undocumented or misdocumented JSON #7502knst wants to merge 2 commits into
Conversation
…d JSON fc892c3 rpc: Fail to return undocumented or misdocumented JSON (MarcoFalke) f4bc4a7 rpc: Add m_skip_type_check to RPCResult (MarcoFalke) Pull request description: This avoids documentation shortcomings such as the ones fixed in commit e7b6272, 138d55e, 577bd51, f8c84e0, 0ee9a00, 13f4185, or faecb2e ACKs for top commit: fanquake: ACK fc892c3 - tested that this catches issue, i.e bitcoin#24691: Tree-SHA512: 9d0d7e6291bfc6f67541a4ff746d374ad8751fefcff6d103d8621c0298b190ab1d209ce96cfc3a0d4a6a5460a9f9bb790eb96027b16e5ff91f2512e40c92ca84 Co-authored-by: fanquake <fanquake@gmail.com>
|
⛔ Blockers found — Sonnet deferred (commit 6287883) |
Potential PR merge conflictsThis is advisory only. It does not block CI, but it marks PRs that will likely need a rebase depending on merge order. If this PR merges firstThese open PRs will likely need a rebase:
|
WalkthroughThis PR updates RPC help schemas across core, governance, quorum, masternode, transaction, networking, and wallet commands. It adds dynamic-object descriptions, marks conditionally emitted fields optional, corrects field names and types, and documents additional response fields. Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant RPCCommand
participant RPCResult
participant UniValue
RPCCommand->>RPCResult: provide documented result schema
RPCResult->>UniValue: inspect returned response
UniValue-->>RPCResult: return keys and values
RPCResult-->>RPCCommand: validate documented response shape
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/rpc/evo.cpp (1)
1-1: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick winKeep production RPCResult schemas renderable in
ToSections.
RPCResult::Type::ANYis only for test schemas, but adding it to real help paths such asprotx listinserts an unreachable branch into the schema traversal used to emit-helpdocumentation. Replace these production usages with renderable alternatives or makeToSectionssafely handleskip_type_check/dynamic shapes without relying onANY.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/rpc/evo.cpp` at line 1, Replace production RPCResult::Type::ANY usages in the evo RPC help schemas, including protx list, with concrete renderable types or supported dynamic-shape definitions. Ensure the affected schemas remain traversable by ToSections and do not introduce unreachable branches; reserve ANY for test-only schemas.
🧹 Nitpick comments (1)
src/rpc/quorums.cpp (1)
117-127: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse a descriptive placeholder instead of
"xxxx"for the dynamic quorum-hash key.This key name is rendered verbatim in generated help text (
"xxxx" : {...}) sinceOBJ_DYN's inner entry is emitted with itsm_key_namewhen nested under anOBJcontext. Elsewhere in this same PR, dynamic-key placeholders use a descriptive form (<outpoint>,<sig_hex>,<protx_hash>); consider<quorumHash>here for consistency and clearer generated docs.✏️ Proposed rename
- {RPCResult::Type::OBJ, "xxxx", "Quorum details", + {RPCResult::Type::OBJ, "<quorumHash>", "Quorum details",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/rpc/quorums.cpp` around lines 117 - 127, Replace the dynamic quorum-hash key placeholder "xxxx" in the RPC result schema with the descriptive placeholder "<quorumHash>", preserving the existing OBJ_DYN structure and quorum detail fields so generated help text clearly identifies the key.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/governance/core_write.cpp`:
- Around line 122-138: Replace the seven RPCResult::Type::ANY entries in the
data schema with appropriate concrete types so RPCResult::ToSections can render
help without reaching NONFATAL_UNREACHABLE(). Preserve skip_type_check=true on
the enclosing data object, which continues to allow mixed and extra proposal
fields during validation; do not modify unrelated fields such as plain or hex.
In `@src/llmq/core_write.cpp`:
- Around line 22-53: Replace the RPCResult::Type::ANY usage in the member_tally
helper with a schema-specific representation that accurately documents the
detail_level-dependent scalar and array variants without relying on ANY. Update
the six member tally fields in the surrounding DKG result schema to use this
representation while preserving their existing descriptions and runtime help
validation.
In `@src/rpc/evo.cpp`:
- Around line 1507-1515: Replace RPCResult::Type::ANY in the protx list result
declaration with typed result definitions: document the non-detailed array
elements as ProTx-hash strings and add a separate typed array shape for detailed
masternode objects, using the existing RPCResult field definitions where
available. Ensure ToSections() can recurse through both array shapes without
encountering ANY.
In `@src/rpc/rawtransaction.cpp`:
- Around line 576-578: Update the getislocks RPC summary text to state that it
returns the string "None" when no InstantSend lock is known, replacing the
inaccurate reference to Null. Keep the existing implementation and detailed
result documentation unchanged.
In `@src/wallet/rpc/transactions.cpp`:
- Around line 424-445: Update WalletTxToJSON() to filter out the internal
Dash-specific “DS” mapValue entry before serializing mapValue into the
transaction JSON. Preserve serialization of all documented entries and ensure
the RPC output conforms to its declared schema.
In `@src/wallet/rpc/wallet.cpp`:
- Line 126: Update the getwalletinfo RPC result definition for
keypoolsize_hd_internal to match its unconditional emission: remove the optional
flag and clarify that a value of zero indicates no internal keypool, or
alternatively update the producer to omit the field when the feature is inactive
while preserving the documented behavior.
---
Outside diff comments:
In `@src/rpc/evo.cpp`:
- Line 1: Replace production RPCResult::Type::ANY usages in the evo RPC help
schemas, including protx list, with concrete renderable types or supported
dynamic-shape definitions. Ensure the affected schemas remain traversable by
ToSections and do not introduce unreachable branches; reserve ANY for test-only
schemas.
---
Nitpick comments:
In `@src/rpc/quorums.cpp`:
- Around line 117-127: Replace the dynamic quorum-hash key placeholder "xxxx" in
the RPC result schema with the descriptive placeholder "<quorumHash>",
preserving the existing OBJ_DYN structure and quorum detail fields so generated
help text clearly identifies the key.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 15abbeec-1c9c-4130-a5ac-badb191f7d73
📒 Files selected for processing (19)
src/evo/core_write.cppsrc/governance/core_write.cppsrc/llmq/core_write.cppsrc/rpc/blockchain.cppsrc/rpc/coinjoin.cppsrc/rpc/evo.cppsrc/rpc/governance.cppsrc/rpc/masternode.cppsrc/rpc/mempool.cppsrc/rpc/mining.cppsrc/rpc/net.cppsrc/rpc/node.cppsrc/rpc/quorums.cppsrc/rpc/rawtransaction.cppsrc/rpc/util.cppsrc/rpc/util.hsrc/wallet/rpc/backup.cppsrc/wallet/rpc/transactions.cppsrc/wallet/rpc/wallet.cpp
| // Everything but "hex" is the submitter's own JSON echoed back verbatim, so neither the | ||
| // set of keys nor their types is ours to promise: a proposal may carry extra fields and | ||
| // may encode the numeric ones as strings. Hence the type check is skipped here. | ||
| {RPCResult::Type::OBJ, "data", "", { | ||
| // Fields emitted through GetDataAsPlainString(), read by CProposalValidator | ||
| {RPCResult::Type::STR, "end_epoch", /*optional=*/true, "Proposal end timestamp"}, | ||
| {RPCResult::Type::STR, "name", /*optional=*/true, "Proposal name"}, | ||
| {RPCResult::Type::STR, "payment_address", /*optional=*/true, "Proposal payment address"}, | ||
| {RPCResult::Type::STR, "payment_amount", /*optional=*/true, "Proposal payment amount"}, | ||
| {RPCResult::Type::STR, "start_epoch", /*optional=*/true, "Proposal start timestamp"}, | ||
| {RPCResult::Type::STR, "type", /*optional=*/true, "Object type"}, | ||
| {RPCResult::Type::STR, "url", /*optional=*/true, "Proposal URL"}, | ||
| {RPCResult::Type::ANY, "end_epoch", /*optional=*/true, "Proposal end timestamp"}, | ||
| {RPCResult::Type::ANY, "name", /*optional=*/true, "Proposal name"}, | ||
| {RPCResult::Type::ANY, "payment_address", /*optional=*/true, "Proposal payment address"}, | ||
| {RPCResult::Type::ANY, "payment_amount", /*optional=*/true, "Proposal payment amount"}, | ||
| {RPCResult::Type::ANY, "start_epoch", /*optional=*/true, "Proposal start timestamp"}, | ||
| {RPCResult::Type::ANY, "type", /*optional=*/true, "Object type"}, | ||
| {RPCResult::Type::ANY, "url", /*optional=*/true, "Proposal URL"}, | ||
| // Failure case for GetDataAsPlainString() | ||
| {RPCResult::Type::STR, "plain", /*optional=*/true, "Governance object data as string"}, | ||
| // Always emitted by ToJson() | ||
| {RPCResult::Type::STR_HEX, "hex", "Governance object data as hex"}, | ||
| }}, | ||
| }, /*skip_type_check=*/true}, |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== file list candidates =="
git ls-files | rg '(^src/governance/core_write\.cpp$|^src/rpc/util\.cpp$|^src/RPC\.\w+$)' || true
echo "== core_write relevant lines =="
if [ -f src/governance/core_write.cpp ]; then
nl -ba src/governance/core_write.cpp | sed -n '100,155p'
fi
echo "== util RPCResult outline =="
if [ -f src/rpc/util.cpp ]; then
ast-grep outline src/rpc/util.cpp --view compact | sed -n '1,220p' || true
fi
echo "== RPCResult::MatchesType =="
rg -n "bool RPCResult::MatchesType|RPCResult::ToSections|NONFATAL_UNREACHABLE|Type::ANY" src/rpc/util.cpp src include -S
echo "== show util around MatchesType/ToSections =="
nl -ba src/rpc/util.cpp | sed -n '1,260p'Repository: dashpay/dash
Length of output: 296
🏁 Script executed:
#!/bin/bash
set -u
echo "== repo files =="
git ls-files src/governance/core_write.cpp src/rpc/util.cpp
echo "== core_write relevant lines =="
awk 'NR>=100 && NR<=155 { printf "%6d %s\n", NR, $0 }' src/governance/core_write.cpp
echo "== util RPCResult relevant matches =="
grep -nE "bool RPCResult::MatchesType|RPCResult::ToSections|NONFATAL_UNREACHABLE|Type::ANY|skip_type_check" src/rpc/util.cpp || true
echo "== util RPCResult sections =="
awk 'NR>=1 && NR<=260 { printf "%6d %s\n", NR, $0 }' src/rpc/util.cppRepository: dashpay/dash
Length of output: 15128
🏁 Script executed:
#!/bin/bash
set -u
echo "== util RPCResult ToSections/MatchesType sections =="
awk 'NR>=740 && NR<=905 { printf "%6d %s\n", NR, $0 }' src/rpc/util.cpp
echo "== util check definitions =="
rg -n "CHECK_NONFATAL|NONFATAL_UNREACHABLE|class ExitSafe|exit_safe" include src/util src -S | head -n 80
echo "== util enum =="
rg -n "enum class Type|Type::ANY|RPCResult" src/rpc/util.h include/rpc src -S | head -n 120Repository: dashpay/dash
Length of output: 28014
🏁 Script executed:
#!/bin/bash
set -u
echo "== check.h NONFATAL_UNREACHABLE definition =="
awk 'NR>=1 && NR<=110 { printf "%6d %s\n", NR, $0 }' src/util/check.h
echo "== ToSections call sites =="
grep -n -C 2 "ToSections" src/rpc/util.cpp | head -n 80 || true
echo "== RPCHelpMan help generation call sites =="
grep -n -C 3 "ToSections\|GetRPCHelp|HelpExample.*Man" src/rpc/*.cpp src/rpc/*.h | head -n 120 || true
echo "== non-ANY OBJ fields under skip_type_check objects =="
python3 - <<'PY'
import pathlib, re
for path in pathlib.Path('src').rglob('*.cpp'):
text = path.read_text(errors='replace')
# simple brace-based scan for GetJsonHelp constructors with skip_type_check=true and Type::ANY children
for m in re.finditer(r'RPCResult\s+(?:\{|\w+)\s*,\s*\{\s*Type::OBJ\b', text):
start = m.end()-1
depth = 0
i = start
while i < len(text) and depth < 4:
c = text[i]
if c == '{': depth += 1
elif c == '}': depth -= 1
i += 1
block = text[start:i]
if 'skip_type_check=true' in block:
hits = [(block[:500].split('\n',1)[0], re.findall(r'Type::ANY,\s*"([^"]+)",', block))]
if hits[0][1]:
print(path)
for line, any_fields in hits:
print(str(line), any_fields)
PYRepository: dashpay/dash
Length of output: 7640
Avoid RPCResult::Type::ANY fields inside parsed object schemas.
skip_type_check=true already disables MatchesType validation for the enclosing data object, so the 7 fields do not need Type::ANY to permit mixed/extra proposal data. However, RPCResult::ToSections recurses into all object fields regardless of skip_type_check; any -help path that renders this schema recurses into those ANY entries and reaches NONFATAL_UNREACHABLE(), which propagates as a recoverable internal-bug RPC error. Use the appropriate concrete type for each field, or update ToSections/help rendering to handle ANY.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/governance/core_write.cpp` around lines 122 - 138, Replace the seven
RPCResult::Type::ANY entries in the data schema with appropriate concrete types
so RPCResult::ToSections can render help without reaching
NONFATAL_UNREACHABLE(). Preserve skip_type_check=true on the enclosing data
object, which continues to allow mixed and extra proposal fields during
validation; do not modify unrelated fields such as plain or hex.
| // A member tally is a count for detail_level = 0, an array of member indexes for | ||
| // detail_level = 1, and an array of {memberIndex, proTxHash} objects for | ||
| // detail_level = 2. RPCResult can only express such a union as ANY: conditional | ||
| // variants are only resolved for top-level results, so listing one variant per | ||
| // detail level here would make every level fail the runtime doc check. | ||
| const auto member_tally{[](const std::string& name, const std::string& what) { | ||
| return RPCResult{RPCResult::Type::ANY, name, | ||
| strprintf("Number of %s (detail_level = 0), array of quorum member indexes " | ||
| "(detail_level = 1), or array of {memberIndex, proTxHash} objects " | ||
| "(detail_level = 2)", | ||
| what)}; | ||
| }}; | ||
| return {RPCResult::Type::OBJ, key, optional, key.empty() ? "" : "The state of a DKG session. Empty for an unknown LLMQ type or quorum hash", | ||
| { | ||
| GetRpcResult("llmqType"), | ||
| GetRpcResult("quorumHash"), | ||
| {RPCResult::Type::NUM, "quorumHeight", "Block height of the quorum"}, | ||
| {RPCResult::Type::NUM, "phase", "Active DKG phase"}, | ||
| {RPCResult::Type::BOOL, "sentContributions", "Returns true if contributions sent"}, | ||
| {RPCResult::Type::BOOL, "sentComplaint", "Returns true if complaints sent"}, | ||
| {RPCResult::Type::BOOL, "sentJustification", "Returns true if justifications sent"}, | ||
| {RPCResult::Type::BOOL, "sentPrematureCommitment", "Returns true if premature commitments sent"}, | ||
| {RPCResult::Type::BOOL, "aborted", "Returns true if DKG session aborted"}, | ||
| {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "badMembers", "Number of bad members"}}, | ||
| {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "weComplain", "Number of complaints sent"}}, | ||
| {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "receivedContributions", "Number of contributions received"}}, | ||
| {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "receivedComplaints", "Number of complaints received"}}, | ||
| {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "receivedJustifications", "Number of justifications received"}}, | ||
| {RPCResult{"for detail_level = 0", RPCResult::Type::NUM, "receivedPrematureCommitments", "Number of premature commitments received"}}, | ||
| {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "badMembers", "Array of indexes for each bad member", { | ||
| {RPCResult::Type::NUM, "", "Quorum member index"}}}}, | ||
| {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "weComplain", "Array of indexes for each complaint sent", { | ||
| {RPCResult::Type::NUM, "", "Quorum member index"}}}}, | ||
| {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "receivedContributions", "Array of indexes for each contribution received", { | ||
| {RPCResult::Type::NUM, "", "Quorum member index"}}}}, | ||
| {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "receivedComplaints", "Array of indexes for each complaint received", { | ||
| {RPCResult::Type::NUM, "", "Quorum member index"}}}}, | ||
| {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "receivedJustifications", "Array of indexes for each justification received", { | ||
| {RPCResult::Type::NUM, "", "Quorum member index"}}}}, | ||
| {RPCResult{"for detail_level = 1", RPCResult::Type::ARR, "receivedPrematureCommitments", "Array of indexes for each commitment received", { | ||
| {RPCResult::Type::NUM, "", "Quorum member index"}}}}, | ||
| {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "badMembers", "Array of objects for each bad member", { | ||
| {RPCResult::Type::OBJ, "", "", { | ||
| GetRpcResult("memberIndex"), | ||
| GetRpcResult("proTxHash", /*optional=*/true)}}}}}, | ||
| {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "weComplain", "Array of objects for each complaint sent", { | ||
| {RPCResult::Type::OBJ, "", "", { | ||
| GetRpcResult("memberIndex"), | ||
| GetRpcResult("proTxHash", /*optional=*/true)}}}}}, | ||
| {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "receivedContributions", "Array of objects for each contribution received", { | ||
| {RPCResult::Type::OBJ, "", "", { | ||
| GetRpcResult("memberIndex"), | ||
| GetRpcResult("proTxHash", /*optional=*/true)}}}}}, | ||
| {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "receivedComplaints", "Array of objects for each complaint received", { | ||
| {RPCResult::Type::OBJ, "", "", { | ||
| GetRpcResult("memberIndex"), | ||
| GetRpcResult("proTxHash", /*optional=*/true)}}}}}, | ||
| {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "receivedJustifications", "Array of objects for each justification received", { | ||
| {RPCResult::Type::OBJ, "", "", { | ||
| GetRpcResult("memberIndex"), | ||
| GetRpcResult("proTxHash", /*optional=*/true)}}}}}, | ||
| {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "receivedPrematureCommitments", "Array of objects for each commitment received", { | ||
| {RPCResult::Type::OBJ, "", "", { | ||
| GetRpcResult("memberIndex"), | ||
| GetRpcResult("proTxHash", /*optional=*/true)}}}}}, | ||
| {RPCResult{"for detail_level = 2", RPCResult::Type::ARR, "allMembers", "Array of provider registration transaction hash for all quorum members", { | ||
| GetRpcResult("proTxHash")}}}, | ||
| GetRpcResult("llmqType", /*optional=*/true), | ||
| GetRpcResult("quorumHash", /*optional=*/true), | ||
| {RPCResult::Type::NUM, "quorumHeight", /*optional=*/true, "Block height of the quorum"}, | ||
| {RPCResult::Type::NUM, "phase", /*optional=*/true, "Active DKG phase"}, | ||
| {RPCResult::Type::BOOL, "sentContributions", /*optional=*/true, "Returns true if contributions sent"}, | ||
| {RPCResult::Type::BOOL, "sentComplaint", /*optional=*/true, "Returns true if complaints sent"}, | ||
| {RPCResult::Type::BOOL, "sentJustification", /*optional=*/true, "Returns true if justifications sent"}, | ||
| {RPCResult::Type::BOOL, "sentPrematureCommitment", /*optional=*/true, "Returns true if premature commitments sent"}, | ||
| {RPCResult::Type::BOOL, "aborted", /*optional=*/true, "Returns true if DKG session aborted"}, | ||
| member_tally("badMembers", "bad members"), | ||
| member_tally("weComplain", "complaints sent"), | ||
| member_tally("receivedContributions", "contributions received"), | ||
| member_tally("receivedComplaints", "complaints received"), | ||
| member_tally("receivedJustifications", "justifications received"), | ||
| member_tally("receivedPrematureCommitments", "premature commitments received"), | ||
| {RPCResult::Type::ARR, "allMembers", /*optional=*/true, "Provider registration transaction hash for all quorum members. Only present for detail_level = 2", { | ||
| GetRpcResult("proTxHash")}}, | ||
| }}; |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate files =="
git ls-files | rg '(^|/)core_write\.cpp$|rpc.*result|rpc.*doc|llmq.*rpc' | sed -n '1,200p'
echo
echo "== core_write excerpt =="
sed -n '1,120p' src/llmq/core_write.cpp | cat -n
echo
echo "== RPCResult definitions/usages =="
rg -n "enum class Type|RPCResult::Type::ANY|NONFATAL_UNREACHABLE|ToSections|rpcresult|GetRpcResult" src -g '*.cpp' -g '*.h' | sed -n '1,240p'Repository: dashpay/dash
Length of output: 23318
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
import re, pathlib
for path in pathlib.Path('src').rglob('*'):
if path.is_file() and path.suffix in {'.cpp','.h'}:
text=path.read_text(errors='ignore')
if 'RPCResult::Type::ANY' in text or 'ToSections' in text or 'NONFATAL_UNREACHABLE' in text:
print(path)
PYRepository: dashpay/dash
Length of output: 464
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== rpc/util.h relevant types =="
sed -n '130,175p' src/rpc/util.h | cat -n
sed -n '250,270p' src/rpc/util.h | cat -n
echo
echo "== rpc/util.cpp relevant doc handling =="
sed -n '450,540p' src/rpc/util.cpp | cat -n
sed -n '740,860p' src/rpc/util.cpp | cat -n
echo
echo "== RPCResult::ANY occurrences with surrounding call context =="
for file in src/rpc/util.cpp src/rpc/server.cpp src/rpc/mempool.cpp src/rpc/node.cpp src/wallet/rpc/transactions.cpp src/wallet/rpc/backup.cpp src/rqt/test/rpcnestedtests.cpp src/governance/core_write.cpp src/llmq/core_write.cpp; do
[ -f "$file" ] || continue
echo "--- $file"
grep -n 'RPCResult::Type::ANY' "$file"
done
echo
echo "== Check call path for GetJsonHelp in rpc/quorums and related llmq rpc =="
fd -a 'quorum|quorums|debug|core_write' src | sort | sed -n '1,120p'
rg -n 'CDKGDebugSessionStatus::GetJsonHelp|CDKGDebugManager::GetJsonHelp|GetJsonHelp|RpcResult|RPCResult' src/llmq src/rpc -g '*.cpp' -g '*.h' | sed -n '1,240p'Repository: dashpay/dash
Length of output: 12758
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== RPCResult implementation =="
sed -n '148,182p' src/rpc/util.h | cat -n
sed -n '660,760p' src/rpc/util.cpp | cat -n
echo
echo "== DKG help call paths =="
rg -n 'CDKGDebugSessionStatus::GetJsonHelp|CDKGDebugManager::GetJsonHelp|GetJsonHelp|RPCHelpMan|GetRpcResult|DEFAULT_RPC_DOC_CHECK|rpcdoccheck' src/rpc src/llmq src/llmq -g '*.cpp' -g '*.h' | sed -n '1,260p'
echo
echo "== RPCResult::ANY usages and matching logic context =="
sed -n '470,505p' src/rpc/server.cpp | cat -n
sed -n '700,760p' src/rpc/util.cpp | cat -n
sed -n '760,860p' src/rpc/util.cpp | cat -nRepository: dashpay/dash
Length of output: 35544
Avoid RPCResult::Type::ANY for production DKG help schemas.
RPCResult::ANY is documented and handled as “for testing only” in ToSections and RPC result printing. Since the nested help path for DKG session results will produce this, this needs a schema/helper-specific solution rather than leaving ANY in production help fields. [code_integrity_and_integration]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/llmq/core_write.cpp` around lines 22 - 53, Replace the
RPCResult::Type::ANY usage in the member_tally helper with a schema-specific
representation that accurately documents the detail_level-dependent scalar and
array variants without relying on ANY. Update the six member tally fields in the
surrounding DKG result schema to use this representation while preserving their
existing descriptions and runtime help validation.
| RPCResult{ | ||
| RPCResult::Type::ARR, "", "List of masternodes", | ||
| { | ||
| RPCResult{"when detailed=false", RPCResult::Type::STR, "", "ProTx hash"}, | ||
| RPCResult{"when detailed=true", RPCResult::Type::OBJ, "", "", | ||
| { | ||
| // TODO: document fields of the detailed entry | ||
| {RPCResult::Type::ELISION, "", ""} | ||
| }}, | ||
| // Array elements are matched against this doc by index, so the two shapes | ||
| // cannot be listed as alternatives here - the first entry would be applied | ||
| // to element 0 only and the second to every element after it. | ||
| // TODO: document fields of the detailed entry | ||
| {RPCResult::Type::ANY, "", "The ProTx hash when detailed=false, otherwise an object describing the masternode"}, | ||
| }}, |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Locate relevant files =="
git ls-files | rg '(^|/)rpc/evo\.cpp$|rpcdoc|RPCResult|GetHelp|ToSections' | head -200
echo
echo "== Search for RPCResult::ANY and ToSections implementation/usages =="
rg -n "RPCResult::Type::ANY|enum class Type|static.*ToSections|ToSections|NONFATAL_UNREACHABLE" src include -S | head -250
echo
echo "== Inspect protx list RPCResult docs around target lines =="
wc -l src/rpc/evo.cpp
sed -n '1460,1545p' src/rpc/evo.cpp
echo
echo "== Inspect RPC docs implementation context candidates =="
for f in $(git ls-files | rg '(^src/rpc/|(^src/.*rpc.*))' | rg '(doc|help|result|util)' | head -50); do
echo "--- $f ---"
wc -l "$f"
doneRepository: dashpay/dash
Length of output: 3889
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Relevant RPCResult implementation slices =="
sed -n '245,290p' src/rpc/util.h
sed -n '475,510p' src/rpc/util.cpp
sed -n '745,845p' src/rpc/util.cpp
sed -n '960,985p' src/rpc/util.cpp
echo
echo "== Search help generation entry points and protx list command =="
rg -n "help\\(|cmd->GetHelp|GetHelp|HelpText|protx list|protoc\\.list|rpc_commands|command.*=" src/rpc src/node src/init -S | head -250
echo
echo "== Evo file command outline =="
ast-grep outline src/rpc/evo.cpp --view compact 2>/dev/null | sed -n '1,220p' || true
rg -n "protx list|list.*protx|\"protx list\"|help_for.*protx|protx" src/rpc/evo.cpp -S | head -120
echo
echo "== Search any Any typed docs outside tests =="
python3 - <<'PY'
import re
from pathlib import Path
for p in sorted(Path(".").rglob("*.cpp")):
s=p.read_text(errors='replace')
if "RPCResult::Type::ANY" in s:
# print surrounding doc entries only if type before name.
for m in re.finditer(r'\{RPCResult::Type::ANY\s*,\s*"([^"]*)"', s):
line=s[:m.start()].count("\n")+1
txt=m.group(1)
if "test" not in txt.lower() and line not in (474, 514, 866, 1007, 1107, 233, 1514, 1170):
print(f"{p}:{line}: {txt}")
PYRepository: dashpay/dash
Length of output: 21440
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Inspect help implementation path =="
sed -n '75,165p' src/rpc/server.cpp
sed -n '145,205p' src/rpc/server.cpp
echo
echo "== Inspect RPCHelpMan result generation and protx list results =="
rg -n "class RPCHelpMan|struct RPCHelpMan|RPCHelpMan::DescribeCommand|RPCHelpMan::HelpToString|GetHelp|ToDescriptionString\\(" src/rpc src/support -S | head -200
sed -n '1,260p' src/rpc/util.h
rg -n "DescribeCommand|HelpToString|ToDescriptionString\\(|Describe|result" src/rpc/util.cpp -S | head -200
echo
echo "== Read-only parser probe for protx list RPCResult shape from source =="
python3 - <<'PY'
from pathlib import Path
p=Path("src/rpc/evo.cpp")
text=p.read_text()
needle='return RPCHelpMan{"protx list"'
i=text.find(needle)
print("protx list start token at:", i)
out=[]
depth=0
for line_no,line in enumerate(text.splitlines(),1):
if i!=-1 and len("\n".join(text.splitlines()[:line_no]))>=i:
out.append((line_no,line))
depth+=line.count('{')-line.count('}')
if depth<=0 and any(s in line for s in ['};', '},']):
break
for row in out[:80]:
print(f"{row[0]}: {row[1]}")
# Find ToSections handler occurrences and report whether ANY is skipped or unreachable.
util=Path("src/rpc/util.cpp").read_text()
for needle in ["RPCResults::ToDescriptionString", "case Type::ANY", "case Type::ARR:"]:
idx=util.find(needle)
print(f"\n--- {needle} at {idx} ---")
if idx>=0:
snippet=util[max(0,idx-800):idx+800]
print("\n".join(f"{n+1}: {ln}" for n,ln in enumerate(snippet.splitlines(), 0) if "ANY" in ln or ("ToDescriptionString" in sn if (sn:=snippet)>=0 else False) or ("case Type::ARR" in ln)))
PYRepository: dashpay/dash
Length of output: 24362
Use a typed result for protx list instead of RPCResult::Type::ANY.
The array result already handles detailed=false as strings; document that shape and add a separate detailed-array shape if needed. RPCResult::Type::ANY is for testing/type-check bypass only, and recursing through an ARR into ANY in ToSections() hits NONFATAL_UNREACHABLE().
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/rpc/evo.cpp` around lines 1507 - 1515, Replace RPCResult::Type::ANY in
the protx list result declaration with typed result definitions: document the
non-detailed array elements as ProTx-hash strings and add a separate typed array
shape for detailed masternode objects, using the existing RPCResult field
definitions where available. Ensure ToSections() can recurse through both array
shapes without encountering ANY.
| // An element is the plain string "None" when no InstantSend Lock is known for | ||
| // that txid, so the element type cannot be checked against this object. | ||
| /*skip_type_check=*/true}, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Update the getislocks summary to document the string "None".
The implementation returns "None" at Line 619, and this change now explicitly documents that string. However, the RPC summary still says it returns Null, which describes the wrong JSON value type. Update the summary text accordingly.
Proposed documentation fix
- "\nReturns the raw InstantSend lock data for each txids. Returns Null if there is no known IS yet.",
+ "\nReturns the raw InstantSend lock data for each txids. Returns the string \"None\" if there is no known IS yet.",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // An element is the plain string "None" when no InstantSend Lock is known for | |
| // that txid, so the element type cannot be checked against this object. | |
| /*skip_type_check=*/true}, | |
| "\nReturns the raw InstantSend lock data for each txids. Returns the string \"None\" if there is no known IS yet.", |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/rpc/rawtransaction.cpp` around lines 576 - 578, Update the getislocks RPC
summary text to state that it returns the string "None" when no InstantSend lock
is known, replacing the inaccurate reference to Null. Keep the existing
implementation and detailed result documentation unchanged.
| {RPCResult::Type::BOOL, "instantlock_internal", "Current internal transaction lock state. Available for 'send' and 'receive' category of transactions"}, | ||
| {RPCResult::Type::BOOL, "chainlock", "The state of the corresponding block ChainLock"}, | ||
| {RPCResult::Type::BOOL, "generated", /*optional=*/true, "Only present if the transaction's only input is a coinbase one."}, | ||
| {RPCResult::Type::BOOL, "platform-transfer", /*optional=*/true, "Only present if the transaction is a Platform Transfer."}, | ||
| {RPCResult::Type::BOOL, "trusted", /*optional=*/true, "Whether we consider the transaction to be trusted and safe to spend from.\n" | ||
| "Only present when the transaction has 0 confirmations (or negative confirmations, if conflicted)."}, | ||
| {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The block hash containing the transaction. Available for 'send' and 'receive'\n" | ||
| "category of transactions."}, | ||
| {RPCResult::Type::STR_HEX, "blockheight", /*optional=*/true, "The block height containing the transaction."}, | ||
| {RPCResult::Type::NUM, "blockheight", /*optional=*/true, "The block height containing the transaction."}, | ||
| {RPCResult::Type::NUM, "blockindex", /*optional=*/true, "The index of the transaction in the block that includes it. Available for 'send' and 'receive'\n" | ||
| "category of transactions."}, | ||
| {RPCResult::Type::NUM_TIME, "blocktime", /*optional=*/true, "The block time expressed in " + UNIX_EPOCH_TIME + "."}, | ||
| {RPCResult::Type::STR_HEX, "txid", "The transaction id. Available for 'send' and 'receive' category of transactions."}, | ||
| {RPCResult::Type::ARR, "walletconflicts", "Conflicting transaction ids.", | ||
| { | ||
| {RPCResult::Type::STR_HEX, "txid", "The transaction id."}, | ||
| }}, | ||
| {RPCResult::Type::NUM_TIME, "time", "The transaction time expressed in " + UNIX_EPOCH_TIME + "."}, | ||
| {RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + ". Available \n" | ||
| "for 'send' and 'receive' category of transactions."}, | ||
| {RPCResult::Type::STR, "comment", /*optional=*/true, "If a comment is associated with the transaction."}}; | ||
| {RPCResult::Type::STR, "comment", /*optional=*/true, "If a comment is associated with the transaction."}, | ||
| {RPCResult::Type::STR, "to", /*optional=*/true, "If a comment to is associated with the transaction."}}; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Locate target file and relevant functions"
fd -a 'transactions\.cpp$|transactions\.h$' src/wallet/rpc 2>/dev/null || true
echo
echo "Target snippet around lines 424-445"
if [ -f src/wallet/rpc/transactions.cpp ]; then
sed -n '380,520p' src/wallet/rpc/transactions.cpp | nl -ba -v380
fi
echo
echo "Search WalletTxToJSON and RPCResult validation references"
rg -n "WalletTxToJSON|mapValue|RPCResult::MatchesType|DS|CoinJoin|DS_INQUEUE|DS_FINAL" src -S | head -200
echo
echo "Files containing RPCResult::MatchesType"
rg -n "MatchesType|RPCResult::Type::STR|RPCResult::Type::OBJ" src test -S | grep -E "(rpc|wallet)" | head -200Repository: dashpay/dash
Length of output: 321
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Target file availability"
[ -f src/wallet/rpc/transactions.cpp ] && echo "src/wallet/rpc/transactions.cpp present"
echo
echo "Target file size"
wc -l src/wallet/rpc/transactions.cpp
echo
echo "Target snippet around lines 424-445"
sed -n '380,520p' src/wallet/rpc/transactions.cpp
echo
echo "Search WalletTxToJSON, mapValue, RPCResult, DS"
rg -n "WalletTxToJSON|mapValue|RPCResult::MatchesType|RPCResult|STR_HEX|DS_INQUEUE|DS_FINAL|DS_|CoinJoin" src/wallet/rpc src/wallet src/main src/primitives src -S | head -300Repository: dashpay/dash
Length of output: 49490
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "WalletTxToJSON implementation"
sed -n '1,90p' src/wallet/rpc/transactions.cpp
echo
echo "Listtransactions CoinJoin DS reading section"
sed -n '330,375p' src/wallet/rpc/transactions.cpp
echo
echo "listtransactions schema wrapper"
sed -n '436,530p' src/wallet/rpc/transactions.cpp
echo
echo "listsinceblock/gettransaction schema wrapper references"
sed -n '540,615p' src/wallet/rpc/transactions.cpp
sed -n '700,755p' src/wallet/rpc/transactions.cpp
echo
echo "Find RPCResult definition and MatchesType"
rg -n "class RPCHelpMan|struct RPCResult|RPCResult::.*Type::|MatchesType|static.*RPCHelpMan" src/wallet/rpc src/wallet src/ -S | head -250Repository: dashpay/dash
Length of output: 50368
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Locate RPCResult implementation"
rg -n "struct RPCResult|class RPCResult|RPCHelpMan|MatchesType" src/wallet/rpc src/rpc src -S --glob '*.h' --glob '*.cpp' | head -150
echo
echo "Inspect RPCResult header/source candidates"
for f in $(rg -l "struct RPCResult|class RPCResult|static void RPCHelpManCheck|static bool MatchesType" src -S --glob '*.h' --glob '*.cpp'); do
echo "--- $f"
wc -l "$f"
rg -n "struct RPCResult|class RPCResult|RPCHelpManCheck|static bool MatchesType|static void RPCHelpManCheck" "$f" -C 12
done
echo
echo "Read candidate file ranges"
for f in $(rg -l "struct RPCResult|class RPCResult" src -S --glob '*.h' --glob '*.cpp' | head -5); do
echo "--- $f"
sed -n '1,220p' "$f"
doneRepository: dashpay/dash
Length of output: 50368
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "RPCResult implementation"
sed -n '250,580p' src/rpc/util.h
sed -n '1,260p' src/rpc/util.cpp
echo
echo "Call sites for RpcHelpManagerCheck/HelpValidate and result checks"
rg -n "HelpValidate|HelpValidateAfter\(|Check.*Result|RPCResult.*result|RPCResults|CallRPC|RPCHelpManCheck|HelpCheck|Result" src/rpc/src src/wallet/rpc -S --glob '*.h' --glob '*.cpp' | head -200
echo
echo "Search exact RPCResult struct definition text"
sed -n '262,390p' src/rpc/util.h
echo
echo "Search RPC help result validation exact methods"
rg -n "RPCResult::.*MatchesType|Checks RPC result|result.*matches|Check.*rpc result" src/rpc src/wallet/rpc -SRepository: dashpay/dash
Length of output: 42112
Drop undocumented mapValue keys before RPC serialization.
WalletTxToJSON() pushes every wtx.mapValue entry into the transaction JSON. The CoinJoin classification uses a Dash-specific DS entry, but the RPC result schemas do not expose it; remove internal/wallet metadata before looping over mapValue or add the entry to the schema with a regression test.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/wallet/rpc/transactions.cpp` around lines 424 - 445, Update
WalletTxToJSON() to filter out the internal Dash-specific “DS” mapValue entry
before serializing mapValue into the transaction JSON. Preserve serialization of
all documented entries and ensure the RPC output conforms to its declared
schema.
| {RPCResult::Type::NUM_TIME, "timefirstkey", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " of the oldest known key in the wallet. Legacy wallets only"}, | ||
| {RPCResult::Type::NUM_TIME, "keypoololdest", /*optional=*/true, "the " + UNIX_EPOCH_TIME + " of the oldest pre-generated key in the key pool. Legacy wallets only"}, | ||
| {RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"}, | ||
| {RPCResult::Type::NUM, "keypoolsize_hd_internal", /*optional=*/ true, "how many new keys are pre-generated for internal use (used for change outputs and mobile coinjoin, only appears if the wallet is using this feature, otherwise external keys are used)"}, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Do not mark keypoolsize_hd_internal optional while always emitting it.
getwalletinfo() unconditionally adds this field, including when no internal keypool feature is active. Keep it required and clarify that zero means no internal pool, or change the producer to omit it under the documented condition.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/wallet/rpc/wallet.cpp` at line 126, Update the getwalletinfo RPC result
definition for keypoolsize_hd_internal to match its unconditional emission:
remove the optional flag and clarify that a value of zero indicates no internal
keypool, or alternatively update the producer to omit the field when the feature
is inactive while preserving the documented behavior.
thepastaclaw
left a comment
There was a problem hiding this comment.
Preliminary review — Codex only
The upstream backport and most Dash-specific schema adaptations are coherent, but the newly introduced nested ANY entries violate the existing help-renderer contract and make several RPC help pages throw NonFatalCheckError. The revised mempool result documentation also omits the normal "false" value for instantlock, so changes are required before merge.
Validated blockers were found in the Codex precheck. Sonnet is deferred until a fresh Codex revalidation clears the blocker gate.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (completed),gpt-5.6-sol— dash-core-commit-history (completed),gpt-5.6-sol— backport-reviewer (completed) - Verifier:
gpt-5.6-sol— verifier - Sonnet: not run (deferred by blocker gate)
🔴 1 blocking | 💬 1 nitpick(s)
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `src/llmq/core_write.cpp`:
- [BLOCKING] src/llmq/core_write.cpp:28-32: Nested ANY result types make RPC help throw
`RPCResult::Type::ANY` is only skipped when it is the top-level result. Nested entries are passed to `RPCResult::ToSections()`, whose `Type::ANY` branch calls `NONFATAL_UNREACHABLE()` and throws `NonFatalCheckError`. Therefore, rendering `help quorum dkgstatus` traverses this member-tally entry and fails instead of returning help. The same PR-introduced problem affects the nested `ANY` entries in `src/governance/core_write.cpp:127-133`, `src/rpc/rawtransaction.cpp:474`, `src/rpc/evo.cpp:1514`, and `src/wallet/rpc/transactions.cpp:868`. The new `m_skip_type_check` flag only affects `MatchesType()` and does not prevent help rendering. Add a displayable representation for nested `ANY`, or use displayable result types with type checking skipped.
| return RPCResult{RPCResult::Type::ANY, name, | ||
| strprintf("Number of %s (detail_level = 0), array of quorum member indexes " | ||
| "(detail_level = 1), or array of {memberIndex, proTxHash} objects " | ||
| "(detail_level = 2)", | ||
| what)}; |
There was a problem hiding this comment.
🔴 Blocking: Nested ANY result types make RPC help throw
RPCResult::Type::ANY is only skipped when it is the top-level result. Nested entries are passed to RPCResult::ToSections(), whose Type::ANY branch calls NONFATAL_UNREACHABLE() and throws NonFatalCheckError. Therefore, rendering help quorum dkgstatus traverses this member-tally entry and fails instead of returning help. The same PR-introduced problem affects the nested ANY entries in src/governance/core_write.cpp:127-133, src/rpc/rawtransaction.cpp:474, src/rpc/evo.cpp:1514, and src/wallet/rpc/transactions.cpp:868. The new m_skip_type_check flag only affects MatchesType() and does not prevent help rendering. Add a displayable representation for nested ANY, or use displayable result types with type checking skipped.
source: ['codex']
| RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction", | ||
| {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}}, | ||
| RPCResult{RPCResult::Type::BOOL, "instantsend", "True if this transaction was locked via InstantSend"}, | ||
| RPCResult{RPCResult::Type::STR, "instantlock", "\"true\" if this transaction was locked via InstantSend, \"unknown\" if InstantSend is unavailable"}, |
There was a problem hiding this comment.
💬 Nitpick: Document the unlocked instantlock value
entryToJSON() serializes isman->IsLocked(...) through util::to_string(bool), which returns either "true" or "false"; it returns "unknown" only when the InstantSend manager is unavailable. The revised documentation omits the normal "false" response value, leaving this result incompletely documented in a PR specifically correcting RPC result schemas.
| RPCResult{RPCResult::Type::STR, "instantlock", "\"true\" if this transaction was locked via InstantSend, \"unknown\" if InstantSend is unavailable"}, | |
| RPCResult{RPCResult::Type::STR, "instantlock", "\"true\" if this transaction was locked via InstantSend, \"false\" if it was not locked, and \"unknown\" if InstantSend is unavailable"}, |
source: ['codex']
Issue being fixed or feature implemented
Backport bitcoin#23083 discovered multiple issues in our help for RPC
What was done?
AI crafted fixes for RPC help + backport bitcoin#23083
How Has This Been Tested?
Run unit / functional tests, fix multiple failures such as:
Breaking Changes
Debug builds going to crash every time when RPC help is not matching with real RPC response.
Checklist: