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

feat: gmp middleware #315

Merged
merged 6 commits into from
Nov 10, 2023
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
13 changes: 10 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ import (
ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
"github.com/spf13/cast"

gmpmiddleware "github.com/ojo-network/ojo/app/gmpmiddleware"
ibctransfer "github.com/ojo-network/ojo/app/ibctransfer"

"github.com/ojo-network/ojo/util/genmap"
Expand Down Expand Up @@ -485,7 +486,8 @@ func New(
scopedTransferKeeper,
)
transferModule := NewIBCTransferModule(app.TransferKeeper)
transferIBCModule := NewIBCAppModule(app.TransferKeeper)
var ibcStack ibcporttypes.IBCModule
ibcStack = NewIBCAppModule(app.TransferKeeper)

// Create evidence Keeper for to register the IBC light client misbehavior evidence route
evidenceKeeper := evidencekeeper.NewKeeper(
Expand Down Expand Up @@ -523,9 +525,14 @@ func New(
),
)

// Create static IBC router, add transfer route, then set and seal it
// Create static IBC router, add transfer route, then set and seal it.
// We also need to add the axelar GMP middleware here.
ibcRouter := ibcporttypes.NewRouter()
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferIBCModule)
ibcStack = gmpmiddleware.NewIBCMiddleware(
ibcStack,
gmpmiddleware.NewGmpHandler(app.GmpKeeper),
)
ibcRouter.AddRoute(ibctransfertypes.ModuleName, ibcStack)
app.IBCKeeper.SetRouter(ibcRouter)

/**** Module Options ****/
Expand Down
208 changes: 208 additions & 0 deletions app/gmpmiddleware/gmp_middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
package gmpmiddleware

import (
"encoding/json"
"fmt"

"cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
"github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types"
ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported"
gmptypes "github.com/ojo-network/ojo/x/gmp/types"
)

type IBCMiddleware struct {
app porttypes.IBCModule
handler GeneralMessageHandler
}

func NewIBCMiddleware(app porttypes.IBCModule, handler GeneralMessageHandler) IBCMiddleware {
return IBCMiddleware{
app: app,
handler: handler,
}
}

// OnChanOpenInit implements the IBCModule interface
func (im IBCMiddleware) OnChanOpenInit(
ctx sdk.Context,
order channeltypes.Order,
connectionHops []string,
portID string,
channelID string,
chanCap *capabilitytypes.Capability,
counterparty channeltypes.Counterparty,
version string,
) (string, error) {
// call underlying callback
return im.app.OnChanOpenInit(
ctx,
order,
connectionHops,
portID,
channelID,
chanCap,
counterparty,
version,
)
}

// OnChanOpenTry implements the IBCMiddleware interface
func (im IBCMiddleware) OnChanOpenTry(
ctx sdk.Context,
order channeltypes.Order,
connectionHops []string,
portID,
channelID string,
channelCap *capabilitytypes.Capability,
counterparty channeltypes.Counterparty,
counterpartyVersion string,
) (string, error) {
return im.app.OnChanOpenTry(
ctx,
order,
connectionHops,
portID,
channelID,
channelCap,
counterparty,
counterpartyVersion,
)
}

// OnChanOpenAck implements the IBCMiddleware interface
func (im IBCMiddleware) OnChanOpenAck(
ctx sdk.Context,
portID,
channelID string,
counterpartyChannelID string,
counterpartyVersion string,
) error {
return im.app.OnChanOpenAck(
ctx,
portID,
channelID,
counterpartyChannelID,
counterpartyVersion,
)
}

// OnChanOpenConfirm implements the IBCMiddleware interface
func (im IBCMiddleware) OnChanOpenConfirm(
ctx sdk.Context,
portID,
channelID string,
) error {
return im.app.OnChanOpenConfirm(ctx, portID, channelID)
}

// OnChanCloseInit implements the IBCMiddleware interface
func (im IBCMiddleware) OnChanCloseInit(
ctx sdk.Context,
portID,
channelID string,
) error {
return im.app.OnChanCloseInit(ctx, portID, channelID)
}

// OnChanCloseConfirm implements the IBCMiddleware interface
func (im IBCMiddleware) OnChanCloseConfirm(
ctx sdk.Context,
portID,
channelID string,
) error {
return im.app.OnChanCloseConfirm(ctx, portID, channelID)
}

// OnRecvPacket implements the IBCMiddleware interface
func (im IBCMiddleware) OnRecvPacket(
ctx sdk.Context,
packet channeltypes.Packet,
relayer sdk.AccAddress,
) ibcexported.Acknowledgement {
ack := im.app.OnRecvPacket(ctx, packet, relayer)
if !ack.Success() {
return ack
}

var data types.FungibleTokenPacketData
if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil {
return channeltypes.NewErrorAcknowledgement(
fmt.Errorf("cannot unmarshal ICS-20 transfer packet data"),
)
}

var msg Message
var err error

if err = json.Unmarshal([]byte(data.GetMemo()), &msg); err != nil {
return channeltypes.NewErrorAcknowledgement(fmt.Errorf("cannot unmarshal memo"))
}

switch msg.Type {
case gmptypes.TypeGeneralMessage:
err = im.handler.HandleGeneralMessage(
ctx,
msg.SourceChain,
msg.SourceAddress,
data.Receiver,
msg.Payload,
data.Sender,
packet.DestinationChannel,
)
case gmptypes.TypeGeneralMessageWithToken:
// parse the transfer amount
amt, ok := sdk.NewIntFromString(data.Amount)
if !ok {
return channeltypes.NewErrorAcknowledgement(
errors.Wrapf(
types.ErrInvalidAmount,
"unable to parse transfer amount (%s) into sdk.Int",
data.Amount,
),
)
}
denom := parseDenom(packet, data.Denom)

err = im.handler.HandleGeneralMessageWithToken(
ctx,
msg.SourceChain,
msg.SourceAddress,
data.Receiver,
msg.Payload,
data.Sender,
packet.DestinationChannel,
sdk.NewCoin(denom, amt),
)
default:
err = fmt.Errorf("unrecognized message type: %d", msg.Type)
}

if err != nil {
return channeltypes.NewErrorAcknowledgement(err)
}

return ack
}

// OnAcknowledgementPacket implements the IBCMiddleware interface
func (im IBCMiddleware) OnAcknowledgementPacket(
ctx sdk.Context,
packet channeltypes.Packet,
acknowledgement []byte,
relayer sdk.AccAddress,
) error {
return im.app.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer)
}

// OnTimeoutPacket implements the IBCMiddleware interface
func (im IBCMiddleware) OnTimeoutPacket(
ctx sdk.Context,
packet channeltypes.Packet,
relayer sdk.AccAddress,
) error {
return im.app.OnTimeoutPacket(ctx, packet, relayer)
}
106 changes: 106 additions & 0 deletions app/gmpmiddleware/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package gmpmiddleware

import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ojo-network/ojo/x/gmp/types"
)

type GmpKeeper interface {
RelayPrice(
goCtx context.Context,
msg *types.MsgRelayPrice,
) (*types.MsgRelayPriceResponse, error)
GetParams(ctx sdk.Context) (params types.Params)
}

type GmpHandler struct {
gmp GmpKeeper
}

func NewGmpHandler(k GmpKeeper) *GmpHandler {
return &GmpHandler{
gmp: k,
}
}

// HandleGeneralMessage takes the receiving message from axelar,
// and sends it along to the GMP module.
func (h GmpHandler) HandleGeneralMessage(
ctx sdk.Context,
srcChain,
srcAddress string,
destAddress string,
payload []byte,
sender string,
channel string,
) error {
ctx.Logger().Info("HandleGeneralMessage called",
"srcChain", srcChain,
"srcAddress", srcAddress,
"destAddress", destAddress,
"payload", payload,
"module", "x/gmp-middleware",
)

err := verifyParams(h.gmp.GetParams(ctx), sender, channel)
if err != nil {
return err
}
denoms, err := parsePayload(payload)
if err != nil {
return err
}

_, err = h.gmp.RelayPrice(ctx,
&types.MsgRelayPrice{
Relayer: srcAddress,
DestinationChain: srcChain,
DestinationAddress: destAddress,
Denoms: denoms,
},
)
return err
}

// HandleGeneralMessage takes the receiving message from axelar,
// and sends it along to the GMP module.
func (h GmpHandler) HandleGeneralMessageWithToken(
ctx sdk.Context,
srcChain,
srcAddress string,
destAddress string,
payload []byte,
sender string,
channel string,
coin sdk.Coin,
) error {
ctx.Logger().Info("HandleGeneralMessageWithToken called",
"srcChain", srcChain,
"srcAddress", srcAddress,
"destAddress", destAddress,
"payload", payload,
"coin", coin,
)

err := verifyParams(h.gmp.GetParams(ctx), sender, channel)
if err != nil {
return err
}
denoms, err := parsePayload(payload)
if err != nil {
return err
}

_, err = h.gmp.RelayPrice(ctx,
&types.MsgRelayPrice{
Relayer: srcAddress,
DestinationChain: srcChain,
DestinationAddress: destAddress,
Denoms: denoms,
Token: coin,
},
)
return err
}
Loading
Loading