Skip to content

fix: Store authority in AttesterInfo and check for authz; proto-gen#362

Open
alpe wants to merge 6 commits intomainfrom
security/authority-verification2
Open

fix: Store authority in AttesterInfo and check for authz; proto-gen#362
alpe wants to merge 6 commits intomainfrom
security/authority-verification2

Conversation

@alpe
Copy link
Contributor

@alpe alpe commented Feb 24, 2026

Overview

Replaces #358

Summary by CodeRabbit

  • Chores

    • Updated many dependencies across the ecosystem (protocol buffers/tooling, Docker/container tooling, OpenTelemetry, Go modules and indirect libraries).
  • Refactor

    • Strengthened attester-set authorization with earlier validation and unified authority checks to prevent unauthorized or malformed operations.
  • API

    • Stored attester identity switched from a validator-style field to an authority-style field in attester records (data representation updated).
  • Tests

    • Centralized test setup with a helper and expanded coverage for join/leave/attest authorization and payload validation.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 24, 2026

📝 Walkthrough

Walkthrough

Switches attester identity from Validator to Authority, introduces authority-based authorization checks and early vote-length validation in Attest, updates proto and tests to reflect the field rename, and applies broad dependency version updates in go.mod.

Changes

Cohort / File(s) Summary
Dependency Management
go.mod
Many module version bumps and indirect dependency adjustments (google.golang.org/genproto, bufbuild/, protovalidate → v1.1.3, otelconnect, docker/moby-related, golang.org/x/, etc.). No source API signature changes.
Protocol Buffers
modules/proto/evabci/network/v1/attester.proto
Renamed validatorauthority in AttesterInfo (kept field tag 1) and changed Cosmos scalar annotation from cosmos.ValidatorAddressString to cosmos.AddressString.
Keeper RPCs / Authorization
modules/network/keeper/msg_server.go
Replaced prior in-attester-set validator membership checks with assertValidValidatorAuthority (authority-based validation); added early vote-length validation in Attest; JoinAttesterSet/LeaveAttesterSet now use/store AttesterInfo.Authority and return Unauthorized on mismatches.
Tests / Test Helpers
modules/network/keeper/msg_server_test.go
Added newTestServer helper and bytes import; updated tests to use the helper; added TestLeaveAttesterSet; extended TestJoinAttesterSet and TestAttest scenarios to cover authority storage and mismatch/unauthorized cases.
Types / Structs
modules/...
Usage of types.AttesterInfo updated to populate/expect Authority instead of Validator across keeper and tests. No exported function signatures changed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped through fields both old and new,
Swapped Validator for Authority true,
Tests trimmed neat with a helper’s cheer,
Proto and deps moved the tree a gear,
A rabbit’s nibble — tidy, swift, and few.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: storing authority in AttesterInfo, implementing authorization checks, and regenerating proto files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch security/authority-verification2

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 and usage tips.

@alpe alpe requested a review from randygrok February 24, 2026 16:01
alpe added 2 commits February 24, 2026 17:33
* main:
  fix(network): add vote payload validation in Attest handler (#360)
@alpe alpe marked this pull request as ready for review February 25, 2026 13:01
@alpe alpe requested a review from a team as a code owner February 25, 2026 13:01
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
modules/network/keeper/msg_server.go (1)

205-233: ⚠️ Potential issue | 🟠 Major

LeaveAttesterSet does not delete the AttesterInfo record.

RemoveAttesterSetMember removes the entry from AttesterSet but leaves the corresponding AttesterInfo record in the store. A stale AttesterInfo entry poses no immediate exploit (the GetValidatorIndex check in Attest acts as a secondary gate), but it leaks storage and could confuse future queries or tooling that iterates AttesterInfo.

Consider adding a DeleteAttesterInfo(ctx, msg.ConsensusAddress) (or equivalent collection Remove) call alongside RemoveAttesterSetMember.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@modules/network/keeper/msg_server.go` around lines 205 - 233, The
LeaveAttesterSet handler currently removes the member from the AttesterSet but
leaves the AttesterInfo record; update LeaveAttesterSet to also delete the
AttesterInfo entry for msg.ConsensusAddress (e.g., call a keeper method like
DeleteAttesterInfo or RemoveAttesterInfo after RemoveAttesterSetMember) and
handle and wrap any error from that deletion (similar to how
RemoveAttesterSetMember errors are wrapped) before emitting the event so the
store won't retain stale AttesterInfo records.
🧹 Nitpick comments (2)
go.mod (1)

1-3: go 1.25.6 is valid but one minor behind — consider bumping to go 1.26.0.

Go 1.26 arrived in February 2026 and is now the latest stable release. go1.25.6 was released on 2026-01-15 and is a valid version, so there is no correctness issue, but upgrading the go directive keeps you on an actively maintained release.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@go.mod` around lines 1 - 3, Update the Go version in the module directive:
change the existing "go 1.25.6" directive in go.mod to "go 1.26.0" so the module
builds against the latest stable Go release; ensure you run "go mod tidy" or a
quick build to verify no toolchain breakages after updating the "go" directive.
modules/network/keeper/msg_server_test.go (1)

159-197: TestAttestVotePayloadValidation still uses inline setup — minor inconsistency with newTestServer.

All other test functions now use newTestServer, but TestAttestVotePayloadValidation still hand-rolls the same boilerplate. This is low priority but worth aligning for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@modules/network/keeper/msg_server_test.go` around lines 159 - 197, Replace
the inline test setup in TestAttestVotePayloadValidation with a call to the
shared helper newTestServer to keep consistency: remove the manual
NewMockStakingKeeper / MakeTestEncodingConfig / NewKeeper / msgServer /
CreateMultiStore / ctx construction and instead call newTestServer(...) to
obtain the msgServer (or server), keeper and sdk.Context (and any test
addresses), then reuse those in the rest of the test when building params,
attester state, and calling server.Attest; ensure the same preconditions
(SetParams, SetAttesterSetMember, SetAttesterInfo, BuildValidatorIndexMap) are
applied to the returned keeper/context so behavior is unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@modules/network/keeper/msg_server_test.go`:
- Around line 310-322: Update the "not_in_set" case in TestAttest to expect the
authorization error instead of collections.ErrNotFound: change the expErr from
collections.ErrNotFound to sdkerrors.ErrUnauthorized in the test case for
types.MsgAttest (the same adjustment done for LeaveAttesterSet), so the test
asserts the intended "not in attester set" unauthorized path when
Keeper/production sentinel is fixed.
- Around line 225-237: The test case "not_in_set" in msg_server_test.go
documents the current bug instead of asserting intended behavior; after fixing
production code to use collections.ErrNotFound in Keeper logic, update the
"not_in_set" test (the table entry named "not_in_set" that constructs a
MsgLeaveAttesterSet with Authority and ConsensusAddress set to
ownerAddr.String()) to expect sdkerrors.ErrInvalidRequest instead of
collections.ErrNotFound, remove or update the NOTE comment, and change expErr to
sdkerrors.ErrInvalidRequest so the test matches the fixed error path.

In `@modules/network/keeper/msg_server.go`:
- Around line 46-55: The branch checking for sdkerrors.ErrNotFound after calling
k.AttesterInfo.Get is dead because collections.Map.Get returns
collections.ErrNotFound, not sdkerrors.ErrNotFound; update the error check to
compare against collections.ErrNotFound (e.g., use errors.Is(err,
collections.ErrNotFound)) and keep the existing
sdkerr.Wrapf(sdkerrors.ErrUnauthorized, ...) return for the "consensus address
not in attester set" case; ensure the import for collections.ErrNotFound is
added if missing and leave the fallback sdkerr.Wrapf(err, "attester set") for
other errors.
- Around line 209-218: In LeaveAttesterSet, fix the unreachable "not-in-set"
branch by checking for collections.ErrNotFound (the sentinel returned by
k.AttesterInfo.Get) instead of sdkerrors.ErrNotFound; update the error check in
the block that calls k.AttesterInfo.Get to use errors.Is(err,
collections.ErrNotFound) and keep the existing
sdkerr.Wrapf(sdkerrors.ErrInvalidRequest, ...) return for that case so callers
receive the intended ErrInvalidRequest message when the consensus address is
missing; ensure the change references k.AttesterInfo.Get and the
LeaveAttesterSet handler.

---

Outside diff comments:
In `@modules/network/keeper/msg_server.go`:
- Around line 205-233: The LeaveAttesterSet handler currently removes the member
from the AttesterSet but leaves the AttesterInfo record; update LeaveAttesterSet
to also delete the AttesterInfo entry for msg.ConsensusAddress (e.g., call a
keeper method like DeleteAttesterInfo or RemoveAttesterInfo after
RemoveAttesterSetMember) and handle and wrap any error from that deletion
(similar to how RemoveAttesterSetMember errors are wrapped) before emitting the
event so the store won't retain stale AttesterInfo records.

---

Nitpick comments:
In `@go.mod`:
- Around line 1-3: Update the Go version in the module directive: change the
existing "go 1.25.6" directive in go.mod to "go 1.26.0" so the module builds
against the latest stable Go release; ensure you run "go mod tidy" or a quick
build to verify no toolchain breakages after updating the "go" directive.

In `@modules/network/keeper/msg_server_test.go`:
- Around line 159-197: Replace the inline test setup in
TestAttestVotePayloadValidation with a call to the shared helper newTestServer
to keep consistency: remove the manual NewMockStakingKeeper /
MakeTestEncodingConfig / NewKeeper / msgServer / CreateMultiStore / ctx
construction and instead call newTestServer(...) to obtain the msgServer (or
server), keeper and sdk.Context (and any test addresses), then reuse those in
the rest of the test when building params, attester state, and calling
server.Attest; ensure the same preconditions (SetParams, SetAttesterSetMember,
SetAttesterInfo, BuildValidatorIndexMap) are applied to the returned
keeper/context so behavior is unchanged.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 223422d and 2979766.

⛔ Files ignored due to path filters (6)
  • go.sum is excluded by !**/*.sum
  • modules/network/module/v1/module.pb.go is excluded by !**/*.pb.go
  • modules/network/types/attester.pb.go is excluded by !**/*.pb.go
  • modules/network/types/query.pb.gw.go is excluded by !**/*.pb.gw.go
  • modules/network/types/tx.pb.go is excluded by !**/*.pb.go
  • modules/proto/buf.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • go.mod
  • modules/network/keeper/msg_server.go
  • modules/network/keeper/msg_server_test.go
  • modules/proto/evabci/network/v1/attester.proto

Copy link
Contributor

@randygrok randygrok left a comment

Choose a reason for hiding this comment

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

some comments left, important to fix

@alpe
Copy link
Contributor Author

alpe commented Feb 26, 2026

Good feedback! Thank you

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@modules/network/keeper/msg_server.go`:
- Around line 223-235: The current assertValidValidatorAuthority relies solely
on AttesterInfo.Get and can authorize addresses that were removed from
AttesterSet but left in AttesterInfo; update assertValidValidatorAuthority to
also check membership via k.AttesterSet.Has(ctx, consensusAddress) and return an
unauthorized error if Has is false, or alternatively modify
RemoveAttesterSetMember to also delete the corresponding k.AttesterInfo entry so
AttesterInfo.Get cannot be used alone for auth; locate the function
assertValidValidatorAuthority and the methods AttesterInfo.Get, AttesterSet.Has,
and RemoveAttesterSetMember to implement the chosen fix.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2979766 and 2bbbb8b.

📒 Files selected for processing (2)
  • modules/network/keeper/msg_server.go
  • modules/network/keeper/msg_server_test.go

@alpe alpe requested a review from randygrok February 26, 2026 16:12
@alpe
Copy link
Contributor Author

alpe commented Feb 26, 2026

@oderabbitai review again

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
modules/network/keeper/msg_server.go (1)

233-235: Consider a more descriptive error message for authority mismatch.

The current message "address %s" doesn't clearly indicate that it's an authority mismatch. A more explicit message would help with debugging and auditing.

💡 Suggested improvement
 	if v.Authority != authority {
-		return sdkerr.Wrapf(sdkerrors.ErrUnauthorized, "address %s", authority)
+		return sdkerr.Wrapf(sdkerrors.ErrUnauthorized, "authority mismatch for consensus address %s: expected %s, got %s", consensusAddress, v.Authority, authority)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@modules/network/keeper/msg_server.go` around lines 233 - 235, The
unauthorized error for the authority check is too vague; update the return in
the authority mismatch branch (the if comparing v.Authority and authority in the
msg server handler) to return a descriptive wrapped sdkerrors.ErrUnauthorized
that includes both the expected authority (v.Authority) and the caller/provided
authority (authority) so the message clearly states "authority mismatch" or
"unauthorized: expected <expected>, got <actual>" to aid debugging and auditing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@modules/network/keeper/msg_server.go`:
- Around line 233-235: The unauthorized error for the authority check is too
vague; update the return in the authority mismatch branch (the if comparing
v.Authority and authority in the msg server handler) to return a descriptive
wrapped sdkerrors.ErrUnauthorized that includes both the expected authority
(v.Authority) and the caller/provided authority (authority) so the message
clearly states "authority mismatch" or "unauthorized: expected <expected>, got
<actual>" to aid debugging and auditing.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1208936 and ebc7c76.

📒 Files selected for processing (1)
  • modules/network/keeper/msg_server.go

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.

3 participants