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: ibc port router for app callbacks #6314

Draft
wants to merge 51 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
845e45f
feat: add intial SendPacket msgs and rpc definition to ibc core
damiannolan May 15, 2024
db5cddf
feat: add OnSendPacket callback to IBCModule interface
damiannolan May 15, 2024
385674a
chore: invoke OnSendPacket callback from msg server rpc
damiannolan May 15, 2024
5c861f4
chore: add comment
damiannolan May 15, 2024
9d4d2ea
chore: rename proto fields
damiannolan May 15, 2024
90fe8ae
chore: add OnSendPacket to ibccallbacks
damiannolan May 15, 2024
fc309f6
feat: add router_v2 while leaving current router impl in place
damiannolan May 15, 2024
d0f85db
chore: add getter and setters for AppRouter to core ibc
damiannolan May 15, 2024
588ff66
imp: implement callbacks OnSendPacket
colin-axner May 15, 2024
8bc82f6
imp: implement OnSendPacket for ics27
colin-axner May 16, 2024
f883d68
imp: implement OnSendPacket in transfer
damiannolan May 16, 2024
c5eef93
Merge branch 'main' into feat/port-router
damiannolan May 16, 2024
e626c7b
chore: start wiring up router_v2 in app.go
damiannolan May 16, 2024
45896aa
imp: add msg server handler to transfer
colin-axner May 16, 2024
20326d4
Merge branch 'feat/port-router' of github.com:cosmos/ibc-go into feat…
colin-axner May 16, 2024
3714960
refactor: enable core IBC SendPacket API and switch transfer to redir…
colin-axner May 16, 2024
b2df2f3
refactor: rewire controller to use SendPacket API
colin-axner May 16, 2024
b295949
refactor: rewire 29-fee to use SendPacket API
colin-axner May 16, 2024
2f5116e
refactor: use SendPacket API for callbacks
colin-axner May 16, 2024
16a88b4
imp: remove capability from SendPacket and add prefix routing
damiannolan May 16, 2024
67e4b5f
refactor: adapt signer to sdk.AccAddress
damiannolan May 16, 2024
3db1613
chore: rm capabilities from recv, ack, timeout packet handler
damiannolan May 16, 2024
07e8b1c
lint: make lint-fix and address
damiannolan May 16, 2024
4214201
refactor: rm SendPacket from ics4wrapper
damiannolan May 16, 2024
9610871
chore: rm callbacks var in SendPacket handler
damiannolan May 16, 2024
ef6e063
Merge branch 'main' into feat/port-router
damiannolan May 22, 2024
cf339f2
fix: rm capability arg in ibc ante handler
damiannolan May 22, 2024
4f8d319
Merge branch 'main' into feat/port-router
damiannolan Jul 11, 2024
a4a7bdd
(chore): remove capabilities from channel handsake (#7009)
bznein Aug 5, 2024
832a0fc
Adding updates to composite router and scaffolding for LegacyIBCModul…
chatton Aug 5, 2024
d701aa2
Rename IBCModule to ClassicIBCModule (#7015)
chatton Aug 5, 2024
9565e36
Merge branch 'main' of github.com:cosmos/ibc-go into feat/port-router
colin-axner Aug 6, 2024
3eaf2ce
fix: tests
colin-axner Aug 6, 2024
41c6656
Add Wrap/Unwrap Interfaces and implement OnChanOpenInit (#7059)
chatton Aug 7, 2024
9460400
Use new port router for onchanupgradetry (#7067)
chatton Aug 7, 2024
6ec1efa
Use new port router for OnChanOpenAck (#7084)
colin-axner Aug 7, 2024
dc6e072
Use new port router for OnChanUpgradeInit (#7082)
chatton Aug 8, 2024
ae43f7a
refactor: implement OnChanOpenConfirm using new port router (#7088)
colin-axner Aug 8, 2024
63dd289
chore: implement OnChanUpgradeTry (#7092)
chatton Aug 8, 2024
0c47e45
chore(api)!: move checks from Transfer to OnSendPacket (#7068)
bznein Aug 8, 2024
467819d
refactor: implement OnChanCloseInit using new port router. (#7095)
bznein Aug 8, 2024
d779697
Use new port router for OnChanUpgradeAck (#7094)
chatton Aug 8, 2024
179025d
refactor: implement onchancloseconfirm using new port router (#7096)
bznein Aug 8, 2024
62db721
Use new port router for OnChanUpgradeOpen (#7102)
chatton Aug 8, 2024
48b6a3f
refactor: replace ack interface with result type for OnRecvPacket (#7…
damiannolan Aug 8, 2024
d9c4e96
imp (api)!: convert coins to token only once in MsgTransfer (#7110)
bznein Aug 8, 2024
0ea612a
use new port router with OnAcknowledgementPacket (#7108)
colin-axner Aug 8, 2024
a9d34ba
chore: docs (#7111)
colin-axner Aug 12, 2024
ec593cb
Bznein/7023/on timeout packet (#7144)
bznein Aug 13, 2024
f5ab15b
Add convenience func to reverse callbacks and refactor other methods …
chatton Aug 13, 2024
6327b58
chore: use app router in OnTimeoutPacket handler (#7164)
chatton Aug 14, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,56 @@ func (im IBCMiddleware) OnChanCloseConfirm(
return nil
}

// OnSendPacket implements the IBCModule interface.
func (im IBCMiddleware) OnSendPacket(
ctx sdk.Context,
portID string,
channelID string,
sequence uint64,
timeoutHeight clienttypes.Height,
timeoutTimestamp uint64,
data []byte,
signer string,
) error {
if !im.keeper.GetParams(ctx).ControllerEnabled {
return types.ErrControllerSubModuleDisabled
}

controllerPortID, err := icatypes.NewControllerPortID(signer)
if err != nil {
return err
}

if controllerPortID != portID {
return errorsmod.Wrap(ibcerrors.ErrUnauthorized, "signer is not owner of interchain account channel")
}

connectionID, err := im.keeper.GetConnectionID(ctx, portID, channelID)
if err != nil {
return err
}

activeChannelID, found := im.keeper.GetOpenActiveChannel(ctx, connectionID, portID)
if !found {
return errorsmod.Wrapf(icatypes.ErrActiveChannelNotFound, "failed to retrieve active channel on connection %s for port %s", connectionID, portID)
}

if activeChannelID != channelID {
return errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "active channel ID does not match provided channelID. expected %s, got %s", activeChannelID, channelID)
}

var icaPacketData icatypes.InterchainAccountPacketData
if err := icaPacketData.UnmarshalJSON(data); err != nil {
return err
}

if err := icaPacketData.ValidateBasic(); err != nil {
return errorsmod.Wrap(err, "invalid interchain account packet data")
}

return nil
}

// OnRecvPacket implements the IBCMiddleware interface
func (IBCMiddleware) OnRecvPacket(
ctx sdk.Context,
Expand Down
15 changes: 15 additions & 0 deletions modules/apps/27-interchain-accounts/host/ibc_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/keeper"
"github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/types"
icatypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/types"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types"
ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors"
Expand Down Expand Up @@ -110,6 +111,20 @@ func (im IBCModule) OnChanCloseConfirm(
return im.keeper.OnChanCloseConfirm(ctx, portID, channelID)
}

// OnSendPacket implements the IBCModule interface.
func (IBCModule) OnSendPacket(
ctx sdk.Context,
portID string,
channelID string,
sequence uint64,
timeoutHeight clienttypes.Height,
timeoutTimestamp uint64,
data []byte,
signer string,
) error {
return errorsmod.Wrap(ibcerrors.ErrInvalidRequest, "cannot send packet on icahost")
}

// OnRecvPacket implements the IBCModule interface
func (im IBCModule) OnRecvPacket(
ctx sdk.Context,
Expand Down
14 changes: 14 additions & 0 deletions modules/apps/29-fee/ibc_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,20 @@ func (im IBCMiddleware) OnChanCloseConfirm(
return im.keeper.RefundFeesOnChannelClosure(ctx, portID, channelID)
}

// OnSendPacket implements the IBCModule interface.
func (IBCMiddleware) OnSendPacket(
ctx sdk.Context,
portID string,
channelID string,
sequence uint64,
timeoutHeight clienttypes.Height,
timeoutTimestamp uint64,
data []byte,
signer string,
) error {
return nil
}

// OnRecvPacket implements the IBCMiddleware interface.
// If fees are not enabled, this callback will default to the ibc-core packet callback
func (im IBCMiddleware) OnRecvPacket(
Expand Down
27 changes: 23 additions & 4 deletions modules/apps/callbacks/ibc_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,31 @@ func (im IBCMiddleware) SendPacket(
return 0, err
}

if err := im.OnSendPacket(ctx, sourcePort, sourceChannel, seq, timeoutHeight, timeoutTimestamp, data, ""); err != nil {
return 0, err
}

return seq, nil
}

// OnSendPacket implements the IBCModule interface.
func (im IBCMiddleware) OnSendPacket(
ctx sdk.Context,
sourcePort string,
sourceChannel string,
sequence uint64,
timeoutHeight clienttypes.Height,
timeoutTimestamp uint64,
data []byte,
signer string,
) error {
callbackData, err := types.GetSourceCallbackData(im.app, data, sourcePort, ctx.GasMeter().GasRemaining(), im.maxCallbackGas)
// SendPacket is not blocked if the packet does not opt-in to callbacks
if err != nil {
return seq, nil
return nil
}

// TODO: the packet sender is now passed in, it is possible to remove `GetPacketSender` in favour of this arg
Copy link
Contributor

Choose a reason for hiding this comment

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

we can remove the GetPacketSender interface now! Wahoo!

callbackExecutor := func(cachedCtx sdk.Context) error {
return im.contractKeeper.IBCSendPacketCallback(
cachedCtx, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data, callbackData.CallbackAddress, callbackData.SenderAddress,
Expand All @@ -114,11 +133,11 @@ func (im IBCMiddleware) SendPacket(
err = im.processCallback(ctx, types.CallbackTypeSendPacket, callbackData, callbackExecutor)
// contract keeper is allowed to reject the packet send.
if err != nil {
return 0, err
return err
}

types.EmitCallbackEvent(ctx, sourcePort, sourceChannel, seq, types.CallbackTypeSendPacket, callbackData, nil)
return seq, nil
types.EmitCallbackEvent(ctx, sourcePort, sourceChannel, sequence, types.CallbackTypeSendPacket, callbackData, nil)
return nil
}

// OnAcknowledgementPacket implements source callbacks for acknowledgement packets.
Expand Down
25 changes: 25 additions & 0 deletions modules/apps/transfer/ibc_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types"
"github.com/cosmos/ibc-go/v8/modules/apps/transfer/keeper"
"github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v8/modules/core/04-channel/types"
porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types"
host "github.com/cosmos/ibc-go/v8/modules/core/24-host"
Expand Down Expand Up @@ -172,6 +173,30 @@ func (IBCModule) OnChanCloseConfirm(
return nil
}

// OnSendPacket implements the IBCModule interface.
func (im IBCModule) OnSendPacket(
ctx sdk.Context,
portID string,
channelID string,
_ uint64,
_ clienttypes.Height,
_ uint64,
dataBz []byte,
signer string,
) error {
var data types.FungibleTokenPacketData
if err := json.Unmarshal(dataBz, &data); err != nil {
return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "cannot unmarshal ICS-20 transfer packet data")
}

sender, err := sdk.AccAddressFromBech32(signer)
if err != nil {
return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "cannot convert signer address to sdk.AccAddress")
}

return im.keeper.OnSendPacket(ctx, portID, channelID, data, sender)
}

// OnRecvPacket implements the IBCModule interface. A successful acknowledgement
// is returned if the packet data is successfully decoded and the receive application
// logic returns without error.
Expand Down
30 changes: 30 additions & 0 deletions modules/apps/transfer/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package keeper

import (
"context"
"strings"

errorsmod "cosmossdk.io/errors"

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

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

Expand All @@ -34,6 +36,34 @@ func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.
return nil, errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "%s is not allowed to send funds", sender)
}

// NOTE: denomination and hex hash correctness checked during msg.ValidateBasic
fullDenomPath := msg.Token.Denom

// deconstruct the token denomination into the denomination trace info
// to determine if the sender is the source chain
if strings.HasPrefix(msg.Token.Denom, "ibc/") {
fullDenomPath, err = k.DenomPathFromHash(ctx, msg.Token.Denom)
if err != nil {
return nil, err
}
}

packetData := types.NewFungibleTokenPacketData(
fullDenomPath, msg.Token.Amount.String(), sender.String(), msg.Receiver, msg.Memo,
)

msgSendPacket := channeltypes.MsgSendPacket{
PortId: msg.SourcePort,
ChannelId: msg.SourceChannel,
TimeoutHeight: msg.TimeoutHeight,
TimeoutTimestamp: msg.TimeoutTimestamp,
Data: packetData.GetBytes(),
Signer: sender.String(),
}

// TODO: route msgSendPacket to core which calls OnSendPacket
_ = msgSendPacket

sequence, err := k.sendTransfer(
ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp,
msg.Memo)
Expand Down
78 changes: 78 additions & 0 deletions modules/apps/transfer/keeper/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,84 @@ func (k Keeper) sendTransfer(
return sequence, nil
}

// OnSendPacket handles transfer sending logic.
// TODO: Copy godoc from above sendTransfer function.
func (k Keeper) OnSendPacket(ctx sdk.Context,
sourcePort string,
sourceChannel string,
packetData types.FungibleTokenPacketData,
sender sdk.AccAddress,
) error {
damiannolan marked this conversation as resolved.
Show resolved Hide resolved
channel, found := k.channelKeeper.GetChannel(ctx, sourcePort, sourceChannel)
if !found {
return errorsmod.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", sourcePort, sourceChannel)
}

// begin createOutgoingPacket logic
// See spec for this logic: https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#packet-relay
labels := []metrics.Label{
telemetry.NewLabel(coretypes.LabelDestinationPort, channel.Counterparty.PortId),
telemetry.NewLabel(coretypes.LabelDestinationChannel, channel.Counterparty.ChannelId),
}

amount, ok := sdkmath.NewIntFromString(packetData.Amount)
if !ok {
return errorsmod.Wrapf(types.ErrInvalidAmount, "cannot convert packet data amount to int: %s", packetData.Amount)
}

token := sdk.NewCoin(packetData.Denom, amount)

// NOTE: SendTransfer simply sends the denomination as it exists on its own
// chain inside the packet data. The receiving chain will perform denom
// prefixing as necessary.
if types.SenderChainIsSource(sourcePort, sourceChannel, packetData.Denom) {
labels = append(labels, telemetry.NewLabel(coretypes.LabelSource, "true"))

// obtain the escrow address for the source channel end
escrowAddress := types.GetEscrowAddress(sourcePort, sourceChannel)
if err := k.escrowToken(ctx, sender, escrowAddress, token); err != nil {
return err
}

} else {
labels = append(labels, telemetry.NewLabel(coretypes.LabelSource, "false"))

// transfer the coins to the module account and burn them
if err := k.bankKeeper.SendCoinsFromAccountToModule(
ctx, sender, types.ModuleName, sdk.NewCoins(token),
); err != nil {
return err
}

if err := k.bankKeeper.BurnCoins(
ctx, types.ModuleName, sdk.NewCoins(token),
); err != nil {
// NOTE: should not happen as the module account was
// retrieved on the step above and it has enough balance
// to burn.
panic(fmt.Errorf("cannot burn coins after a successful send to a module account: %v", err))
}
}

defer func() {
if token.Amount.IsInt64() {
telemetry.SetGaugeWithLabels(
[]string{"tx", "msg", "ibc", "transfer"},
float32(token.Amount.Int64()),
[]metrics.Label{telemetry.NewLabel(coretypes.LabelDenom, packetData.Denom)},
)
}

telemetry.IncrCounterWithLabels(
[]string{"ibc", types.ModuleName, "send"},
1,
labels,
)
}()

return nil
}

// OnRecvPacket processes a cross chain fungible token transfer. If the
// sender chain is the source of minted tokens then vouchers will be minted
// and sent to the receiving address. Otherwise if the sender chain is sending
Expand Down
Loading
Loading