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

refactor: cleanup middleware stacks #1248

Merged
merged 21 commits into from
Apr 28, 2022

Conversation

seantking
Copy link
Contributor

@seantking seantking commented Apr 12, 2022

Description

Cleaning up the middleware stacks using evmos as inspiration.

closes: #773


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.
  • Code follows the module structure standards.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added relevant godoc comments.
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer
  • Review Codecov Report in the comment section below once CI passes

testing/simapp/app.go Outdated Show resolved Hide resolved
// create IBC module from bottom to top of stack
var transferStack porttypes.IBCModule
transferStack = transfer.NewIBCModule(app.TransferKeeper)
transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This works fine and I like the UX.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we should add the routing right after:

ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack)

Copy link
Contributor

Choose a reason for hiding this comment

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

I love this UX as well ❤️

testing/mock/ibc_module.go Outdated Show resolved Hide resolved
// Create static IBC router, add app routes, then set and seal it
// pass in top-level (fully-wrapped) IBCModules to IBC Router
ibcRouter := porttypes.NewRouter()
ibcRouter.AddRoute(icacontrollertypes.SubModuleName, icaControllerIBCModule).
Copy link
Contributor Author

@seantking seantking Apr 13, 2022

Choose a reason for hiding this comment

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

Wasn't sure if we needed this still. I'm guessing we do, but I'm not 100% sure why. We don't add the fee module middleware for example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For any observers, we need this because the controller module owns the port capability and the ica-auth module owns the channel capability. thanks @colin-axner for the reminder

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I'll add a comment explaining this

// create IBC module from bottom to top of stack
var transferStack porttypes.IBCModule
transferStack = transfer.NewIBCModule(app.TransferKeeper)
transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we should add the routing right after:

ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack)

testing/simapp/app.go Outdated Show resolved Hide resolved
testing/mock/ibc_module.go Outdated Show resolved Hide resolved
testing/simapp/app.go Show resolved Hide resolved
testing/simapp/app.go Show resolved Hide resolved
@codecov-commenter
Copy link

Codecov Report

Merging #1248 (e0e405e) into main (311379f) will increase coverage by 0.04%.
The diff coverage is 57.89%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1248      +/-   ##
==========================================
+ Coverage   80.05%   80.10%   +0.04%     
==========================================
  Files         166      166              
  Lines       11910    11951      +41     
==========================================
+ Hits         9535     9573      +38     
- Misses       1914     1920       +6     
+ Partials      461      458       -3     
Impacted Files Coverage Δ
modules/apps/27-interchain-accounts/module.go 57.69% <ø> (ø)
modules/apps/29-fee/module.go 55.55% <ø> (ø)
...ps/27-interchain-accounts/controller/ibc_module.go 86.00% <33.33%> (-7.48%) ⬇️
modules/apps/29-fee/ibc_module.go 95.10% <69.23%> (+3.67%) ⬆️
modules/apps/29-fee/types/codec.go 43.75% <0.00%> (-26.25%) ⬇️
modules/apps/29-fee/types/keys.go 96.66% <0.00%> (-3.34%) ⬇️
modules/apps/29-fee/keeper/keeper.go 92.34% <0.00%> (-0.91%) ⬇️
modules/core/04-channel/types/packet.go 67.56% <0.00%> (ø)
modules/apps/29-fee/keeper/msg_server.go 78.04% <0.00%> (+3.04%) ⬆️
... and 1 more

app.IBCFeeKeeper = ibcfeekeeper.NewKeeper(appCodec, keys[ibcfeetypes.StoreKey], app.GetSubspace(ibcfeetypes.ModuleName),
app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper,
)

// Create Transfer Stack
Copy link
Member

Choose a reason for hiding this comment

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

Should we add a comment similar to this?

I think even something simple like that makes the flow of control much clearer

@fedekunze
Copy link
Contributor

awesome! feel free to use our BDD tests too ❤️

@seantking seantking marked this pull request as ready for review April 14, 2022 13:12
@seantking
Copy link
Contributor Author

awesome! feel free to use our BDD tests too heart

Nice, I'll check em out. Can you link?

Great work btw, I really like the pattern you used. Thanks for the inspiration 🤝

@seantking seantking requested a review from fedekunze April 14, 2022 13:13
Copy link
Contributor

@fedekunze fedekunze left a comment

Choose a reason for hiding this comment

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

Copy link
Contributor

@colin-axner colin-axner left a comment

Choose a reason for hiding this comment

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

Excellent!

testing/simapp/app.go Outdated Show resolved Hide resolved
)
// Create Interchain Accounts Stack
// SendPacket, since it is originating from the application to core IBC:
// icaAuthModuleKeeper.SendPacket -> icaControllerKeeper.SendPacket -> channel.SendPacket
Copy link
Contributor

Choose a reason for hiding this comment

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

technically the icaAuthModuleKeeper calls SendTx, maybe we should reflect this approach?

testing/simapp/app.go Outdated Show resolved Hide resolved
testing/simapp/app.go Show resolved Hide resolved
testing/simapp/app.go Outdated Show resolved Hide resolved
testing/simapp/app.go Outdated Show resolved Hide resolved
testing/simapp/app.go Outdated Show resolved Hide resolved
Copy link
Member

@AdityaSripal AdityaSripal left a comment

Choose a reason for hiding this comment

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

Are we not incentivizing ICA packets? I think it would be a good example to show how to stack more than 1 middleware in case of the controller

chanCap *capabilitytypes.Capability,
packet exported.PacketI,
) error {
panic("SendPacket not supported for ICA controller module")
Copy link
Member

Choose a reason for hiding this comment

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

ICA auth SendPacket should call this function and then this function will pass the call one layer up.

Copy link
Contributor

@colin-axner colin-axner Apr 21, 2022

Choose a reason for hiding this comment

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

Why would this occur? ICA auth calls SendTx. ICA auth shouldn't send non ICA packets?

Copy link
Member

Choose a reason for hiding this comment

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

ICA auth is being wrapped by ICA correct? In that case we will want the packet flow to be:

ICA-Auth -SendPacket-> ICA -SendPacket-> IBC

The ICA middleware in this case will do nothing but forward the packet one layer up. This is to keep consistency and to make sure ICA-auth packets are not missed by additional middleware that is wrapping the stack

Copy link
Contributor

@colin-axner colin-axner Apr 25, 2022

Choose a reason for hiding this comment

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

ICA auth is being wrapped by ICA correct?

Only partially (not all callbacks/interfaces should be implemented). SendPacket usage is replaced by SendTx

ICA controller constructs the packet and thus calls SendPacket. ICA Auth shouldn't call SendPacket. It could bypass SendTx by calling SendPacket directly, if we panic, we disable this functionality. I don't understand the purpose of SendTx if we do allow bypassing. The spec doesn't indicate the appropriate functionality

// ICA Controller keeper
app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper(
appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName),
app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee
Copy link
Member

Choose a reason for hiding this comment

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

Should we include this comment for every IBC keeper so that it is clearer to people looking at this file?

@seantking seantking force-pushed the sean/issue#773-cleanup-middleware-stacks branch from 4254ea7 to 6624b73 Compare April 19, 2022 16:40
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.

Left a couple of small nits, but more or less looks good to go from what I can see!
Would be good to get a couple of more acks before merging.

Nice work 👍

Comment on lines 13 to 14
"github.com/cosmos/ibc-go/v3/modules/core/exported"
ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported"
Copy link
Member

Choose a reason for hiding this comment

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

This is imported twice

Copy link
Contributor

Choose a reason for hiding this comment

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

we should add a linter for this

Copy link
Contributor

Choose a reason for hiding this comment

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

duplicate import is still there

func NewIBCModule(k keeper.Keeper, app porttypes.IBCModule) IBCModule {
return IBCModule{
keeper: k,
// NewIBCMiddlware creates a new IBCMiddlware given the keeper and underlying application
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// NewIBCMiddlware creates a new IBCMiddlware given the keeper and underlying application
// NewIBCMiddleware creates a new IBCMiddleware given the keeper and underlying application


icaModule := ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper)
// OnAckPacket as this is where fee's are paid out
Copy link
Member

Choose a reason for hiding this comment

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

nit: may as well be explicit

Suggested change
// OnAckPacket as this is where fee's are paid out
// OnAcknowledgementPacket as this is where fee's are paid out

Copy link
Contributor

@colin-axner colin-axner left a comment

Choose a reason for hiding this comment

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

LGTM! Nice work!


// Create Interchain Accounts Stack
// SendPacket, since it is originating from the application to core IBC:
// icaAuthModuleKeeper.SendPacket -> fee.SendPacket -> icaControllerKeeper.SendPacket -> channel.SendPacket
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, this doesn't make sense. If fee was in the stack, it should be above icaControllerKeeper. Futhermore, icaAuthModuleKeeper must call SendTx not SendPacket

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would say that the icaAuthModuleKeeper is still calling SendPacket it's just doing so via SendTx but I agree we should change to SendTx to be more explicit.

Comment on lines 433 to 437
var icaControllerStack porttypes.IBCModule
icaControllerStack = ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp("", scopedICAMockKeeper))
app.ICAAuthModule = icaControllerStack.(ibcmock.IBCModule)
icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper)
icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer this change to be made in a followup pr. Ideally it would come with tests. But if contained in this pr, the fee should be at the top of the stack. Generic middleware cannot be inserted between ICA auth and controller because the SendTx API

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, good point. I'll remove it and do it in a follow up PR.

testing/simapp/app.go Outdated Show resolved Hide resolved
Comment on lines +461 to +463
feeMockModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp(MockFeePort, scopedFeeMockKeeper))
app.FeeMockModule = feeMockModule
feeWithMockModule := ibcfee.NewIBCMiddleware(feeMockModule, app.IBCFeeKeeper)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is possible to combine mockIBCModule and the fee mock stack. Ideally the fee version just wouldn't be set for the isolated mock module usage. I'd be in favor of a followup pr fixing this


mockIBCModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp(ibcmock.ModuleName, scopedIBCMockKeeper))
// RecvPacket, message that originates from core IBC and goes down to app, the flow is the otherway
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// RecvPacket, message that originates from core IBC and goes down to app, the flow is the otherway
// RecvPacket, message that originates from core IBC and goes bottom to app, the flow is the other way

AddRoute(ibcmock.ModuleName+icacontrollertypes.SubModuleName, icaControllerStack) // ica with mock auth module stack route to ica (top level of middleware stack)

// Create Mock IBC Fee module stack for testing
// OnAckPacket as this is where fee's are paid out
Copy link
Contributor

Choose a reason for hiding this comment

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

Same nit as Damian's:

Suggested change
// OnAckPacket as this is where fee's are paid out
// OnAcknowledgementPacket as this is where fee's are paid out

// OnAckPacket as this is where fee's are paid out
// mockModule.OnAcknowledgementPacket -> fee.OnAcknowledgementPacket -> channel.OnAcknowledgementPacket

// RecvPacket, message that originates from core IBC and goes down to app, the flow is the otherway
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// RecvPacket, message that originates from core IBC and goes down to app, the flow is the otherway
// RecvPacket, message that originates from core IBC and goes bottom to app, the flow is the other way


// SendPacket, since it is originating from the application to core IBC:
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be more clear if you revert the order? So the explanation for SendPacket first, then RecvPacket's, and finally OnAcknowledgementPacket's

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree

@@ -163,3 +167,22 @@ func (im IBCModule) OnTimeoutPacket(

return im.app.OnTimeoutPacket(ctx, packet, relayer)
}

// SendPacket implements the ICS4 Wrapper interface
func (im IBCMiddleware) SendPacket(
Copy link
Member

Choose a reason for hiding this comment

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

Ok I understand now why you've done it this way.

I think it should be documented in this function's go-doc that the packet is going to get constructed directly by ICA controller and sent to IBC rather than being created by ICA-auth.

Reading this file, made me think SendPacket wasn't happening at all when really it is happening through the controller's SendTx function

@seantking
Copy link
Contributor Author

I think this is good to merge now?

Copy link
Contributor

@colin-axner colin-axner left a comment

Choose a reason for hiding this comment

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

Wahoo!! Great job 🚀

Comment on lines 13 to 14
"github.com/cosmos/ibc-go/v3/modules/core/exported"
ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported"
Copy link
Contributor

Choose a reason for hiding this comment

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

duplicate import is still there

Copy link
Member

@AdityaSripal AdityaSripal left a comment

Choose a reason for hiding this comment

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

Nice work! Could you create a new issue to tackle wrapping ICA with fee?

Comment on lines +457 to +459
feeMockModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp(MockFeePort, scopedFeeMockKeeper))
app.FeeMockModule = feeMockModule
feeWithMockModule := ibcfee.NewIBCMiddleware(feeMockModule, app.IBCFeeKeeper)
Copy link
Member

Choose a reason for hiding this comment

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

nit: why do you use different variables here, but with transfer you just reassign?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I needed to satisfy the compiler. The mock module is of type ibcmock.MockModule & the middleware is of type IBCMiddleware.

I think we could do a follow-up to create a mock middleware if it's useful.

@seantking seantking merged commit cc4cd7b into main Apr 28, 2022
@seantking seantking deleted the sean/issue#773-cleanup-middleware-stacks branch April 28, 2022 16:17
CosmosCar pushed a commit to caelus-labs/ibc-go that referenced this pull request Nov 6, 2023
<!--
Please read and fill out this form before submitting your PR.

Please make sure you have reviewed our contributors guide before
submitting your
first PR.
-->

## Overview

<!-- 
Please provide an explanation of the PR, including the appropriate
context,
background, goal, and rationale. If there is an issue with this
information,
please provide a tl;dr and link the issue. 
-->

## Checklist

<!-- 
Please complete the checklist to ensure that the PR is ready to be
reviewed.

IMPORTANT:
PRs should be left in Draft until the below checklist is completed.
-->

- [ ] New and updated code has appropriate documentation
- [ ] New and updated code has new and/or updated testing
- [ ] Required CI checks are passing
- [ ] Visual proof for any user facing features like CLI or
documentation updates
- [ ] Linked issues closed with keywords

---------

Co-authored-by: Manav Aggarwal <manavaggarwal1234@gmail.com>
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.

Organize middleware stacks
7 participants