Skip to content

Commit ddce441

Browse files
refactor: make transfer module v2 use same core paths as v1 (#7754)
* reuse transfer keeper in v2 * remove keeper from transfer module v2 * moved some comments around and disabled forwarding * code review fixes * Update modules/apps/transfer/keeper/relay_test.go --------- Co-authored-by: Aditya <[email protected]>
1 parent 379e3d2 commit ddce441

17 files changed

+327
-1324
lines changed

modules/apps/transfer/ibc_module.go

+41-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

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

14+
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/telemetry"
1415
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/keeper"
1516
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/types"
1617
channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types"
@@ -171,12 +172,11 @@ func (im IBCModule) OnRecvPacket(
171172
relayer sdk.AccAddress,
172173
) ibcexported.Acknowledgement {
173174
var (
175+
ack ibcexported.Acknowledgement
174176
ackErr error
175177
data types.FungibleTokenPacketDataV2
176178
)
177179

178-
ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)})
179-
180180
// we are explicitly wrapping this emit event call in an anonymous function so that
181181
// the packet data is evaluated after it has been assigned a value.
182182
defer func() {
@@ -192,12 +192,36 @@ func (im IBCModule) OnRecvPacket(
192192
return ack
193193
}
194194

195-
if ackErr = im.keeper.OnRecvPacket(ctx, packet, data); ackErr != nil {
195+
receivedCoins, ackErr := im.keeper.OnRecvPacket(
196+
ctx,
197+
data,
198+
packet.SourcePort,
199+
packet.SourceChannel,
200+
packet.DestinationPort,
201+
packet.DestinationChannel,
202+
)
203+
if ackErr != nil {
196204
ack = channeltypes.NewErrorAcknowledgement(ackErr)
197205
im.keeper.Logger.Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), packet.Sequence))
198206
return ack
199207
}
200208

209+
if data.HasForwarding() {
210+
// we are now sending from the forward escrow address to the final receiver address.
211+
if ackErr = im.keeper.ForwardPacket(ctx, data, packet, receivedCoins); ackErr != nil {
212+
ack = channeltypes.NewErrorAcknowledgement(ackErr)
213+
im.keeper.Logger.Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), packet.Sequence))
214+
return ack
215+
216+
}
217+
218+
ack = nil
219+
}
220+
221+
ack = channeltypes.NewResultAcknowledgement([]byte{byte(1)})
222+
223+
telemetry.ReportOnRecvPacket(packet, data.Tokens)
224+
201225
im.keeper.Logger.Info("successfully handled ICS-20 packet", "sequence", packet.Sequence)
202226

203227
if data.HasForwarding() {
@@ -227,10 +251,16 @@ func (im IBCModule) OnAcknowledgementPacket(
227251
return err
228252
}
229253

230-
if err := im.keeper.OnAcknowledgementPacket(ctx, packet, data, ack); err != nil {
254+
if err := im.keeper.OnAcknowledgementPacket(ctx, packet.SourcePort, packet.SourceChannel, data, ack); err != nil {
231255
return err
232256
}
233257

258+
if forwardedPacket, isForwarded := im.keeper.GetForwardedPacket(ctx, packet.SourcePort, packet.SourceChannel, packet.Sequence); isForwarded {
259+
if err := im.keeper.HandleForwardedPacketAcknowledgement(ctx, packet, forwardedPacket, data, ack); err != nil {
260+
return err
261+
}
262+
}
263+
234264
return im.keeper.EmitOnAcknowledgementPacketEvent(ctx, data, ack)
235265
}
236266

@@ -247,10 +277,16 @@ func (im IBCModule) OnTimeoutPacket(
247277
}
248278

249279
// refund tokens
250-
if err := im.keeper.OnTimeoutPacket(ctx, packet, data); err != nil {
280+
if err := im.keeper.OnTimeoutPacket(ctx, packet.SourcePort, packet.SourceChannel, data); err != nil {
251281
return err
252282
}
253283

284+
if forwardedPacket, isForwarded := im.keeper.GetForwardedPacket(ctx, packet.SourcePort, packet.SourceChannel, packet.Sequence); isForwarded {
285+
if err := im.keeper.HandleForwardedPacketTimeout(ctx, packet, forwardedPacket, data); err != nil {
286+
return err
287+
}
288+
}
289+
254290
return im.keeper.EmitOnTimeoutEvent(ctx, data)
255291
}
256292

modules/apps/transfer/keeper/events.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/types"
1313
channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types"
14+
ibcexported "github.com/cosmos/ibc-go/v9/modules/core/exported"
1415
)
1516

1617
// EmitTransferEvent emits an ibc transfer event on successful transfers.
@@ -36,7 +37,7 @@ func (k Keeper) EmitTransferEvent(ctx context.Context, sender, receiver string,
3637
}
3738

3839
// EmitOnRecvPacketEvent emits a fungible token packet event in the OnRecvPacket callback
39-
func (k Keeper) EmitOnRecvPacketEvent(ctx context.Context, packetData types.FungibleTokenPacketDataV2, ack channeltypes.Acknowledgement, ackErr error) error {
40+
func (k Keeper) EmitOnRecvPacketEvent(ctx context.Context, packetData types.FungibleTokenPacketDataV2, ack ibcexported.Acknowledgement, ackErr error) error {
4041
tokensStr := mustMarshalJSON(packetData.Tokens)
4142
forwardingHopStr := mustMarshalJSON(packetData.Forwarding.Hops)
4243

modules/apps/transfer/keeper/export_test.go

-5
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,6 @@ func (k Keeper) UnwindHops(ctx sdk.Context, msg *types.MsgTransfer) (*types.MsgT
3939
return k.unwindHops(ctx, msg)
4040
}
4141

42-
// GetForwardedPacket is a wrapper around getForwardedPacket for testing purposes.
43-
func (k Keeper) GetForwardedPacket(ctx sdk.Context, portID, channelID string, sequence uint64) (channeltypes.Packet, bool) {
44-
return k.getForwardedPacket(ctx, portID, channelID, sequence)
45-
}
46-
4742
// SetForwardedPacket is a wrapper around setForwardedPacket for testing purposes.
4843
func (k Keeper) SetForwardedPacket(ctx sdk.Context, portID, channelID string, sequence uint64, packet channeltypes.Packet) {
4944
k.setForwardedPacket(ctx, portID, channelID, sequence, packet)

modules/apps/transfer/keeper/forwarding.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import (
1313
ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors"
1414
)
1515

16-
// forwardPacket forwards a fungible FungibleTokenPacketDataV2 to the next hop in the forwarding path.
17-
func (k Keeper) forwardPacket(ctx context.Context, data types.FungibleTokenPacketDataV2, packet channeltypes.Packet, receivedCoins sdk.Coins) error {
16+
// ForwardPacket forwards a fungible FungibleTokenPacketDataV2 to the next hop in the forwarding path.
17+
func (k Keeper) ForwardPacket(ctx context.Context, data types.FungibleTokenPacketDataV2, packet channeltypes.Packet, receivedCoins sdk.Coins) error {
1818
var nextForwardingPath *types.Forwarding
1919
if len(data.Forwarding.Hops) > 1 {
2020
// 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

modules/apps/transfer/keeper/keeper.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ func (k Keeper) setForwardedPacket(ctx context.Context, portID, channelID string
308308
}
309309

310310
// getForwardedPacket gets the forwarded packet from the store.
311-
func (k Keeper) getForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64) (channeltypes.Packet, bool) {
311+
func (k Keeper) GetForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64) (channeltypes.Packet, bool) {
312312
store := k.KVStoreService.OpenKVStore(ctx)
313313
bz, err := store.Get(types.PacketForwardKey(portID, channelID, sequence))
314314
if err != nil {

modules/apps/transfer/keeper/mbt_relay_test.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -365,20 +365,27 @@ func (suite *KeeperTestSuite) TestModelBasedRelay() {
365365

366366
}
367367
case "OnRecvPacket":
368-
err = suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket(suite.chainB.GetContext(), packet, tc.packet.Data)
368+
_, err = suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket(
369+
suite.chainB.GetContext(),
370+
tc.packet.Data,
371+
packet.SourcePort,
372+
packet.SourceChannel,
373+
packet.DestinationPort,
374+
packet.DestinationChannel,
375+
)
369376

370377
case "OnTimeoutPacket":
371378
registerDenomFn()
372-
err = suite.chainB.GetSimApp().TransferKeeper.OnTimeoutPacket(suite.chainB.GetContext(), packet, tc.packet.Data)
379+
err = suite.chainB.GetSimApp().TransferKeeper.OnTimeoutPacket(suite.chainB.GetContext(), packet.SourcePort, packet.SourceChannel, tc.packet.Data)
373380

374381
case "OnRecvAcknowledgementResult":
375382
err = suite.chainB.GetSimApp().TransferKeeper.OnAcknowledgementPacket(
376-
suite.chainB.GetContext(), packet, tc.packet.Data,
383+
suite.chainB.GetContext(), packet.SourcePort, packet.SourceChannel, tc.packet.Data,
377384
channeltypes.NewResultAcknowledgement(nil))
378385
case "OnRecvAcknowledgementError":
379386
registerDenomFn()
380387
err = suite.chainB.GetSimApp().TransferKeeper.OnAcknowledgementPacket(
381-
suite.chainB.GetContext(), packet, tc.packet.Data,
388+
suite.chainB.GetContext(), packet.SourcePort, packet.SourceChannel, tc.packet.Data,
382389
channeltypes.NewErrorAcknowledgement(fmt.Errorf("MBT Error Acknowledgement")))
383390
default:
384391
err = fmt.Errorf("Unknown handler: %s", tc.handler)

modules/apps/transfer/keeper/msg_server.go

+52-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import (
88

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

11+
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/telemetry"
1112
"github.com/cosmos/ibc-go/v9/modules/apps/transfer/types"
13+
channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types"
1214
ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors"
1315
)
1416

@@ -25,30 +27,70 @@ func (k Keeper) Transfer(ctx context.Context, msg *types.MsgTransfer) (*types.Ms
2527
return nil, err
2628
}
2729

28-
coins := msg.GetCoins()
30+
if msg.Forwarding.GetUnwind() {
31+
msg, err = k.unwindHops(ctx, msg)
32+
if err != nil {
33+
return nil, err
34+
}
35+
}
2936

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

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

38-
if msg.Forwarding.GetUnwind() {
39-
msg, err = k.unwindHops(ctx, msg)
47+
coins := msg.GetCoins()
48+
hops := msg.Forwarding.GetHops()
49+
if appVersion == types.V1 {
50+
// ics20-1 only supports a single coin, so if that is the current version, we must only process a single coin.
51+
if len(coins) > 1 {
52+
return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "cannot transfer multiple coins with %s", types.V1)
53+
}
54+
55+
// ics20-1 does not support forwarding, so if that is the current version, we must reject the transfer.
56+
if len(hops) > 0 {
57+
return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "cannot forward coins with %s", types.V1)
58+
}
59+
}
60+
61+
tokens := make([]types.Token, len(coins))
62+
63+
for i, coin := range coins {
64+
tokens[i], err = k.tokenFromCoin(ctx, coin)
4065
if err != nil {
4166
return nil, err
4267
}
4368
}
4469

45-
sequence, err := k.sendTransfer(
46-
ctx, msg.SourcePort, msg.SourceChannel, coins, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp,
47-
msg.Memo, msg.Forwarding.GetHops())
70+
if err := k.SendTransfer(ctx, msg.SourcePort, msg.SourceChannel, tokens, sender); err != nil {
71+
return nil, err
72+
}
73+
74+
packetDataBytes, err := createPacketDataBytesFromVersion(
75+
appVersion, sender.String(), msg.Receiver, msg.Memo, tokens, hops,
76+
)
4877
if err != nil {
4978
return nil, err
5079
}
5180

81+
sequence, err := k.ics4Wrapper.SendPacket(ctx, msg.SourcePort, msg.SourceChannel, msg.TimeoutHeight, msg.TimeoutTimestamp, packetDataBytes)
82+
if err != nil {
83+
return nil, err
84+
}
85+
86+
if err := k.EmitTransferEvent(ctx, sender.String(), msg.Receiver, tokens, msg.Memo, hops); err != nil {
87+
return nil, err
88+
}
89+
90+
destinationPort := channel.Counterparty.PortId
91+
destinationChannel := channel.Counterparty.ChannelId
92+
telemetry.ReportTransfer(msg.SourcePort, msg.SourceChannel, destinationPort, destinationChannel, tokens)
93+
5294
k.Logger.Info("IBC fungible token transfer", "tokens", coins, "sender", msg.Sender, "receiver", msg.Receiver)
5395

5496
return &types.MsgTransferResponse{Sequence: sequence}, nil

0 commit comments

Comments
 (0)