diff --git a/CHANGELOG.md b/CHANGELOG.md index 129fabf0745..b8bb91dd822 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking +* (modules) [\#206](https://github.com/cosmos/ibc-go/pull/206) Expose `relayer sdk.AccAddress` on `OnRecvPacket`, `OnAcknowledgementPacket`, `OnTimeoutPacket` module callbacks to enable incentivization. * (02-client) [\#181](https://github.com/cosmos/ibc-go/pull/181) Remove 'InitialHeight' from UpdateClient Proposal. Only copy over latest consensus state from substitute client. * (06-solomachine) [\#169](https://github.com/cosmos/ibc-go/pull/169) Change FrozenSequence to boolean in solomachine ClientState. The solo machine proto package has been bumped from `v1` to `v2`. * (module/core/02-client) [\#165](https://github.com/cosmos/ibc-go/pull/165) Remove GetFrozenHeight from the ClientState interface. diff --git a/docs/migrations/ibc-migration-043.md b/docs/migrations/ibc-migration-043.md index 177bb3c7ef9..239900c179b 100644 --- a/docs/migrations/ibc-migration-043.md +++ b/docs/migrations/ibc-migration-043.md @@ -106,6 +106,8 @@ Application developers need to update their `OnRecvPacket` callback logic. The `OnRecvPacket` callback has been modified to only return the acknowledgement. The acknowledgement returned must implement the `Acknowledgement` interface. The acknowledgement should indicate if it represents a successful processing of a packet by returning true on `Success()` and false in all other cases. A return value of false on `Success()` will result in all state changes which occurred in the callback being discarded. More information can be found in the [documentation](https://github.com/cosmos/ibc-go/blob/main/docs/custom.md#receiving-packets). +The `OnRecvPacket`, `OnAcknowledgementPacket`, and `OnTimeoutPacket` callbacks are now passed the `sdk.AccAddress` of the relayer who relayed the IBC packet. Applications may use or ignore this information. + ## IBC Event changes The `packet_data` attribute has been deprecated in favor of `packet_data_hex`, in order to provide standardized encoding/decoding of packet data in events. While the `packet_data` event still exists, all relayers and IBC Event consumers are strongly encouraged to switch over to using `packet_data_hex` as soon as possible. diff --git a/modules/apps/transfer/module.go b/modules/apps/transfer/module.go index b0addfafed3..1c9afbe9f46 100644 --- a/modules/apps/transfer/module.go +++ b/modules/apps/transfer/module.go @@ -323,6 +323,7 @@ func (am AppModule) OnChanCloseConfirm( func (am AppModule) OnRecvPacket( ctx sdk.Context, packet channeltypes.Packet, + relayer sdk.AccAddress, ) ibcexported.Acknowledgement { ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) @@ -360,6 +361,7 @@ func (am AppModule) OnAcknowledgementPacket( ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, + relayer sdk.AccAddress, ) (*sdk.Result, error) { var ack channeltypes.Acknowledgement if err := types.ModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil { @@ -411,6 +413,7 @@ func (am AppModule) OnAcknowledgementPacket( func (am AppModule) OnTimeoutPacket( ctx sdk.Context, packet channeltypes.Packet, + relayer sdk.AccAddress, ) (*sdk.Result, error) { var data types.FungibleTokenPacketData if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { diff --git a/modules/core/05-port/types/module.go b/modules/core/05-port/types/module.go index 10a756bbe03..4a1c2596b81 100644 --- a/modules/core/05-port/types/module.go +++ b/modules/core/05-port/types/module.go @@ -67,16 +67,19 @@ type IBCModule interface { OnRecvPacket( ctx sdk.Context, packet channeltypes.Packet, + relayer sdk.AccAddress, ) exported.Acknowledgement OnAcknowledgementPacket( ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, + relayer sdk.AccAddress, ) (*sdk.Result, error) OnTimeoutPacket( ctx sdk.Context, packet channeltypes.Packet, + relayer sdk.AccAddress, ) (*sdk.Result, error) } diff --git a/modules/core/keeper/msg_server.go b/modules/core/keeper/msg_server.go index 2edcdd157c2..e1f2081046a 100644 --- a/modules/core/keeper/msg_server.go +++ b/modules/core/keeper/msg_server.go @@ -424,6 +424,11 @@ func (k Keeper) ChannelCloseConfirm(goCtx context.Context, msg *channeltypes.Msg func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + relayer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer") + } + // Lookup module by channel capability module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.DestinationPort, msg.Packet.DestinationChannel) if err != nil { @@ -444,7 +449,7 @@ func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacke // Perform application logic callback // Cache context so that we may discard state changes from callback if the acknowledgement is unsuccessful. cacheCtx, writeFn := ctx.CacheContext() - ack := cbs.OnRecvPacket(cacheCtx, msg.Packet) + ack := cbs.OnRecvPacket(cacheCtx, msg.Packet, relayer) if ack == nil || ack.Success() { // write application state changes for asynchronous and successful acknowledgements writeFn() @@ -478,6 +483,12 @@ func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacke // Timeout defines a rpc handler method for MsgTimeout. func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*channeltypes.MsgTimeoutResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + + relayer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer") + } + // Lookup module by channel capability module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) if err != nil { @@ -496,7 +507,7 @@ func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*c } // Perform application logic callback - _, err = cbs.OnTimeoutPacket(ctx, msg.Packet) + _, err = cbs.OnTimeoutPacket(ctx, msg.Packet, relayer) if err != nil { return nil, sdkerrors.Wrap(err, "timeout packet callback failed") } @@ -527,6 +538,11 @@ func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*c func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeoutOnClose) (*channeltypes.MsgTimeoutOnCloseResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + relayer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer") + } + // Lookup module by channel capability module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) if err != nil { @@ -547,7 +563,7 @@ func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeo // Perform application logic callback // NOTE: MsgTimeout and MsgTimeoutOnClose use the same "OnTimeoutPacket" // application logic callback. - _, err = cbs.OnTimeoutPacket(ctx, msg.Packet) + _, err = cbs.OnTimeoutPacket(ctx, msg.Packet, relayer) if err != nil { return nil, sdkerrors.Wrap(err, "timeout packet callback failed") } @@ -578,6 +594,11 @@ func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeo func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAcknowledgement) (*channeltypes.MsgAcknowledgementResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) + relayer, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, sdkerrors.Wrap(err, "Invalid address for msg Signer") + } + // Lookup module by channel capability module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) if err != nil { @@ -596,7 +617,7 @@ func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAckn } // Perform application logic callback - _, err = cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement) + _, err = cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement, relayer) if err != nil { return nil, sdkerrors.Wrap(err, "acknowledge packet callback failed") } diff --git a/testing/mock/mock.go b/testing/mock/mock.go index d6673d6d372..e2062dda51a 100644 --- a/testing/mock/mock.go +++ b/testing/mock/mock.go @@ -17,6 +17,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types" host "github.com/cosmos/ibc-go/modules/core/24-host" "github.com/cosmos/ibc-go/modules/core/exported" ) @@ -34,6 +35,8 @@ var ( MockCanaryCapabilityName = "mock canary capability name" ) +var _ porttypes.IBCModule = AppModule{} + // Expected Interface // PortKeeper defines the expected IBC port keeper type PortKeeper interface { @@ -189,7 +192,7 @@ func (am AppModule) OnChanCloseConfirm(sdk.Context, string, string) error { } // OnRecvPacket implements the IBCModule interface. -func (am AppModule) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet) exported.Acknowledgement { +func (am AppModule) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) exported.Acknowledgement { // set state by claiming capability to check if revert happens return am.scopedKeeper.NewCapability(ctx, MockCanaryCapabilityName) if bytes.Equal(MockPacketData, packet.GetData()) { @@ -202,11 +205,11 @@ func (am AppModule) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet) ex } // OnAcknowledgementPacket implements the IBCModule interface. -func (am AppModule) OnAcknowledgementPacket(sdk.Context, channeltypes.Packet, []byte) (*sdk.Result, error) { +func (am AppModule) OnAcknowledgementPacket(sdk.Context, channeltypes.Packet, []byte, sdk.AccAddress) (*sdk.Result, error) { return nil, nil } // OnTimeoutPacket implements the IBCModule interface. -func (am AppModule) OnTimeoutPacket(sdk.Context, channeltypes.Packet) (*sdk.Result, error) { +func (am AppModule) OnTimeoutPacket(sdk.Context, channeltypes.Packet, sdk.AccAddress) (*sdk.Result, error) { return nil, nil }