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: WriteAcknowledgement API #882

Merged
merged 8 commits into from
Feb 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (modules/core/02-client) [\#536](https://github.com/cosmos/ibc-go/pull/536) `GetSelfConsensusState` return type changed from bool to error.
* (channel) [\#644](https://github.com/cosmos/ibc-go/pull/644) Removes `CounterpartyHops` function from the ChannelKeeper.
* (testing) [\#776](https://github.com/cosmos/ibc-go/pull/776) Adding helper fn to generate capability name for testing callbacks

* (channel) [\#882](https://github.com/cosmos/ibc-go/pull/882) The `WriteAcknowledgement` API now takes `exported.Acknowledgement` instead of a byte array

### State Machine Breaking

Expand Down
26 changes: 26 additions & 0 deletions docs/migrations/v3-to-v4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Migrating from ibc-go v2 to v3

This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG.
Any changes that must be done by a user of ibc-go should be documented here.

There are four sections based on the four potential user groups of this document:
- Chains
- IBC Apps
- Relayers
- IBC Light Clients

**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated to bump the version number on major releases.
```go
github.com/cosmos/ibc-go/v3 -> github.com/cosmos/ibc-go/v4
```

No genesis or in-place migrations required when upgrading from v1 or v2 of ibc-go.

## Chains

### IS04 - Channel

The `WriteAcknowledgement` API now takes the `exported.Acknowledgement` type instead of passing in the acknowledgement byte array directly.
This is an API breaking change and as such IBC application developers will have to update any calls to `WriteAcknowledgement`.


13 changes: 9 additions & 4 deletions modules/core/04-channel/keeper/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ func (k Keeper) WriteAcknowledgement(
ctx sdk.Context,
chanCap *capabilitytypes.Capability,
packet exported.PacketI,
acknowledgement []byte,
acknowledgement exported.Acknowledgement,
) error {
channel, found := k.GetChannel(ctx, packet.GetDestPort(), packet.GetDestChannel())
if !found {
Expand Down Expand Up @@ -342,14 +342,19 @@ func (k Keeper) WriteAcknowledgement(
return types.ErrAcknowledgementExists
}

if len(acknowledgement) == 0 {
damiannolan marked this conversation as resolved.
Show resolved Hide resolved
if acknowledgement == nil {
return sdkerrors.Wrap(types.ErrInvalidAcknowledgement, "acknowledgement cannot be nil")
}

bz := acknowledgement.Acknowledgement()
Copy link
Member

Choose a reason for hiding this comment

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

You should still check if acknowledgement is nil first or it will panic

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call, thank you

if len(bz) == 0 {
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
if len(bz) == 0 {
if acknowledgement == nil || len(acknowledgement.Acknowledgement()) == 0 {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added the check as a separate if statement. Just my personal preference.

return sdkerrors.Wrap(types.ErrInvalidAcknowledgement, "acknowledgement cannot be empty")
Comment on lines +349 to 351
Copy link
Member

Choose a reason for hiding this comment

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

Just change this check to if acknowledgement == nil

}

// set the acknowledgement so that it can be verified on the other side
k.SetPacketAcknowledgement(
ctx, packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
types.CommitAcknowledgement(acknowledgement),
types.CommitAcknowledgement(bz),
)

// log that a packet acknowledgement has been written
Expand All @@ -362,7 +367,7 @@ func (k Keeper) WriteAcknowledgement(
"dst_channel", packet.GetDestChannel(),
)

EmitWriteAcknowledgementEvent(ctx, packet, channel, acknowledgement)
EmitWriteAcknowledgementEvent(ctx, packet, channel, bz)

return nil
}
Expand Down
24 changes: 17 additions & 7 deletions modules/core/04-channel/keeper/packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ func (suite *KeeperTestSuite) TestRecvPacket() {
func (suite *KeeperTestSuite) TestWriteAcknowledgement() {
var (
path *ibctesting.Path
ack []byte
ack exported.Acknowledgement
packet exported.PacketI
channelCap *capabilitytypes.Capability
)
Expand All @@ -504,7 +504,7 @@ func (suite *KeeperTestSuite) TestWriteAcknowledgement() {
func() {
suite.coordinator.Setup(path)
packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
ack = ibctesting.MockAcknowledgement
ack = ibcmock.MockAcknowledgement
channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
},
true,
Expand All @@ -513,13 +513,13 @@ func (suite *KeeperTestSuite) TestWriteAcknowledgement() {
// use wrong channel naming
suite.coordinator.Setup(path)
packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.InvalidID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp)
ack = ibctesting.MockAcknowledgement
ack = ibcmock.MockAcknowledgement
channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
}, false},
{"channel not open", func() {
suite.coordinator.Setup(path)
packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
ack = ibctesting.MockAcknowledgement
ack = ibcmock.MockAcknowledgement

err := path.EndpointB.SetChannelClosed()
suite.Require().NoError(err)
Expand All @@ -530,7 +530,7 @@ func (suite *KeeperTestSuite) TestWriteAcknowledgement() {
func() {
suite.coordinator.Setup(path)
packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
ack = ibctesting.MockAcknowledgement
ack = ibcmock.MockAcknowledgement
channelCap = capabilitytypes.NewCapability(3)
},
false,
Expand All @@ -540,14 +540,24 @@ func (suite *KeeperTestSuite) TestWriteAcknowledgement() {
func() {
suite.coordinator.Setup(path)
packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
ack = ibctesting.MockAcknowledgement
suite.chainB.App.GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ack)
ack = ibcmock.MockAcknowledgement
suite.chainB.App.GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ack.Acknowledgement())
channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
},
false,
},
{
"empty acknowledgement",
func() {
suite.coordinator.Setup(path)
packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
ack = ibcmock.NewMockEmptyAcknowledgement()
channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
},
false,
},
{
"acknowledgement is nil",
func() {
suite.coordinator.Setup(path)
packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
Expand Down
2 changes: 1 addition & 1 deletion modules/core/05-port/types/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ type ICS4Wrapper interface {
ctx sdk.Context,
chanCap *capabilitytypes.Capability,
packet exported.PacketI,
ack []byte,
ack exported.Acknowledgement,
) error
}

Expand Down
2 changes: 1 addition & 1 deletion modules/core/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacke
// NOTE: IBC applications modules may call the WriteAcknowledgement asynchronously if the
// acknowledgement is nil.
if ack != nil {
if err := k.ChannelKeeper.WriteAcknowledgement(ctx, cap, msg.Packet, ack.Acknowledgement()); err != nil {
if err := k.ChannelKeeper.WriteAcknowledgement(ctx, cap, msg.Packet, ack); err != nil {
return nil, err
}
}
Expand Down
2 changes: 1 addition & 1 deletion testing/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ func (endpoint *Endpoint) WriteAcknowledgement(ack exported.Acknowledgement, pac
channelCap := endpoint.Chain.GetChannelCapability(packet.GetDestPort(), packet.GetDestChannel())

// no need to send message, acting as a handler
err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.WriteAcknowledgement(endpoint.Chain.GetContext(), channelCap, packet, ack.Acknowledgement())
err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.WriteAcknowledgement(endpoint.Chain.GetContext(), channelCap, packet, ack)
if err != nil {
return err
}
Expand Down
23 changes: 23 additions & 0 deletions testing/mock/ack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package mock

// MockEmptyAcknowledgement implements the exported.Acknowledgement interface and always returns an empty byte string as Response
type MockEmptyAcknowledgement struct {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@colin-axner Open to suggestions with this. I don't want to add technical debt unnecessarily.

Copy link
Contributor

Choose a reason for hiding this comment

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

No this is great. None of the mock code has added any technical debt so far. I think it'll be useful to keep around

Response []byte
}

// NewMockEmptyAcknowledgement returns a new instance of MockEmptyAcknowledgement
func NewMockEmptyAcknowledgement() MockEmptyAcknowledgement {
return MockEmptyAcknowledgement{
Response: []byte{},
}
}

// Success implements the Acknowledgement interface
func (ack MockEmptyAcknowledgement) Success() bool {
return true
}

// Acknowledgement implements the Acknowledgement interface
func (ack MockEmptyAcknowledgement) Acknowledgement() []byte {
return []byte{}
}