Skip to content

switch to collections in the ibchooks module.#2768

Open
nagarajdivine wants to merge 1 commit into
mainfrom
feat/collections-ibchooks
Open

switch to collections in the ibchooks module.#2768
nagarajdivine wants to merge 1 commit into
mainfrom
feat/collections-ibchooks

Conversation

@nagarajdivine

@nagarajdivine nagarajdivine commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Description


Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.

  • Targeted PR against correct branch (see CONTRIBUTING.md).
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/).
  • Added relevant godoc comments.
  • Added relevant changelog entries under .changelog/unreleased (see Adding Changes).
  • Re-reviewed Files changed in the Github PR explorer.
  • Review Codecov Report in the comment section below once CI passes.

Summary by CodeRabbit

  • New Features

    • Added an upgrade path for ibchooks storage, including migration support to the newer collections-based format.
    • Updated module registration so the new version is recognized during app startup.
  • Bug Fixes

    • Improved persistence handling for packet callbacks, packet acknowledgements, and module parameters.
    • Legacy ibchooks data is now migrated automatically, helping preserve existing on-chain state during upgrades.

@nagarajdivine nagarajdivine requested a review from a team as a code owner June 26, 2026 18:02
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The ibchooks module now uses collections-backed storage for params, packet callbacks, and packet ack actors. App wiring passes a KVStoreService into the keeper, and the module registers a migration while bumping consensus version to 2.

Changes

ibchooks collections storage

Layer / File(s) Summary
Collection keys and wiring
x/ibchooks/types/keys.go, app/app.go, .changelog/unreleased/features/2492-collections-ibchooks.md
Defines collection prefixes for params, packet callbacks, and packet acks, and updates app construction to pass a KVStoreService into the keeper. The changelog entry notes the switch to collections.
Keeper schema and params
x/ibchooks/keeper/keeper.go, x/ibchooks/keeper/params.go
The keeper now builds a collections schema, stores params in a collections item, and reads and writes params through that item.
Packet state storage
x/ibchooks/keeper/keeper.go
Packet callback and packet ack actor storage now uses collections maps keyed by channel and sequence, with collections-based deletes and the existing ack payload decoding.
Legacy migration
x/ibchooks/keeper/migrations.go
A migrator scans legacy KV entries, rekeys channel::seq and channel::seq::ack entries into collections storage, and removes the migrated legacy keys.
Migration registration
x/ibchooks/module.go
The module registers the migration and bumps consensus version to 2.

Sequence Diagram(s)

Migration registration

sequenceDiagram
  participant AppModule
  participant keeper.NewMigrator
  participant cfg.RegisterMigration
  participant Migrator
  participant Keeper
  AppModule->>keeper.NewMigrator: create Migrator from Keeper
  AppModule->>cfg.RegisterMigration: register version 1 migration
  cfg.RegisterMigration->>Migrator: call Migrate1to2
  Migrator->>Keeper: rekey legacy state into collections storage
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I hopped by night with a twitchy nose,
🥕 collections in the burrow, tidy rows.
Packet crumbs and params now stay neat,
A migrator thumps the old trails clean and sweet.
Hop hop! The keeper learned a shiny new beat.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The module switches to collections, but it also adds a versioned migration, which conflicts with #2492's no-migration requirement. Remove the migration path and keep the collections refactor compatible without a versioned state migration.
Out of Scope Changes check ⚠️ Warning The new migration files and migration registration add versioned upgrade plumbing that is outside #2492's collections-only scope. Drop the migration plumbing or move it to a separate follow-up if backward compatibility truly needs it.
✅ 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 matches the main change: switching ibchooks to collections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/collections-ibchooks

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
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
x/ibchooks/keeper/migrations.go (2)

54-78: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: log unrecognized/unparseable legacy entries instead of silently skipping.

Entries that fail ParseUint (Lines 58-61, 66-69) or hit default (Lines 73-74) are left in place with no record. For a one-shot upgrade migration, emitting their count/keys at warn level would make post-upgrade auditing of any orphaned legacy state much easier.

🤖 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/ibchooks/keeper/migrations.go` around lines 54 - 78, The migration in
migrations.go silently skips legacy entries that fail ParseUint or do not match
the expected key patterns, which makes orphaned state hard to audit. Update the
legacy-entry loop in the migration logic that handles packetCallbacks and
packetAckActors to emit a warning (ideally including the key or at least a
count) whenever an entry falls through the ParseUint failure paths or the
default branch, while still continuing the migration. Keep the existing
Set/Delete behavior intact and use the existing migration/keeper context to
locate the logging point.

24-83: 🗄️ Data Integrity & Integration | 🔵 Trivial

Verify the legacy key/value contract the whole migration depends on.

The migration is safe based on the codebase history, but the comment oversimplifies the Params preservation:

  1. Legacy keys: Confirmed. Legacy packet keys are raw strings channel::seq and channel::seq::ack with no prefix byte. The skip logic (checking for 0x01, 0x02, 0x03) and parsing logic hold.
  2. Legacy values: Confirmed. Callback values are raw bech32 strings and ack values are raw bytes; the migration preserves these byte-for-byte using the new collections codecs.
  3. Params encoding: The claim "Params are already byte-identical" is risky without qualification. Legacy v1 used cdc.MustMarshal(&params) (proto/AMINO). The new v2 uses codec.CollValue[types.Params](cdc), which delegates to the codec. While this produces identical bytes only if the codec instance and Params proto definition are strictly unchanged, failure to ensure this invariant could cause decode panics on post-upgrade reads.

Action: Add a comment or run a schema check to ensure the Params proto definition and binary encoding remain unchanged in this upgrade to guarantee byte compatibility. If the proto definition or codec changed, an explicit Params migration is required.

🤖 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/ibchooks/keeper/migrations.go` around lines 24 - 83, Verify and document
the legacy key/value contract that Migrate1to2 in Migrator depends on,
especially the Params path. Keep the existing packet key detection and value
preservation logic, but add an explicit safeguard/comment around
types.ParamsKeyBz and codec.CollValue[types.Params](cdc) to confirm the Params
bytes remain compatible with the legacy cdc.MustMarshal encoding. If the Params
proto/codec has changed, update the migration to rewrite Params explicitly
instead of relying on byte-identical preservation.
🤖 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/ibchooks/keeper/keeper.go`:
- Around line 135-141: GetPacketCallback and GetPacketAckActor are treating
every collections.Get failure as a missing key, which hides real
read/decoding/storage errors. Update both methods to only return an empty result
when the error is collections.ErrNotFound, and otherwise propagate or surface
the unexpected error. Use the existing Keeper methods GetPacketCallback and
GetPacketAckActor plus the packetCallbacks/packetAckActors collections lookups
to apply the standard collections error handling pattern.

---

Nitpick comments:
In `@x/ibchooks/keeper/migrations.go`:
- Around line 54-78: The migration in migrations.go silently skips legacy
entries that fail ParseUint or do not match the expected key patterns, which
makes orphaned state hard to audit. Update the legacy-entry loop in the
migration logic that handles packetCallbacks and packetAckActors to emit a
warning (ideally including the key or at least a count) whenever an entry falls
through the ParseUint failure paths or the default branch, while still
continuing the migration. Keep the existing Set/Delete behavior intact and use
the existing migration/keeper context to locate the logging point.
- Around line 24-83: Verify and document the legacy key/value contract that
Migrate1to2 in Migrator depends on, especially the Params path. Keep the
existing packet key detection and value preservation logic, but add an explicit
safeguard/comment around types.ParamsKeyBz and
codec.CollValue[types.Params](cdc) to confirm the Params bytes remain compatible
with the legacy cdc.MustMarshal encoding. If the Params proto/codec has changed,
update the migration to rewrite Params explicitly instead of relying on
byte-identical preservation.
🪄 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: 23b58747-065d-438e-a603-7121691d214f

📥 Commits

Reviewing files that changed from the base of the PR and between c2c5002 and 4c7e407.

📒 Files selected for processing (7)
  • .changelog/unreleased/features/2492-collections-ibchooks.md
  • app/app.go
  • x/ibchooks/keeper/keeper.go
  • x/ibchooks/keeper/migrations.go
  • x/ibchooks/keeper/params.go
  • x/ibchooks/module.go
  • x/ibchooks/types/keys.go

Comment on lines 135 to 141
func (k Keeper) GetPacketCallback(ctx sdk.Context, channel string, packetSequence uint64) string {
store := ctx.KVStore(k.storeKey)
return string(store.Get(GetPacketCallbackKey(channel, packetSequence)))
v, err := k.packetCallbacks.Get(ctx, collections.Join(channel, packetSequence))
if err != nil {
return ""
}
return v
}

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.

🩺 Stability & Availability | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In cosmossdk.io/collections v1.4.0, does Map.Get return collections.ErrNotFound for a missing key, and what other errors can it return (e.g. value decoding errors)?

💡 Result:

In cosmossdk.io/collections v1.4.0, the Map.Get method does return collections.ErrNotFound when a requested key is missing from the underlying storage [1][2]. Beyond ErrNotFound, Map.Get can return other errors, most notably those related to encoding and decoding [1]. Because the collections framework relies on value codecs to deserialize data retrieved from the store, any failure during this deserialization process will result in an error, typically categorized under collections.ErrEncoding (which is aliased to the SDK's codec encoding error) [1]. Additionally, because Map.Get interacts with the underlying KVStore, it can propagate errors returned by the storage layer itself (e.g., database access issues). Developers frequently use errors.Is(err, collections.ErrNotFound) to check for missing keys specifically, allowing them to handle such cases—such as by returning a default value—differently than actual system or data integrity errors [2].

Citations:


🏁 Script executed:

cat -n x/ibchooks/keeper/keeper.go | sed -n '162,184p'

Repository: provenance-io/provenance

Length of output: 970


🏁 Script executed:

rg --type go "func.*GetParams.*Returns" -A 20

Repository: provenance-io/provenance

Length of output: 162


🏁 Script executed:

rg --type go "func.*GetParams" -A 15

Repository: provenance-io/provenance

Length of output: 162


🏁 Script executed:

rg --type go "GetParams" -n -B 2 -A 15

Repository: provenance-io/provenance

Length of output: 162


🏁 Script executed:

find . -name "params.go" -type f | head -5

Repository: provenance-io/provenance

Length of output: 311


🏁 Script executed:

cat -n ./x/exchange/keeper/params.go | grep -A 15 "func.*GetParams"

Repository: provenance-io/provenance

Length of output: 1363


🏁 Script executed:

rg --type go "collections.ErrNotFound" -n -B 3 -A 5 | head -40

Repository: provenance-io/provenance

Length of output: 162


🏁 Script executed:

rg "ErrNotFound" --type go -n | head -20

Repository: provenance-io/provenance

Length of output: 162


Avoid swallowing non-ErrNotFound errors from collections Get.

GetPacketCallback and GetPacketAckActor return empty results on any error from Get. In cosmossdk.io/collections, Map.Get returns collections.ErrNotFound only for missing keys, while other errors (e.g., decoding failures, storage corruption) propagate distinct values. Handling all errors identically masks data integrity issues, potentially dropping in-flight callbacks or actors instead of surfacing the failure.

Match the standard pattern: return empty only when the key is missing, and propagate or panic on actual errors.

🛠 Proposed alignment for GetPacketCallback
 func (k Keeper) GetPacketCallback(ctx sdk.Context, channel string, packetSequence uint64) string {
 	v, err := k.packetCallbacks.Get(ctx, collections.Join(channel, packetSequence))
 	if err != nil {
-		return ""
+		if errors.Is(err, collections.ErrNotFound) {
+			return ""
+		}
+		panic(err)
 	}
 	return v
 }
🛠 Proposed alignment for GetPacketAckActor
 func (k Keeper) GetPacketAckActor(ctx sdk.Context, channel string, packetSequence uint64) (string, string) {
 	rawData, err := k.packetAckActors.Get(ctx, collections.Join(channel, packetSequence))
 	if err != nil {
-		return "", ""
+		if errors.Is(err, collections.ErrNotFound) {
+			return "", ""
+		}
+		panic(err)
 	}
 	// ... rest of function
📝 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
func (k Keeper) GetPacketCallback(ctx sdk.Context, channel string, packetSequence uint64) string {
store := ctx.KVStore(k.storeKey)
return string(store.Get(GetPacketCallbackKey(channel, packetSequence)))
v, err := k.packetCallbacks.Get(ctx, collections.Join(channel, packetSequence))
if err != nil {
return ""
}
return v
}
func (k Keeper) GetPacketCallback(ctx sdk.Context, channel string, packetSequence uint64) string {
v, err := k.packetCallbacks.Get(ctx, collections.Join(channel, packetSequence))
if err != nil {
if errors.Is(err, collections.ErrNotFound) {
return ""
}
panic(err)
}
return v
}
🤖 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/ibchooks/keeper/keeper.go` around lines 135 - 141, GetPacketCallback and
GetPacketAckActor are treating every collections.Get failure as a missing key,
which hides real read/decoding/storage errors. Update both methods to only
return an empty result when the error is collections.ErrNotFound, and otherwise
propagate or surface the unexpected error. Use the existing Keeper methods
GetPacketCallback and GetPacketAckActor plus the packetCallbacks/packetAckActors
collections lookups to apply the standard collections error handling pattern.

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.

Switch to collections in the ibchooks module.

1 participant