Skip to content

feat(poa): add validator self-removal message#146

Merged
AdriaCarrera merged 7 commits into
xrplevm:mainfrom
aluque-peersyst:feat/add-validator-self-remove-message
Jun 23, 2026
Merged

feat(poa): add validator self-removal message#146
AdriaCarrera merged 7 commits into
xrplevm:mainfrom
aluque-peersyst:feat/add-validator-self-remove-message

Conversation

@aluque-peersyst

@aluque-peersyst aluque-peersyst commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Add message for validators to remove themselves from the validator set

Summary by CodeRabbit

  • New Features
    • Added a new self-removal transaction/RPC that lets a validator remove itself from the authority.
    • Introduced the corresponding message type and emits a dedicated self_remove_validator event on successful self-removal.
  • Tests
    • Added unit tests covering invalid addresses, non-validator addresses, and successful self-removal.
    • Added integration tests verifying bonded→unbonding transitions, authorization failure, non-validator handling, and repeated attempts.
  • Chores
    • Updated gomock import path in tests.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a SelfRemoveValidator RPC to the POA module's Msg service, enabling validators to remove themselves. Introduces MsgSelfRemoveValidator and MsgSelfRemoveValidatorResponse proto messages, a keeper method ExecuteSelfRemoveValidator that validates and delegates removal, a message server handler, codec and event registrations, unit tests, and comprehensive integration tests covering success and failure paths.

Changes

SelfRemoveValidator feature

Layer / File(s) Summary
Proto contract and message types
proto/poa/tx.proto, x/poa/types/message_self_remove_validator.go
Adds SelfRemoveValidator RPC to Msg service with MsgSelfRemoveValidator request type and empty response. Introduces MsgSelfRemoveValidator message with cosmos.msg.v1.signer = "address" annotation and address field. Provides Go constructor NewMsgSelfRemoveValidator(address) with sdk.Msg compile-time assertion.
Codec registrations and event type
x/poa/types/codec.go, x/poa/types/events.go
Registers MsgSelfRemoveValidator in RegisterCodec as Amino type "poa/SelfRemoveValidator" and in RegisterInterfaces as sdk.Msg implementation. Adds EventTypeSelfRemoveValidator constant for validator self-removal events.
Keeper ExecuteSelfRemoveValidator
x/poa/keeper/keeper.go
Implements ExecuteSelfRemoveValidator method: parses bech32 address to validator address, validates validator exists (returns ErrAddressIsNotAValidator if not), delegates removal to ExecuteRemoveValidator, and emits EventTypeSelfRemoveValidator with address, block height, and staking token amount.
Message server handler and unit tests
x/poa/keeper/msg_server_self_remove_validator.go, x/poa/keeper/msg_server_self_remove_validator_test.go, x/poa/keeper/msg_server_remove_validator_test.go
Adds msgServer.SelfRemoveValidator handler that unwraps SDK context and delegates to keeper's ExecuteSelfRemoveValidator. Table-driven unit tests cover invalid address decoding, non-existent validator rejection, and successful removal with mocked staking/bank side effects and hook invocation. Updates gomock import in existing test to go.uber.org/mock/gomock.
Integration tests
tests/integration/poa_test.go
Adds four integration test methods covering existing validator self-removal (bonded/jailed/tombstoned states → unbonding completion), non-validator rejection, unauthorized signer rejection, and second self-remove attempt failure. Tests verify preconditions, transaction submission via factory, and postconditions including token/share zeroing and validator unbonding status.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Possibly related PRs

  • xrplevm/node#142: Main PR's ExecuteSelfRemoveValidator delegates to the existing ExecuteRemoveValidator logic, so its correctness depends on the same staking hook error handling that the retrieved PR expands in MsgServer RemoveValidator tests.
  • xrplevm/node#143: Both PRs update the same gomock import from github.com/golang/mock/gomock to go.uber.org/mock/gomock in POA keeper tests.
  • xrplevm/node#144: Main PR's ExecuteSelfRemoveValidator delegates removal to ExecuteRemoveValidator using derived validator/address parsing, which directly intersects with the retrieved PR's refactor of how ExecuteRemoveValidator parses and handles validator addresses.

Suggested reviewers

  • AdriaCarrera

Poem

🐇 Hop, hop, away I go,
No longer bound to the validator row!
I sign my name and wave goodbye,
SelfRemoveValidator takes my reply!
The proto speaks, the keeper heeds,
A rabbit knows when it's time to leave! 🌿

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is minimal and does not follow the required template structure with Motivation, Changes, Considerations, and Dependencies sections. Expand the description to follow the template: add a Motivation section explaining why validators need self-removal capability, a Changes section listing the specific implementations added, and any relevant Considerations or Dependencies.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: adding a validator self-removal message feature to the POA module.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 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 `@x/poa/keeper/keeper.go`:
- Around line 293-297: In the validator address parsing logic, change from
parsing validatorAddress as an account address using sdk.AccAddressFromBech32
and then coercing to validator address, to directly parsing it as a validator
address using sdk.ValAddressFromBech32. Assign the result to valAddress
directly, then derive the accAddress from the validator address bytes if needed
by calling sdk.AccAddress on the valAddress bytes. This ensures the proper
bech32 format (valoper prefix) is accepted and self-removal for standard
validator addresses works correctly.
- Around line 299-302: In the GetValidator error handling block around line
299-302, the current code returns ErrAddressIsNotAValidator for all errors from
k.sk.GetValidator, which masks real staking keeper failures. Instead, check if
the error is specifically a not-found error (typically using
sdk.ErrUnknownAddress or similar) and only then return
ErrAddressIsNotAValidator; for all other errors, return the original error
unchanged to preserve important debugging information about store or query
issues.

In `@x/poa/keeper/msg_server_remove_validator_self.go`:
- Around line 10-18: The RemoveValidatorSelf message handler is missing an
authority validation check before mutating the validator set. Add an explicit
authority gate check in the RemoveValidatorSelf method that verifies
msg.Authority equals k.authority before calling ExecuteRemoveValidatorSelf. If
the authority does not match, return an appropriate error (typically an
unauthorized or permission denied error) to enforce the POA module's authority
gate invariant that requires authority verification before any validator set
mutations.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 74b0d139-8c9c-4763-834d-6feec76e4257

📥 Commits

Reviewing files that changed from the base of the PR and between 2d77d09 and 417d913.

⛔ Files ignored due to path filters (1)
  • x/poa/types/tx.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (9)
  • proto/poa/tx.proto
  • x/poa/keeper/keeper.go
  • x/poa/keeper/msg_server_remove_validator_self.go
  • x/poa/keeper/msg_server_remove_validator_self_test.go
  • x/poa/keeper/msg_server_remove_validator_test.go
  • x/poa/types/codec.go
  • x/poa/types/errors.go
  • x/poa/types/events.go
  • x/poa/types/message_remove_validator_self.go

Comment thread x/poa/keeper/keeper.go
Comment thread x/poa/keeper/keeper.go
Comment on lines +299 to +302
validator, err := k.sk.GetValidator(ctx, valAddress)
if err != nil {
return types.ErrAddressIsNotAValidator
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not collapse all GetValidator failures into “not a validator”.

Returning ErrAddressIsNotAValidator for every error masks real staking keeper failures (store/query issues) and can mislead callers. Only map the specific not-found case; propagate other errors unchanged.

Proposed fix
 	validator, err := k.sk.GetValidator(ctx, valAddress)
 	if err != nil {
-		return types.ErrAddressIsNotAValidator
+		if errors.IsOf(err, stakingtypes.ErrNoValidatorFound) {
+			return types.ErrAddressIsNotAValidator
+		}
+		return err
 	}
🤖 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 `@x/poa/keeper/keeper.go` around lines 299 - 302, In the GetValidator error
handling block around line 299-302, the current code returns
ErrAddressIsNotAValidator for all errors from k.sk.GetValidator, which masks
real staking keeper failures. Instead, check if the error is specifically a
not-found error (typically using sdk.ErrUnknownAddress or similar) and only then
return ErrAddressIsNotAValidator; for all other errors, return the original
error unchanged to preserve important debugging information about store or query
issues.

Comment thread x/poa/keeper/msg_server_remove_validator_self.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
x/poa/keeper/keeper.go (2)

293-297: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Parse validatorAddress as a validator address, not an account address.

At Line 293, sdk.AccAddressFromBech32 can reject valid validator-form bech32 input and break self-removal for normal validator addresses. Parse with sdk.ValAddressFromBech32 first.

Proposed fix
-	accAddress, err := sdk.AccAddressFromBech32(validatorAddress)
+	valAddress, err := sdk.ValAddressFromBech32(validatorAddress)
 	if err != nil {
 		return err
 	}
-	valAddress := sdk.ValAddress(accAddress)
+	accAddress := sdk.AccAddress(valAddress)
🤖 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 `@x/poa/keeper/keeper.go` around lines 293 - 297, In the code block where
validatorAddress is being processed, the issue is that sdk.AccAddressFromBech32
is being used to parse validatorAddress, which expects an account-format bech32
address. Instead, parse validatorAddress directly as a validator address using
sdk.ValAddressFromBech32, which will properly handle validator-format bech32
addresses (like those with "val" prefix). Remove the intermediate step that
converts from account address to validator address using sdk.ValAddress, and
assign the result directly from sdk.ValAddressFromBech32 to valAddress.

299-303: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not convert every GetValidator failure into “not a validator.”

At Line 300-302, all errors are mapped to types.ErrAddressIsNotAValidator. This hides real staking/store failures and makes debugging harder. Only map the specific not-found case; return other errors unchanged.

Proposed fix
 	validator, err := k.sk.GetValidator(ctx, valAddress)
 	if err != nil {
 		ctx.Logger().Warn("Error getting validator", "error", err)
-		return types.ErrAddressIsNotAValidator
+		if errors.IsOf(err, stakingtypes.ErrNoValidatorFound) {
+			return types.ErrAddressIsNotAValidator
+		}
+		return err
 	}
🤖 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 `@x/poa/keeper/keeper.go` around lines 299 - 303, The error handling in the
GetValidator call block is converting all errors to
types.ErrAddressIsNotAValidator, which masks real failures in the staking keeper
or store. Instead of catching all errors at line 300-302 with the
k.sk.GetValidator call on valAddress, you need to differentiate between a
specific not-found error (which should map to types.ErrAddressIsNotAValidator)
and other error types that represent actual failures and should be returned
unchanged. Check if the returned error is specifically a "not found" or "not a
validator" type error before converting it; otherwise, return the original error
to preserve debugging information and avoid hiding real staking/store failures.
🤖 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.

Duplicate comments:
In `@x/poa/keeper/keeper.go`:
- Around line 293-297: In the code block where validatorAddress is being
processed, the issue is that sdk.AccAddressFromBech32 is being used to parse
validatorAddress, which expects an account-format bech32 address. Instead, parse
validatorAddress directly as a validator address using sdk.ValAddressFromBech32,
which will properly handle validator-format bech32 addresses (like those with
"val" prefix). Remove the intermediate step that converts from account address
to validator address using sdk.ValAddress, and assign the result directly from
sdk.ValAddressFromBech32 to valAddress.
- Around line 299-303: The error handling in the GetValidator call block is
converting all errors to types.ErrAddressIsNotAValidator, which masks real
failures in the staking keeper or store. Instead of catching all errors at line
300-302 with the k.sk.GetValidator call on valAddress, you need to differentiate
between a specific not-found error (which should map to
types.ErrAddressIsNotAValidator) and other error types that represent actual
failures and should be returned unchanged. Check if the returned error is
specifically a "not found" or "not a validator" type error before converting it;
otherwise, return the original error to preserve debugging information and avoid
hiding real staking/store failures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c0c13364-75ba-445a-828f-959bf4b1d38f

📥 Commits

Reviewing files that changed from the base of the PR and between 417d913 and 453c00b.

📒 Files selected for processing (1)
  • x/poa/keeper/keeper.go

Comment thread proto/poa/tx.proto Outdated

// MsgRemoveValidatorSelf defines a message for a validator to remove itself
message MsgRemoveValidatorSelf {
option (cosmos.msg.v1.signer) = "validator_address";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to address

Comment thread proto/poa/tx.proto Outdated
message MsgRemoveValidatorResponse {}

// MsgRemoveValidatorSelf defines a message for a validator to remove itself
message MsgRemoveValidatorSelf {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to SelfRemoveValidator

Comment thread x/poa/keeper/keeper.go Outdated
return types.ErrAddressIsNotAValidator
}

// Prevent the last bonded validator from removing itself. If it is not bonded, the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is not needed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if preventing last validator removal is present in x/staking

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked x/staking, and there is no last-validator guard. Removed the one that I added.

"github.com/xrplevm/node/v10/x/poa/types"
)

func (k msgServer) RemoveValidatorSelf(goCtx context.Context, msg *types.MsgRemoveValidatorSelf) (*types.MsgRemoveValidatorSelfResponse, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename function

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
x/poa/keeper/keeper.go (2)

293-298: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Parse self-removal input as validator bech32, not account bech32.

Line 293 currently uses sdk.AccAddressFromBech32, which rejects valid validator-operator formatted inputs and can break self-removal for normal validator addresses.

Suggested fix
-	accAddress, err := sdk.AccAddressFromBech32(validatorAddress)
+	valAddress, err := sdk.ValAddressFromBech32(validatorAddress)
 	if err != nil {
 		return err
 	}
-	valAddress := sdk.ValAddress(accAddress)
+	accAddress := sdk.AccAddress(valAddress)
+	_ = accAddress
#!/bin/bash
# Verify address parsing choices on self-remove path
rg -n -C3 'ExecuteSelfRemoveValidator|AccAddressFromBech32|ValAddressFromBech32' x/poa/keeper/keeper.go
rg -n -C2 'TestMsgServer_SelfRemoveValidator|validatorAddress|MsgSelfRemoveValidator' x/poa/keeper/msg_server_self_remove_validator_test.go
🤖 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 `@x/poa/keeper/keeper.go` around lines 293 - 298, The address parsing in the
self-removal validator code path is currently using sdk.AccAddressFromBech32 to
parse validatorAddress, which incorrectly attempts to parse a
validator-formatted bech32 address as an account address. Fix this by directly
parsing validatorAddress as a validator address using sdk.ValAddressFromBech32
instead, and assign the result directly to valAddress, eliminating the
intermediate accAddress conversion step. This change should be made in the code
block handling validatorAddress parsing around the ExecuteSelfRemoveValidator or
MsgSelfRemoveValidator logic.

299-303: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not collapse all staking lookup failures into “not a validator”.

Line 302 maps every GetValidator error to ErrAddressIsNotAValidator, which hides real keeper/storage failures and reduces debuggability.

Suggested fix
 	validator, err := k.sk.GetValidator(ctx, valAddress)
 	if err != nil {
 		ctx.Logger().Warn("Error getting validator", "error", err)
-		return types.ErrAddressIsNotAValidator
+		if errors.IsOf(err, stakingtypes.ErrNoValidatorFound) {
+			return types.ErrAddressIsNotAValidator
+		}
+		return err
 	}
#!/bin/bash
# Verify current GetValidator error mapping sites
rg -n -C3 'GetValidator\(ctx, valAddress\)|ErrAddressIsNotAValidator' x/poa/keeper/keeper.go
🤖 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 `@x/poa/keeper/keeper.go` around lines 299 - 303, The GetValidator call in the
validator lookup block returns all errors (keeper failures, storage issues,
etc.) as ErrAddressIsNotAValidator, which obscures real system errors. Instead
of mapping every error from k.sk.GetValidator(ctx, valAddress) to
types.ErrAddressIsNotAValidator, distinguish between cases where the validator
truly does not exist versus actual keeper/storage errors, and handle them
appropriately by either propagating the real error for debugging or returning
the appropriate error type only when the validator is genuinely not found.
🤖 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 `@proto/poa/tx.proto`:
- Around line 53-57: Add an authority field to the MsgSelfRemoveValidator
message definition to enable authority validation in the message handler. Insert
a new field after the existing address field in MsgSelfRemoveValidator that
captures the authority address, following the same pattern used for the address
field with appropriate cosmos protobuf annotations for scalar types. This will
allow the handler to perform the required msg.Authority == k.authority check
before any validator-set mutations.

---

Duplicate comments:
In `@x/poa/keeper/keeper.go`:
- Around line 293-298: The address parsing in the self-removal validator code
path is currently using sdk.AccAddressFromBech32 to parse validatorAddress,
which incorrectly attempts to parse a validator-formatted bech32 address as an
account address. Fix this by directly parsing validatorAddress as a validator
address using sdk.ValAddressFromBech32 instead, and assign the result directly
to valAddress, eliminating the intermediate accAddress conversion step. This
change should be made in the code block handling validatorAddress parsing around
the ExecuteSelfRemoveValidator or MsgSelfRemoveValidator logic.
- Around line 299-303: The GetValidator call in the validator lookup block
returns all errors (keeper failures, storage issues, etc.) as
ErrAddressIsNotAValidator, which obscures real system errors. Instead of mapping
every error from k.sk.GetValidator(ctx, valAddress) to
types.ErrAddressIsNotAValidator, distinguish between cases where the validator
truly does not exist versus actual keeper/storage errors, and handle them
appropriately by either propagating the real error for debugging or returning
the appropriate error type only when the validator is genuinely not found.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: d314bd96-a6e3-413e-9a6d-18b55008d39e

📥 Commits

Reviewing files that changed from the base of the PR and between 453c00b and ae63a8d.

⛔ Files ignored due to path filters (1)
  • x/poa/types/tx.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (7)
  • proto/poa/tx.proto
  • x/poa/keeper/keeper.go
  • x/poa/keeper/msg_server_self_remove_validator.go
  • x/poa/keeper/msg_server_self_remove_validator_test.go
  • x/poa/types/codec.go
  • x/poa/types/events.go
  • x/poa/types/message_self_remove_validator.go

Comment thread proto/poa/tx.proto

@AdriaCarrera AdriaCarrera left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add integration tests in poa testsuite

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@tests/integration/poa_test.go`:
- Around line 647-654: The assertion with require.Contains on the err.Error()
call does not guard against err being nil. If the Validator query unexpectedly
succeeds, err will be nil and calling err.Error() will cause a panic instead of
a clean test failure. Before calling err.Error() in the require.Contains
statement, first assert that err is not nil using require.Error to ensure the
validator query actually failed as expected before checking the error message.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: d736e6d0-2bc0-48e1-844d-a38aea32c302

📥 Commits

Reviewing files that changed from the base of the PR and between ae63a8d and 0c66f64.

📒 Files selected for processing (1)
  • tests/integration/poa_test.go

Comment thread tests/integration/poa_test.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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 `@tests/integration/poa_test.go`:
- Around line 763-770: The test is dereferencing err without first asserting it
is not nil, which can cause a panic and hide the actual test failure. Before
calling err.Error() in the require.Contains assertion on the line after the
Validator call, add a guard using require.Error(s.T(), err) to ensure the error
is not nil and the Validator call actually failed as expected.
- Around line 701-705: The code checks that the validators slice is non-empty
but does not validate that tc.valIndex is within the valid range of the
validators slice before indexing into it on the line where validator is
assigned. Add a bounds check using require.Less or require.True to ensure that
tc.valIndex is less than len(validators) after confirming validators is
non-empty, preventing potential panics when test cases use indices like 1 on
single-validator setups.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 626fb00b-9bd9-460c-9aed-45e99765fd7f

📥 Commits

Reviewing files that changed from the base of the PR and between 0c66f64 and 5015bbc.

📒 Files selected for processing (1)
  • tests/integration/poa_test.go

Comment on lines +701 to +705
validators := s.Network().GetValidators()
require.NotZero(s.T(), len(validators))

validator := validators[tc.valIndex]
valAddr, err := sdktypes.ValAddressFromBech32(validator.OperatorAddress)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Validate tc.valIndex bounds before indexing validators.

Line 702 only checks non-empty validators, but cases use index 1; this can panic on a single-validator setup.

Suggested fix
 			validators := s.Network().GetValidators()
 			require.NotZero(s.T(), len(validators))
+			require.Greater(s.T(), len(validators), tc.valIndex)

 			validator := validators[tc.valIndex]
🤖 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 `@tests/integration/poa_test.go` around lines 701 - 705, The code checks that
the validators slice is non-empty but does not validate that tc.valIndex is
within the valid range of the validators slice before indexing into it on the
line where validator is assigned. Add a bounds check using require.Less or
require.True to ensure that tc.valIndex is less than len(validators) after
confirming validators is non-empty, preventing potential panics when test cases
use indices like 1 on single-validator setups.

Comment on lines +763 to +770
_, err = s.Network().GetStakingClient().Validator(
s.Network().GetContext(),
&stakingtypes.QueryValidatorRequest{
ValidatorAddr: nonValAddr.String(),
},
)
require.Contains(s.T(), err.Error(), fmt.Sprintf("validator %s not found", nonValAddr.String()))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard err before checking the not-found message in non-validator precheck.

Line 769 dereferences err without asserting it exists, which can panic and hide the real failure.

Suggested fix
 	_, err = s.Network().GetStakingClient().Validator(
 		s.Network().GetContext(),
 		&stakingtypes.QueryValidatorRequest{
 			ValidatorAddr: nonValAddr.String(),
 		},
 	)
+	require.Error(s.T(), err)
 	require.Contains(s.T(), err.Error(), fmt.Sprintf("validator %s not found", nonValAddr.String()))
📝 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.

Suggested change
_, err = s.Network().GetStakingClient().Validator(
s.Network().GetContext(),
&stakingtypes.QueryValidatorRequest{
ValidatorAddr: nonValAddr.String(),
},
)
require.Contains(s.T(), err.Error(), fmt.Sprintf("validator %s not found", nonValAddr.String()))
_, err = s.Network().GetStakingClient().Validator(
s.Network().GetContext(),
&stakingtypes.QueryValidatorRequest{
ValidatorAddr: nonValAddr.String(),
},
)
require.Error(s.T(), err)
require.Contains(s.T(), err.Error(), fmt.Sprintf("validator %s not found", nonValAddr.String()))
🤖 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 `@tests/integration/poa_test.go` around lines 763 - 770, The test is
dereferencing err without first asserting it is not nil, which can cause a panic
and hide the actual test failure. Before calling err.Error() in the
require.Contains assertion on the line after the Validator call, add a guard
using require.Error(s.T(), err) to ensure the error is not nil and the Validator
call actually failed as expected.

…n' of github.com:aluque-peersyst/xrplevm-node into feat/add-validator-self-remove-message
@AdriaCarrera AdriaCarrera merged commit 9bc17ff into xrplevm:main Jun 23, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants