diff --git a/app/gmp_middleware/gmp_middleware.go b/app/gmp_middleware/gmp_middleware.go index c48fb120..c9528b31 100644 --- a/app/gmp_middleware/gmp_middleware.go +++ b/app/gmp_middleware/gmp_middleware.go @@ -4,14 +4,15 @@ import ( "encoding/json" "fmt" + "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" transfertypes "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 { @@ -38,7 +39,16 @@ func (im IBCMiddleware) OnChanOpenInit( version string, ) (string, error) { // call underlying callback - return im.app.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, chanCap, counterparty, version) + return im.app.OnChanOpenInit( + ctx, + order, + connectionHops, + portID, + channelID, + chanCap, + counterparty, + version, + ) } // OnChanOpenTry implements the IBCMiddleware interface @@ -52,7 +62,16 @@ func (im IBCMiddleware) OnChanOpenTry( counterparty channeltypes.Counterparty, counterpartyVersion string, ) (string, error) { - return im.app.OnChanOpenTry(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion) + return im.app.OnChanOpenTry( + ctx, + order, + connectionHops, + portID, + channelID, + channelCap, + counterparty, + counterpartyVersion, + ) } // OnChanOpenAck implements the IBCMiddleware interface @@ -63,7 +82,13 @@ func (im IBCMiddleware) OnChanOpenAck( counterpartyChannelID string, counterpartyVersion string, ) error { - return im.app.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) + return im.app.OnChanOpenAck( + ctx, + portID, + channelID, + counterpartyChannelID, + counterpartyVersion, + ) } // OnChanOpenConfirm implements the IBCMiddleware interface @@ -106,13 +131,9 @@ func (im IBCMiddleware) OnRecvPacket( var data transfertypes.FungibleTokenPacketData if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { - return channeltypes.NewErrorAcknowledgement(fmt.Errorf("cannot unmarshal ICS-20 transfer packet data")) - } - - // authenticate the message with packet sender + channel-id - // TODO: authenticate the message with channel-id - if data.Sender != AxelarGMPAcc { - return ack + return channeltypes.NewErrorAcknowledgement( + fmt.Errorf("cannot unmarshal ICS-20 transfer packet data"), + ) } var msg Message @@ -123,19 +144,40 @@ func (im IBCMiddleware) OnRecvPacket( } switch msg.Type { - case TypeGeneralMessage: - // implement the handler - err = im.handler.HandleGeneralMessage(ctx, msg.SourceChain, msg.SourceAddress, data.Receiver, msg.Payload) - case TypeGeneralMessageWithToken: + 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(sdkerrors.Wrapf(transfertypes.ErrInvalidAmount, "unable to parse transfer amount (%s) into sdk.Int", data.Amount)) + return channeltypes.NewErrorAcknowledgement( + errors.Wrapf( + transfertypes.ErrInvalidAmount, + "unable to parse transfer amount (%s) into sdk.Int", + data.Amount, + ), + ) } - denom := parseDenom(packet, data.Denom) - // implement the handler - err = im.handler.HandleGeneralMessageWithToken(ctx, msg.SourceChain, msg.SourceAddress, data.Receiver, msg.Payload, sdk.NewCoin(denom, amt)) + + 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) } diff --git a/app/gmp_middleware/handler.go b/app/gmp_middleware/handler.go index 822aeb07..473c22ae 100644 --- a/app/gmp_middleware/handler.go +++ b/app/gmp_middleware/handler.go @@ -2,14 +2,20 @@ package gmp_middleware import ( "context" + "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ojo-network/ojo/x/gmp/types" gmptypes "github.com/ojo-network/ojo/x/gmp/types" ) type GmpKeeper interface { - RelayPrice(goCtx context.Context, msg *gmptypes.MsgRelayPrice) (*gmptypes.MsgRelayPriceResponse, error) + RelayPrice( + goCtx context.Context, + msg *gmptypes.MsgRelayPrice, + ) (*gmptypes.MsgRelayPriceResponse, error) + GetParams(ctx sdk.Context) (params types.Params) } type GmpHandler struct { @@ -24,7 +30,15 @@ func NewGmpHandler(k GmpKeeper) *GmpHandler { // 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) error { +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, @@ -33,6 +47,14 @@ func (h GmpHandler) HandleGeneralMessage(ctx sdk.Context, srcChain, srcAddress s "module", "x/gmp-middleware", ) + params := h.gmp.GetParams(ctx) + if !strings.EqualFold(params.GmpAddress, sender) { + return fmt.Errorf("invalid sender address: %s", sender) + } + if !strings.EqualFold(params.GmpChannel, channel) { + return fmt.Errorf("invalid channel: %s", channel) + } + denomString := string(payload) denoms := strings.Split(denomString, ",") @@ -47,8 +69,18 @@ func (h GmpHandler) HandleGeneralMessage(ctx sdk.Context, srcChain, srcAddress s return err } -// HandleGeneralMessageWithToken currently performs a no-op. -func (h GmpHandler) HandleGeneralMessageWithToken(ctx sdk.Context, srcChain, srcAddress string, destAddress string, payload []byte, coin sdk.Coin) error { +// 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, @@ -57,5 +89,25 @@ func (h GmpHandler) HandleGeneralMessageWithToken(ctx sdk.Context, srcChain, src "coin", coin, ) - return nil + params := h.gmp.GetParams(ctx) + if !strings.EqualFold(params.GmpAddress, sender) { + return fmt.Errorf("invalid sender address: %s", sender) + } + if !strings.EqualFold(params.GmpChannel, channel) { + return fmt.Errorf("invalid channel: %s", channel) + } + + denomString := string(payload) + denoms := strings.Split(denomString, ",") + + _, err := h.gmp.RelayPrice(ctx, &gmptypes.MsgRelayPrice{ + Relayer: srcAddress, + DestinationChain: srcChain, + DestinationAddress: destAddress, + Denoms: denoms, + Token: coin, + }, + ) + + return err } diff --git a/app/gmp_middleware/types.go b/app/gmp_middleware/types.go index 1c5e5f07..af514a31 100644 --- a/app/gmp_middleware/types.go +++ b/app/gmp_middleware/types.go @@ -8,12 +8,10 @@ import ( ) type GeneralMessageHandler interface { - HandleGeneralMessage(ctx sdk.Context, srcChain, srcAddress string, destAddress string, payload []byte) error - HandleGeneralMessageWithToken(ctx sdk.Context, srcChain, srcAddress string, destAddress string, payload []byte, coin sdk.Coin) error + HandleGeneralMessage(ctx sdk.Context, srcChain, srcAddress string, destAddress string, payload []byte, sender string, channel string) error + HandleGeneralMessageWithToken(ctx sdk.Context, srcChain, srcAddress string, destAddress string, payload []byte, sender string, channel string, coin sdk.Coin) error } -const AxelarGMPAcc = "axelar1dv7u5k73pzqrxlzujxg3qp8kvc3pje7jtdvu72npnt5zhq05ejcsn5qme5" - // Message is attached in ICS20 packet memo field type Message struct { SourceChain string `json:"source_chain"` @@ -22,16 +20,6 @@ type Message struct { Type int64 `json:"type"` } -type MessageType int - -const ( - // TypeUnrecognized means coin type is unrecognized - TypeUnrecognized = iota - TypeGeneralMessage - // TypeGeneralMessageWithToken is a general message with token - TypeGeneralMessageWithToken -) - // parseDenom convert denom to receiver chain representation func parseDenom(packet channeltypes.Packet, denom string) string { if types.ReceiverChainIsSource(packet.GetSourcePort(), packet.GetSourceChannel(), denom) {