-
Notifications
You must be signed in to change notification settings - Fork 597
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
Add IBC hooks for every IBC method #2296
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this new middleware, @nicolaslara! I have left some comments after doing a first review.
As a general remark, we would appreciate if you can groups the import like this:
import (
// standard libraries
// external libraries
// ibc-go
}
This is just the code style we are trying to keep in the project. :)
It would be also nice to add documentation for this new middleware. And we also need a changelog entry (I would say under Features
).
Looks also like gofumpt
is complaining a bit on CI as well.
} | ||
|
||
type IBCAppHooksOnChanOpenInitOverride interface { | ||
OnChanOpenInitOverride(im IBCMiddleware, ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) (string, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: do you mind to put each argument on a new line (like we do here)? I think it's easier for readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed it to only one line specifically for readability (so it's easy to scan which methods are defined on each interface, considering the arguments are the same as for the functions they override), but happy to change it back to one arg per line
OnChanCloseConfirmAfterHook(ctx sdk.Context, portID, channelID string, err error) | ||
} | ||
|
||
// OnAcknowledgementPacket Hooks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would change the order and put the OnRecvPacket
hooks before the OnAcknowledgementPacket
hooks.
chainC *ibctesting.TestChain | ||
|
||
path *ibctesting.Path | ||
pathAToC *ibctesting.Path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think chainC
and pathAToC
are not used, right? So maybe you can just remove them...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes! that was left over from copy pasting a transfer test. Removed.
} | ||
|
||
// Recv | ||
type TestRecvOverrides struct{ Status *Status } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type TestRecvOverrides struct{ Status *Status } | |
type TestRecvOverrideHooks struct{ Status *Status } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed
} | ||
|
||
// Send | ||
type TestSendOverrides struct{ Status *Status } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type TestSendOverrides struct{ Status *Status } | |
type TestSendOverrideHooks struct{ Status *Status } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed
modules/apps/hooks/hooks.go
Outdated
ibcexported "github.com/cosmos/ibc-go/v5/modules/core/exported" | ||
) | ||
|
||
type IBCAppHooks interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if we could shave off the IBCApp
prefix from all these types...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed
testCases := []struct { | ||
msg string | ||
malleate func(*testutils.Status) | ||
recvIsSource bool // the receiving chain is the source of the coin originally |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you actually need to test the scenario of the receiving chain being the original source of the tokens? If not, maybe this can be removed to simplify the logic of the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call! simplifying.
} | ||
|
||
// Recv | ||
type TestRecvOverrides struct{ Status *Status } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a nit, but I think that you could also make Status
unexported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can... but then you have to add a NewTestRecvOverrideHooks
, which I find less clean. Since it's only used in testing, I don't see the harm in having it be exported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't feel strongly either way, though. Happy to change it if you do
return err | ||
} | ||
|
||
type TestSendBeforeAfterHooks struct{ Status *Status } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both TestSendOverrides
and TestSendBeforeAfterHooks
are not used in the tests. Do you plan to write tests for them as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was planning to add those, but realized that that's quite hard to test because the ICS4Middlware (that should contain the hooks) is inside the IBCFeeKeeper (which doesn't export the ics4Wrapper).
The easiest way to test this would be to add the testing hook directly on simapp, but I'm not sure if that's too intrusive.
I've removed those for now. We will probably test all of these functions with an app that uses them (i.e.: the packet forwarding middleware)
@@ -0,0 +1,142 @@ | |||
package ibc_hooks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to move this file inside the types
folder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that would create an import cycle, as ibc_module.go depends on the hooks and the hooks on the middleware struct defined in that file
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #2296 +/- ##
==========================================
- Coverage 79.52% 78.82% -0.71%
==========================================
Files 175 177 +2
Lines 12069 12226 +157
==========================================
+ Hits 9598 9637 +39
- Misses 2047 2152 +105
- Partials 424 437 +13
|
Co-authored-by: Carlos Rodriguez <carlos@interchain.io>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @nicolaslara, thanks for your PR! It seems to me like the intention of this middleware is to make writing middleware more standardized. Since people now implement the before/after/override for each function (most will be no-op) and your middleware then orders the calls.
My concern is that to implement the hook interface, we triple the number of functions expected to be implemented.
Why is this approach better than just having folks implement the interface as-is, and documenting how they can use the callback to execute logic before/after the underlying layer or override entirely? Especially since this middleware is not doing anything other than ordering the logic for them.
type OnChanOpenInitOverrideHooks interface { | ||
OnChanOpenInitOverride(im IBCMiddleware, ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) (string, error) | ||
} | ||
type OnChanOpenInitBeforeHooks interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't the before and after hooks return errors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe they should. I can update them to return errors
Hey @nicolaslara can you respond to the above? Seems like this can be closed, thanks |
hey @AdityaSripal, yeah, this can be closed. I still like this way of extending the ibc module better but we can implement it on our end if we want (and so can anyone else who prefers it).
I think the opposite is true. Since we're matching based on the interface, you can implement only the functions you want to override, instead of implementing a whole IBCModule/ICSWrapper structs. The structs in testing_hooks.go are an example of what a user would need to implement. Now, after re-reading this, I think if we want to provide an interface to better extend the core IBC modules, it doesn't make sense to do it as a middleware, the hooks could instead be baked in on the core implementation |
Thank you, @nicolaslara. |
Description
This introduces a middleware for IBC that allows users to write their own hooks.
This was developed to allow the packet forward middleware send the tokens back if a hop fails, but it useful in general for simplifying middleware development.
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.
docs/
) or specification (x/<module>/spec/
)godoc
comments.Unreleased
section inCHANGELOG.md
Files changed
in the Github PR explorerCodecov Report
in the comment section below once CI passes