fix: Update noripple_check to exclude transactions field on error responses#6303
fix: Update noripple_check to exclude transactions field on error responses#6303mvadari wants to merge 19 commits intoXRPLF:developfrom
noripple_check to exclude transactions field on error responses#6303Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes issue #4616 by ensuring that the transactions field is not included in error responses from the noripple_check RPC handler. Additionally, it modernizes the code by replacing string literals with jss:: constants for consistency with current rippled conventions.
Changes:
- Moved account validation earlier in the flow to fail fast before ledger lookup
- Changed
transactionsarray from being conditionally created to always being created as a local variable and only added to the result at the end, ensuring error paths don't include it - Replaced string literals with
jss::constants throughout the handler (e.g.,"Account"→jss::Account,"gateway"→jss::gateway) - Added test case to verify
transactionsfield is absent in error responses
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/xrpld/rpc/handlers/NoRippleCheck.cpp | Refactored to exclude transactions field from error responses, moved account validation earlier, and replaced string literals with jss:: constants |
| src/test/rpc/NoRippleCheck_test.cpp | Added test to verify transactions field is not present on error response and adjusted test structure slightly |
| include/xrpl/protocol/jss.h | Added gateway, problems, and user constants for use in noripple_check handler |
| API-CHANGELOG.md | Documented the API change for the unreleased version |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return false; | ||
| }); | ||
|
|
||
| if (transactions) |
There was a problem hiding this comment.
According to the API-CHANGELOG.md, the transactions field should not be included in the response if there are no problems. However, this code only checks if the transactions parameter is true, not whether there are any problems. This means an empty transactions array will still be returned when transactions=true but there are no problems, which contradicts the documented behavior. The condition should check both that transactions is true AND that jvTransactions is not empty, or check if problems.size() is greater than 0.
| if (transactions) | |
| if (transactions && !jvTransactions.empty()) |
There was a problem hiding this comment.
This is intentional
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #6303 +/- ##
=======================================
Coverage 79.8% 79.8%
=======================================
Files 858 858
Lines 67757 67759 +2
Branches 7557 7552 -5
=======================================
+ Hits 54064 54076 +12
+ Misses 13693 13683 -10
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "experimenting"); | ||
| } | ||
| else if (roleGateway & !bDefaultRipple) | ||
| else if (roleGateway & !defaultRipple) |
There was a problem hiding this comment.
Incorrect operator used: bitwise AND (&) is used instead of logical AND (&&). The expression roleGateway & !defaultRipple performs bitwise AND between two boolean values, which can lead to incorrect behavior. This should be roleGateway && !defaultRipple to perform logical AND.
| if (!BEAST_EXPECT(result[jss::transactions].isArray())) | ||
| return; |
There was a problem hiding this comment.
The API changelog states that the transactions field should not be included when there are no problems. However, the test expectation on line 228 checks txs.size() == 0, which implicitly expects an empty array rather than the absence of the field. This test should be updated to check !result.isMember(jss::transactions) when there are no problems, even if the transactions parameter was set to true. Note that line 206 also unsafely accesses result[jss::transactions] without checking if the field exists first - this should be guarded with a membership check.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Json::Value jvTransactions = Json::arrayValue; | ||
|
|
||
| if (bDefaultRipple & !roleGateway) | ||
| if (defaultRipple & !roleGateway) |
There was a problem hiding this comment.
This uses bitwise AND (&) instead of logical AND (&&). Since defaultRipple is a boolean, this should use && to avoid unexpected behavior. The same issue appears on line 117.
| std::string problem; | ||
| bool needFix = false; | ||
| if (bNoRipple & roleGateway) | ||
| if (noRipple && roleGateway) |
There was a problem hiding this comment.
This correctly uses logical AND (&&), but line 110 and 117 in the same function use bitwise AND (&) for the same type of boolean comparison. For consistency and correctness, all boolean comparisons should use logical operators.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (defaultRipple & !roleGateway) | ||
| { |
There was a problem hiding this comment.
defaultRipple and roleGateway are booleans; using bitwise & here avoids short-circuiting and is easy to misread as a bug. Use logical && for boolean conditions.
| else if (roleGateway & !defaultRipple) | ||
| { |
There was a problem hiding this comment.
This condition also uses bitwise & with boolean operands. Prefer && for boolean logic to match the surrounding code and avoid surprises from lack of short-circuiting.
| auto id = parseBase58<AccountID>(params[jss::account].asString()); | ||
| if (!id) | ||
| { | ||
| return rpcError(rpcACT_MALFORMED); | ||
| } |
There was a problem hiding this comment.
Moving the parseBase58 failure to return rpcError(rpcACT_MALFORMED) before lookupLedger changes the error response shape beyond omitting transactions (it will also no longer include ledger metadata like ledger_hash/ledger_index/validated that previously came from lookupLedger). Please confirm this behavior change is intended and, if so, document it in the API changelog/PR description.
|
|
||
| ### Additions and bugfixes in unreleased version | ||
|
|
||
| - `noripple_check`: The `transactions` field is no longer included in the response if the response is an error or if there are no `problems`. |
There was a problem hiding this comment.
This changelog entry says transactions is omitted when there are no problems, but the handler still includes transactions: [] whenever transactions=true (even if problems is empty). Update the changelog to match the implemented behavior (or adjust the implementation if the changelog is the intended contract).
| - `noripple_check`: The `transactions` field is no longer included in the response if the response is an error or if there are no `problems`. | |
| - `noripple_check`: The `transactions` field is no longer included in the response if the response is an error. When `transactions=true` and there are no `problems`, the response includes `transactions: []`. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (defaultRipple & !roleGateway) | ||
| { | ||
| problems.append( | ||
| "You appear to have set your default ripple flag even though you " | ||
| "are not a gateway. This is not recommended unless you are " | ||
| "experimenting"); | ||
| } | ||
| else if (roleGateway & !bDefaultRipple) | ||
| else if (roleGateway & !defaultRipple) | ||
| { |
There was a problem hiding this comment.
These conditions use bitwise & with boolean operands (defaultRipple/roleGateway). While it currently works, it does not short-circuit and is easy to misread as a bug; other handlers in this codebase generally use logical &&/|| for boolean logic. Replace & with && here (and similarly for the else if).
269fba9 to
d3af1b6
Compare
d3af1b6 to
42ba358
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (defaultRipple & !roleGateway) | ||
| { | ||
| problems.append( | ||
| "You appear to have set your default ripple flag even though you " | ||
| "are not a gateway. This is not recommended unless you are " | ||
| "experimenting"); | ||
| } | ||
| else if (roleGateway & !bDefaultRipple) | ||
| else if (roleGateway & !defaultRipple) | ||
| { |
There was a problem hiding this comment.
These conditions use bitwise & with boolean operands (defaultRipple & !roleGateway, roleGateway & !defaultRipple). This works but is easy to misread and does not short-circuit; it also regresses the earlier change in this PR thread. Use logical && for boolean logic here.
| if (!params.isMember(jss::role)) | ||
| return RPC::missing_field_error(jss::role); | ||
|
|
||
| bool roleGateway = false; | ||
| { | ||
| std::string const role = params["role"].asString(); | ||
| if (role == "gateway") | ||
| std::string const role = params[jss::role].asString(); | ||
| if (role == jss::gateway) | ||
| roleGateway = true; | ||
| else if (role != "user") | ||
| return RPC::invalid_field_error("role"); | ||
| else if (role != jss::user) | ||
| return RPC::invalid_field_error(jss::role); |
There was a problem hiding this comment.
role is treated as a string without validating its JSON type. If role is non-string (e.g. object/number), asString() will silently coerce and may accept invalid input. Add an isString() check for params[jss::role] and return RPC::invalid_field_error(jss::role) when it is not a string.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Json::Value jvTransactions = Json::arrayValue; | ||
|
|
||
| if (bDefaultRipple & !roleGateway) | ||
| if (defaultRipple & !roleGateway) |
There was a problem hiding this comment.
These conditions use bitwise & with boolean operands. While it works, it removes short-circuiting and is inconsistent with nearby boolean logic (&&). Use && here to make intent clear and avoid subtle precedence/maintenance issues.
High Level Overview of Change
This PR updates the
noripple_checkRPC to exclude thetransactionsfield on error responses. It also does some other cleanup of the file, to match modern rippled code.Context of Change
Fixes #4616
Type of Change
API Impact
Before / After
Before: an
rpcACT_MALFORMEDerror message return would have an emptytransactionsarray attached to it.After: Now it does not.
Test Plan
Added a test. CI passes.