Skip to content

Commit

Permalink
feat: Add handshake logic to ics29 (#307)
Browse files Browse the repository at this point in the history
* do handshake logic, create test file

* do cap logic and fix build

* open handshake implementation and tests

* remove prints

* Update modules/apps/29-fee/module.go

Co-authored-by: Sean King <seantking@users.noreply.github.com>

* debugging progress

* fee enabled flag

* cleanup handshake logic

* fix tests

* much cleaner simapp

* split module.go file

* cleanup and docs

* assert IBC interfaces are fulfilled in middleware

* Update modules/apps/transfer/module.go

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>

* fix unnecessary crossing hello logic

* fix version negotiation bugs and improve tests

* cleanup tests

* Apply suggestions from code review

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>

* address rest of colin comments

Co-authored-by: Sean King <seantking@users.noreply.github.com>
Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 27, 2021
1 parent 70c58af commit dd4f8c7
Show file tree
Hide file tree
Showing 14 changed files with 768 additions and 208 deletions.
41 changes: 41 additions & 0 deletions modules/apps/29-fee/fee_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package fee_test

import (
"testing"

"github.com/stretchr/testify/suite"

"github.com/cosmos/ibc-go/modules/apps/29-fee/types"
transfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types"
channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types"
ibctesting "github.com/cosmos/ibc-go/testing"
)

type FeeTestSuite struct {
suite.Suite

coordinator *ibctesting.Coordinator

chainA *ibctesting.TestChain
chainB *ibctesting.TestChain

path *ibctesting.Path
}

func (suite *FeeTestSuite) SetupTest() {
suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0))
suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1))

path := ibctesting.NewPath(suite.chainA, suite.chainB)
feeTransferVersion := channeltypes.MergeChannelVersions(types.Version, transfertypes.Version)
path.EndpointA.ChannelConfig.Version = feeTransferVersion
path.EndpointB.ChannelConfig.Version = feeTransferVersion
path.EndpointA.ChannelConfig.PortID = transfertypes.PortID
path.EndpointB.ChannelConfig.PortID = transfertypes.PortID
suite.path = path
}

func TestIBCFeeTestSuite(t *testing.T) {
suite.Run(t, new(FeeTestSuite))
}
178 changes: 178 additions & 0 deletions modules/apps/29-fee/ibc_module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package fee

import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"

"github.com/cosmos/ibc-go/modules/apps/29-fee/keeper"
"github.com/cosmos/ibc-go/modules/apps/29-fee/types"
channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types"
porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types"
ibcexported "github.com/cosmos/ibc-go/modules/core/exported"
)

// IBCModule implements the ICS26 callbacks for the fee middleware given the fee keeper and the underlying application.
type IBCModule struct {
keeper keeper.Keeper
app porttypes.IBCModule
}

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

// OnChanOpenInit implements the IBCModule interface
func (im IBCModule) OnChanOpenInit(
ctx sdk.Context,
order channeltypes.Order,
connectionHops []string,
portID string,
channelID string,
chanCap *capabilitytypes.Capability,
counterparty channeltypes.Counterparty,
version string,
) error {
mwVersion, appVersion := channeltypes.SplitChannelVersion(version)
// Since it is valid for fee version to not be specified, the above middleware version may be for a middleware
// lower down in the stack. Thus, if it is not a fee version we pass the entire version string onto the underlying
// application.
// If an invalid fee version was passed, we expect the underlying application to fail on its version negotiation.
if mwVersion == types.Version {
im.keeper.SetFeeEnabled(ctx, portID, channelID)
} else {
// middleware version is not the expected version for this midddleware. Pass the full version string along,
// if it not valid version for any other lower middleware, an error will be returned by base application.
appVersion = version
}

// call underlying app's OnChanOpenInit callback with the appVersion
return im.app.OnChanOpenInit(ctx, order, connectionHops, portID, channelID,
chanCap, counterparty, appVersion)
}

// OnChanOpenTry implements the IBCModule interface
func (im IBCModule) OnChanOpenTry(
ctx sdk.Context,
order channeltypes.Order,
connectionHops []string,
portID,
channelID string,
chanCap *capabilitytypes.Capability,
counterparty channeltypes.Counterparty,
version,
counterpartyVersion string,
) error {
mwVersion, appVersion := channeltypes.SplitChannelVersion(version)
cpMwVersion, cpAppVersion := channeltypes.SplitChannelVersion(counterpartyVersion)

// Since it is valid for fee version to not be specified, the above middleware version may be for a middleware
// lower down in the stack. Thus, if it is not a fee version we pass the entire version string onto the underlying
// application.
// If an invalid fee version was passed, we expect the underlying application to fail on its version negotiation.
if mwVersion == types.Version || cpMwVersion == types.Version {
if cpMwVersion != mwVersion {
return sdkerrors.Wrapf(types.ErrInvalidVersion, "fee versions do not match. self version: %s, counterparty version: %s", mwVersion, cpMwVersion)
}

im.keeper.SetFeeEnabled(ctx, portID, channelID)
} else {
// middleware versions are not the expected version for this midddleware. Pass the full version strings along,
// if it not valid version for any other lower middleware, an error will be returned by base application.
appVersion = version
cpAppVersion = counterpartyVersion
}

// call underlying app's OnChanOpenTry callback with the app versions
return im.app.OnChanOpenTry(ctx, order, connectionHops, portID, channelID,
chanCap, counterparty, appVersion, cpAppVersion)
}

// OnChanOpenAck implements the IBCModule interface
func (im IBCModule) OnChanOpenAck(
ctx sdk.Context,
portID,
channelID string,
counterpartyVersion string,
) error {
// If handshake was initialized with fee enabled it must complete with fee enabled.
// If handshake was initialized with fee disabled it must complete with fee disabled.
cpAppVersion := counterpartyVersion
if im.keeper.IsFeeEnabled(ctx, portID, channelID) {
var cpFeeVersion string
cpFeeVersion, cpAppVersion = channeltypes.SplitChannelVersion(counterpartyVersion)

if cpFeeVersion != types.Version {
return sdkerrors.Wrapf(types.ErrInvalidVersion, "expected counterparty version: %s, got: %s", types.Version, cpFeeVersion)
}
}
// call underlying app's OnChanOpenAck callback with the counterparty app version.
return im.app.OnChanOpenAck(ctx, portID, channelID, cpAppVersion)
}

// OnChanOpenConfirm implements the IBCModule interface
func (im IBCModule) OnChanOpenConfirm(
ctx sdk.Context,
portID,
channelID string,
) error {
// call underlying app's OnChanOpenConfirm callback.
return im.app.OnChanOpenConfirm(ctx, portID, channelID)
}

// OnChanCloseInit implements the IBCModule interface
func (im IBCModule) OnChanCloseInit(
ctx sdk.Context,
portID,
channelID string,
) error {
// TODO: Unescrow all remaining funds for unprocessed packets
im.keeper.DeleteFeeEnabled(ctx, portID, channelID)
return im.app.OnChanCloseInit(ctx, portID, channelID)
}

// OnChanCloseConfirm implements the IBCModule interface
func (im IBCModule) OnChanCloseConfirm(
ctx sdk.Context,
portID,
channelID string,
) error {
// TODO: Unescrow all remaining funds for unprocessed packets
im.keeper.DeleteFeeEnabled(ctx, portID, channelID)
return im.app.OnChanCloseConfirm(ctx, portID, channelID)
}

// OnRecvPacket implements the IBCModule interface.
func (im IBCModule) OnRecvPacket(
ctx sdk.Context,
packet channeltypes.Packet,
relayer sdk.AccAddress,
) ibcexported.Acknowledgement {
// TODO: Implement fee specific logic if fee is enabled for the given channel
return im.app.OnRecvPacket(ctx, packet, relayer)
}

// OnAcknowledgementPacket implements the IBCModule interface
func (im IBCModule) OnAcknowledgementPacket(
ctx sdk.Context,
packet channeltypes.Packet,
acknowledgement []byte,
relayer sdk.AccAddress,
) error {
// TODO: Implement fee specific logic if fee is enabled for the given channel
return im.app.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer)
}

// OnTimeoutPacket implements the IBCModule interface
func (im IBCModule) OnTimeoutPacket(
ctx sdk.Context,
packet channeltypes.Packet,
relayer sdk.AccAddress,
) error {
// TODO: Implement fee specific logic if fee is enabled for the given channel
return im.app.OnTimeoutPacket(ctx, packet, relayer)
}
Loading

0 comments on commit dd4f8c7

Please sign in to comment.