Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(api!): replace Router with PortKeeper in IBCKeeper. #6138

Merged
merged 12 commits into from
Apr 11, 2024

Conversation

bznein
Copy link
Contributor

@bznein bznein commented Apr 10, 2024

Description

Removes Router from IBCKeeper and replace calls to it with calls to the new function PortKeeper.GetRoute()

Note: I didn't add tests for this new method for the reason that GetRoute on the underlying router is already tested, and I wasn't able to get a proper set up for the test. I'm more than open to suggestions!

closes: #6133


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 the correct branch (see CONTRIBUTING.md).
  • Linked to GitHub issue with discussion and accepted design, OR link to spec that describes this work.
  • Code follows the module structure standards and Go style guide.
  • [] Wrote unit and integration tests.
  • Updated relevant documentation (docs/).
  • Added relevant godoc comments.
  • Provide a conventional commit message to follow the repository standards.
  • Include a descriptive changelog entry when appropriate. This may be left to the discretion of the PR reviewers. (e.g. chores should be omitted from changelog)
  • Re-reviewed Files changed in the GitHub PR explorer.
  • Review SonarCloud Report in the comment section below once CI passes.

Summary by CodeRabbit

  • Refactor
    • Enhanced channel operations by replacing Router with PortKeeper across modules for improved reliability.
    • Introduced GetRoute() function for better route handling in channel operations.
  • Bug Fixes
    • Improved application callbacks for channel operations like opening, closing, and timeouts.

Copy link
Contributor

coderabbitai bot commented Apr 10, 2024

Walkthrough

The update primarily focuses on the removal of the Router from the IBCKeeper and its replacement with the PortKeeper in the IBC-related modules. This change aims to streamline routing within the IBC modules by centralizing it through the PortKeeper, enhancing code maintainability and reducing redundancy.

Changes

Files Changes
modules/apps/27-interchain-accounts/.../ibc_middleware_test.go, modules/apps/29-fee/ibc_middleware_test.go, modules/apps/callbacks/ibc_middleware_test.go, modules/apps/transfer/ibc_module_test.go Replaced references to Router with PortKeeper in test functions.
docs/docs/05-migrations/13-v8-to-v9.md Updated function names and removal of Router field documentation.
modules/core/05-port/keeper/keeper.go Added GetRoute() function to the Keeper struct.
CHANGELOG.md Updated to reflect the removal of Router from the IBC core keeper and utilization of PortKeeper instead.

Assessment against linked issues

Objective Addressed Explanation
Remove Router from IBCKeeper and use PortKeeper (#6133)
Add GetRoute() to PortKeeper (#6133)
Replace usage of Router in core with PortKeeper.Route() (#6133)

Possibly related issues


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

Comment on lines 85 to 88
// GetRoute() returns a IBCModule for a given module.
func (k Keeper) GetRoute(module string) (types.IBCModule, bool) {
return k.Router.GetRoute(module)
}
Copy link
Contributor

@coderabbitai coderabbitai bot Apr 10, 2024

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The initialization of the Router field in the Keeper struct is not explicitly shown in the provided output from the NewKeeper function. The function initializes various other keepers and components, but there is no direct reference to the initialization of a Router field. This suggests that either the Router is initialized elsewhere, or it might not be properly initialized, which could lead to a nil pointer dereference when GetRoute() is called.

Given the absence of explicit initialization in the provided constructor and the direct use of Router.GetRoute(module) in the GetRoute() method without any nil checks, there is a potential risk of encountering a nil pointer dereference if Router is not properly initialized elsewhere in the code.

Based on this analysis, the review comment concerning the need to ensure that the Router field is properly initialized before calling GetRoute() is justified. Further investigation into the complete initialization of Router across the codebase would be necessary to fully ensure safety against nil pointer dereferences.

Analysis chain

Ensure that the Router field is properly initialized before calling GetRoute(), as it directly accesses Router which could potentially be nil.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Check for any nil checks or initializations before using Router in GetRoute.
ast-grep --lang go --pattern $'func (k Keeper) GetRoute($_) $_ {
  k.Router.GetRoute($_)
}'

Length of output: 92



Script:

#!/bin/bash
# Search for the constructor or initialization method of Keeper where Router might be initialized
ast-grep --lang go --pattern $'func NewKeeper($$$) *Keeper {
  $$$
}'

# Verify the actual implementation of GetRoute() to ensure it matches the description and check for nil handling
ast-grep --lang go --pattern $'func (k Keeper) GetRoute($_) $_ {
  $$$
}'

Length of output: 3673

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know if this is actually a problem, we could error in the case of the router not being sealed, but at the moment the only usage of the Sealed() fn is to check whether or not we can seal a router a second time.

Copy link
Contributor

Choose a reason for hiding this comment

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

@chatton, you're right to consider the implications of the router's state on the system's behavior. The sealing of the router is primarily a safety mechanism to prevent modifications after its initial setup, which is crucial for ensuring that the routing remains consistent and error-free throughout the application's lifecycle.

If the router isn't sealed when GetRoute() is called, and there's a possibility of modification, it could lead to inconsistencies or errors during routing. Implementing error handling or a check within GetRoute() to ensure the router is sealed before proceeding could be a good safeguard. This would help maintain the integrity of the routing process, especially in a dynamic environment where changes to the router might be attempted after initial configuration.

Reviewing the current error handling strategies around the router's usage and considering enhancements could further strengthen the system's robustness against such issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@chatton yeah I'm conflicted :) We could definitely check for k.Router == nil || !k.Router.Sealed() here and either panic or return nil, false in that case. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we currently panic if the router isn't set on the core keeper? I'm thinking this would be quite the misconfiguration by a chain developer but might be nice to do what we recently did for the queryRouter (c70c9c6) and panic as early as possible as opposed to when a chain launches and does some sort of lookup on it.

Might be overkill though 🤷

Copy link
Contributor

@DimitrisJim DimitrisJim Apr 10, 2024

Choose a reason for hiding this comment

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

To the rabbit's point. I'd probably want to make the Router private and have an accesor method for it that does the nil/unsealed check, if that was possible. But that's out of scope for this PR. I'd be fine with adding these sanity checks for the time being if others agree.

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah I wouldn't be against panicking if the router is not sealed, as it shouldn't be used when it is partially configured.

Normally wouldn't like to panic, but the alternative of false, nil just means a silent failure IMO.

Copy link
Member

Choose a reason for hiding this comment

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

It would be nice to maybe also make the Router unexported in 05-port.

Aside from that I think there's some other improvements we could probably make to APIs of the core IBCKeeper.
For example right now we require users to create a port router in app.go and bind ibc appmodules there, similarly we retrieve the new light client module router from the clientKeeper and AddRoute for each light client module.

It may be nice to have everything flow through the IBCKeeper, as it essentially is a facade around the set of submodules which make up core ibc.

e.g. IBCKeeper.RegisterClientModule(lightClient) and IBCKeeper.RegisterIBCApplication or something like that, could be useful at some point, maybe these changes may be warranted with depinject work so I think we can hold off on them for now and discuss later. Feel free to drop any thoughts 💭

Copy link
Contributor

Choose a reason for hiding this comment

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

definitely sounds nice on first read. Don't see why we should be exposing these routers in app.go instead of keeping them as an impl detail of the core keeper.

Copy link
Contributor

@chatton chatton left a comment

Choose a reason for hiding this comment

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

LGTM, left a few small suggestions but nothing major 👍

modules/core/05-port/keeper/keeper.go Outdated Show resolved Hide resolved
modules/core/05-port/keeper/keeper.go Outdated Show resolved Hide resolved
Comment on lines 85 to 88
// GetRoute() returns a IBCModule for a given module.
func (k Keeper) GetRoute(module string) (types.IBCModule, bool) {
return k.Router.GetRoute(module)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know if this is actually a problem, we could error in the case of the router not being sealed, but at the moment the only usage of the Sealed() fn is to check whether or not we can seal a router a second time.

Copy link
Contributor

@DimitrisJim DimitrisJim left a comment

Choose a reason for hiding this comment

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

lgtm. Lets wait for another opinion on the rabbit's point though. 🐇

Copy link
Contributor

@crodriguezvega crodriguezvega left a comment

Choose a reason for hiding this comment

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

You're on fire, @bznein! 🔥🧯

@@ -33,7 +33,6 @@ type Keeper struct {
ConnectionKeeper *connectionkeeper.Keeper
ChannelKeeper *channelkeeper.Keeper
PortKeeper *portkeeper.Keeper
Router *porttypes.Router
Copy link
Contributor

Choose a reason for hiding this comment

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

Removing this is API breaking, so we should document it in the migration docs of v9. I will also change the PR name to reflect this.

@crodriguezvega crodriguezvega changed the title chore: replace Router with PortKeeper in IBCKeeper. chore(api!): replace Router with PortKeeper in IBCKeeper. Apr 10, 2024
Copy link
Member

@damiannolan damiannolan left a comment

Choose a reason for hiding this comment

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

Code changes look great! Thanks for picking this up, just left one comment about aligning APIs as we now have two routers in ibc core - one for ibc apps and one for ibc client modules

modules/core/05-port/keeper/keeper.go Outdated Show resolved Hide resolved
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.

Remove Router from IBCKeeper and use PortKeeper
5 participants