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: make transfer module v2 use same core paths as v1 #7754

Open
wants to merge 4 commits into
base: feat/ibc-eureka
Choose a base branch
from
Open
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
46 changes: 41 additions & 5 deletions modules/apps/transfer/ibc_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/events"
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/telemetry"
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/keeper"
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/types"
channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types"
Expand Down Expand Up @@ -172,12 +173,11 @@ func (im IBCModule) OnRecvPacket(
relayer sdk.AccAddress,
) ibcexported.Acknowledgement {
var (
ack ibcexported.Acknowledgement
ackErr error
data types.FungibleTokenPacketDataV2
)

ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)})

// we are explicitly wrapping this emit event call in an anonymous function so that
// the packet data is evaluated after it has been assigned a value.
defer func() {
Expand All @@ -191,12 +191,36 @@ func (im IBCModule) OnRecvPacket(
return ack
}

if ackErr = im.keeper.OnRecvPacket(ctx, packet, data); ackErr != nil {
receivedCoins, ackErr := im.keeper.OnRecvPacket(
ctx,
data,
packet.SourcePort,
packet.SourceChannel,
packet.DestinationPort,
packet.DestinationChannel,
)
if ackErr != nil {
ack = channeltypes.NewErrorAcknowledgement(ackErr)
im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), packet.Sequence))
return ack
}

if data.HasForwarding() {
// we are now sending from the forward escrow address to the final receiver address.
if ackErr = im.keeper.ForwardPacket(ctx, data, packet, receivedCoins); ackErr != nil {
ack = channeltypes.NewErrorAcknowledgement(ackErr)
im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), packet.Sequence))
return ack

}

ack = nil
}

ack = channeltypes.NewResultAcknowledgement([]byte{byte(1)})

telemetry.ReportOnRecvPacket(packet, data.Tokens)

im.keeper.Logger(ctx).Info("successfully handled ICS-20 packet", "sequence", packet.Sequence)

if data.HasForwarding() {
Expand Down Expand Up @@ -226,10 +250,16 @@ func (im IBCModule) OnAcknowledgementPacket(
return err
}

if err := im.keeper.OnAcknowledgementPacket(ctx, packet, data, ack); err != nil {
if err := im.keeper.OnAcknowledgementPacket(ctx, packet.SourcePort, packet.SourceChannel, data, ack); err != nil {
return err
}

if forwardedPacket, isForwarded := im.keeper.GetForwardedPacket(ctx, packet.SourcePort, packet.SourceChannel, packet.Sequence); isForwarded {
if err := im.keeper.HandleForwardedPacketAcknowledgement(ctx, packet, forwardedPacket, data, ack); err != nil {
return err
}
}

events.EmitOnAcknowledgementPacketEvent(ctx, data, ack)

return nil
Expand All @@ -248,10 +278,16 @@ func (im IBCModule) OnTimeoutPacket(
}

// refund tokens
if err := im.keeper.OnTimeoutPacket(ctx, packet, data); err != nil {
if err := im.keeper.OnTimeoutPacket(ctx, packet.SourcePort, packet.SourceChannel, data); err != nil {
return err
}

if forwardedPacket, isForwarded := im.keeper.GetForwardedPacket(ctx, packet.SourcePort, packet.SourceChannel, packet.Sequence); isForwarded {
if err := im.keeper.HandleForwardedPacketTimeout(ctx, packet, forwardedPacket, data); err != nil {
return err
}
}

events.EmitOnTimeoutEvent(ctx, data)
return nil
}
Expand Down
3 changes: 2 additions & 1 deletion modules/apps/transfer/internal/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/cosmos/ibc-go/v9/modules/apps/transfer/types"
channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types"
ibcexported "github.com/cosmos/ibc-go/v9/modules/core/exported"
)

// EmitTransferEvent emits a ibc transfer event on successful transfers.
Expand All @@ -34,7 +35,7 @@ func EmitTransferEvent(ctx context.Context, sender, receiver string, tokens type
}

// EmitOnRecvPacketEvent emits a fungible token packet event in the OnRecvPacket callback
func EmitOnRecvPacketEvent(ctx context.Context, packetData types.FungibleTokenPacketDataV2, ack channeltypes.Acknowledgement, ackErr error) {
func EmitOnRecvPacketEvent(ctx context.Context, packetData types.FungibleTokenPacketDataV2, ack ibcexported.Acknowledgement, ackErr error) {
tokensStr := mustMarshalJSON(packetData.Tokens)
forwardingHopStr := mustMarshalJSON(packetData.Forwarding.Hops)

Expand Down
5 changes: 0 additions & 5 deletions modules/apps/transfer/keeper/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ func (k Keeper) UnwindHops(ctx sdk.Context, msg *types.MsgTransfer) (*types.MsgT
return k.unwindHops(ctx, msg)
}

// GetForwardedPacket is a wrapper around getForwardedPacket for testing purposes.
func (k Keeper) GetForwardedPacket(ctx sdk.Context, portID, channelID string, sequence uint64) (channeltypes.Packet, bool) {
return k.getForwardedPacket(ctx, portID, channelID, sequence)
}

// SetForwardedPacket is a wrapper around setForwardedPacket for testing purposes.
func (k Keeper) SetForwardedPacket(ctx sdk.Context, portID, channelID string, sequence uint64, packet channeltypes.Packet) {
k.setForwardedPacket(ctx, portID, channelID, sequence, packet)
Expand Down
4 changes: 2 additions & 2 deletions modules/apps/transfer/keeper/forwarding.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors"
)

// forwardPacket forwards a fungible FungibleTokenPacketDataV2 to the next hop in the forwarding path.
func (k Keeper) forwardPacket(ctx context.Context, data types.FungibleTokenPacketDataV2, packet channeltypes.Packet, receivedCoins sdk.Coins) error {
// ForwardPacket forwards a fungible FungibleTokenPacketDataV2 to the next hop in the forwarding path.
func (k Keeper) ForwardPacket(ctx context.Context, data types.FungibleTokenPacketDataV2, packet channeltypes.Packet, receivedCoins sdk.Coins) error {
var nextForwardingPath *types.Forwarding
if len(data.Forwarding.Hops) > 1 {
// remove the first hop since we are going to send to the first hop now and we want to propagate the rest of the hops to the receiver
Expand Down
20 changes: 10 additions & 10 deletions modules/apps/transfer/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,17 +299,8 @@ func (k Keeper) IterateTokensInEscrow(ctx context.Context, storeprefix []byte, c
}
}

// setForwardedPacket sets the forwarded packet in the store.
func (k Keeper) setForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64, packet channeltypes.Packet) {
store := k.storeService.OpenKVStore(ctx)
bz := k.cdc.MustMarshal(&packet)
if err := store.Set(types.PacketForwardKey(portID, channelID, sequence), bz); err != nil {
panic(err)
}
}

// getForwardedPacket gets the forwarded packet from the store.
func (k Keeper) getForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64) (channeltypes.Packet, bool) {
func (k Keeper) GetForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64) (channeltypes.Packet, bool) {
store := k.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.PacketForwardKey(portID, channelID, sequence))
if err != nil {
Expand All @@ -325,6 +316,15 @@ func (k Keeper) getForwardedPacket(ctx context.Context, portID, channelID string
return storedPacket, true
}

// setForwardedPacket sets the forwarded packet in the store.
func (k Keeper) setForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64, packet channeltypes.Packet) {
store := k.storeService.OpenKVStore(ctx)
bz := k.cdc.MustMarshal(&packet)
if err := store.Set(types.PacketForwardKey(portID, channelID, sequence), bz); err != nil {
panic(err)
}
}

// deleteForwardedPacket deletes the forwarded packet from the store.
func (k Keeper) deleteForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64) {
store := k.storeService.OpenKVStore(ctx)
Expand Down
15 changes: 11 additions & 4 deletions modules/apps/transfer/keeper/mbt_relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,20 +365,27 @@ func (suite *KeeperTestSuite) TestModelBasedRelay() {

}
case "OnRecvPacket":
err = suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket(suite.chainB.GetContext(), packet, tc.packet.Data)
_, err = suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket(
suite.chainB.GetContext(),
tc.packet.Data,
packet.SourcePort,
packet.SourceChannel,
packet.DestinationPort,
packet.DestinationChannel,
)

case "OnTimeoutPacket":
registerDenomFn()
err = suite.chainB.GetSimApp().TransferKeeper.OnTimeoutPacket(suite.chainB.GetContext(), packet, tc.packet.Data)
err = suite.chainB.GetSimApp().TransferKeeper.OnTimeoutPacket(suite.chainB.GetContext(), packet.SourcePort, packet.SourceChannel, tc.packet.Data)

case "OnRecvAcknowledgementResult":
err = suite.chainB.GetSimApp().TransferKeeper.OnAcknowledgementPacket(
suite.chainB.GetContext(), packet, tc.packet.Data,
suite.chainB.GetContext(), packet.SourcePort, packet.SourceChannel, tc.packet.Data,
channeltypes.NewResultAcknowledgement(nil))
case "OnRecvAcknowledgementError":
registerDenomFn()
err = suite.chainB.GetSimApp().TransferKeeper.OnAcknowledgementPacket(
suite.chainB.GetContext(), packet, tc.packet.Data,
suite.chainB.GetContext(), packet.SourcePort, packet.SourceChannel, tc.packet.Data,
channeltypes.NewErrorAcknowledgement(fmt.Errorf("MBT Error Acknowledgement")))
default:
err = fmt.Errorf("Unknown handler: %s", tc.handler)
Expand Down
65 changes: 51 additions & 14 deletions modules/apps/transfer/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/events"
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/telemetry"
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/types"
channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types"
ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors"
)

Expand All @@ -18,39 +21,73 @@ var _ types.MsgServer = (*Keeper)(nil)
func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

if !k.GetParams(ctx).SendEnabled {
return nil, types.ErrSendDisabled
}

sender, err := sdk.AccAddressFromBech32(msg.Sender)
if err != nil {
return nil, err
}

coins := msg.GetCoins()
if msg.Forwarding.GetUnwind() {
msg, err = k.unwindHops(ctx, msg)
if err != nil {
return nil, err
}
}

if err := k.BankKeeper.IsSendEnabledCoins(ctx, coins...); err != nil {
return nil, errorsmod.Wrap(types.ErrSendDisabled, err.Error())
channel, found := k.channelKeeper.GetChannel(ctx, msg.SourcePort, msg.SourceChannel)
if !found {
return nil, errorsmod.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", msg.SourcePort, msg.SourceChannel)
}

if k.IsBlockedAddr(sender) {
return nil, errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "%s is not allowed to send funds", sender)
appVersion, found := k.ics4Wrapper.GetAppVersion(ctx, msg.SourcePort, msg.SourceChannel)
if !found {
return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "application version not found for source port: %s and source channel: %s", msg.SourcePort, msg.SourceChannel)
}

if msg.Forwarding.GetUnwind() {
msg, err = k.unwindHops(ctx, msg)
coins := msg.GetCoins()
hops := msg.Forwarding.GetHops()
if appVersion == types.V1 {
// ics20-1 only supports a single coin, so if that is the current version, we must only process a single coin.
if len(coins) > 1 {
return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "cannot transfer multiple coins with %s", types.V1)
}

// ics20-1 does not support forwarding, so if that is the current version, we must reject the transfer.
if len(hops) > 0 {
return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "cannot forward coins with %s", types.V1)
}
}

tokens := make([]types.Token, len(coins))

for i, coin := range coins {
tokens[i], err = k.tokenFromCoin(ctx, coin)
if err != nil {
return nil, err
}
}

sequence, err := k.sendTransfer(
ctx, msg.SourcePort, msg.SourceChannel, coins, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp,
msg.Memo, msg.Forwarding.GetHops())
if err := k.SendTransfer(ctx, tokens, sender, msg.SourcePort, msg.SourceChannel); err != nil {
return nil, err
}

packetDataBytes, err := createPacketDataBytesFromVersion(
appVersion, sender.String(), msg.Receiver, msg.Memo, tokens, hops,
)
if err != nil {
return nil, err
}

sequence, err := k.ics4Wrapper.SendPacket(ctx, msg.SourcePort, msg.SourceChannel, msg.TimeoutHeight, msg.TimeoutTimestamp, packetDataBytes)
if err != nil {
return nil, err
}

events.EmitTransferEvent(ctx, sender.String(), msg.Receiver, tokens, msg.Memo, hops)

destinationPort := channel.Counterparty.PortId
destinationChannel := channel.Counterparty.ChannelId
telemetry.ReportTransfer(msg.SourcePort, msg.SourceChannel, destinationPort, destinationChannel, tokens)

k.Logger(ctx).Info("IBC fungible token transfer", "tokens", coins, "sender", msg.Sender, "receiver", msg.Receiver)

return &types.MsgTransferResponse{Sequence: sequence}, nil
Expand Down
Loading
Loading