-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Dreamer
committed
Mar 8, 2024
1 parent
bbefb02
commit 531761c
Showing
4 changed files
with
275 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
package axelar | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
errorsmod "cosmossdk.io/errors" | ||
sdkmath "cosmossdk.io/math" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/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" | ||
|
||
"github.com/irisnet/irishub/v2/modules/axelar/types" | ||
) | ||
|
||
// IBCMiddleware implements the IBCMiddleware interface | ||
type IBCMiddleware struct { | ||
app porttypes.IBCModule | ||
handler types.GeneralMessageHandler | ||
} | ||
|
||
// NewIBCMiddleware creates a new IBCMiddleware | ||
func NewIBCMiddleware(app porttypes.IBCModule, handler types.GeneralMessageHandler) IBCMiddleware { | ||
if handler == nil { | ||
handler = types.EmptyHandler{} | ||
} | ||
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 transfertypes.FungibleTokenPacketData | ||
if err := transfertypes.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 != types.AxelarGMPAcc { | ||
return ack | ||
} | ||
|
||
var ( | ||
msg types.Message | ||
err error | ||
) | ||
|
||
if err = json.Unmarshal([]byte(data.GetMemo()), &msg); err != nil { | ||
return channeltypes.NewErrorAcknowledgement(fmt.Errorf("cannot unmarshal memo")) | ||
} | ||
|
||
switch msg.Type { | ||
case types.TypePureMessage: | ||
err = im.handler.HandleGeneralMessage(ctx, msg.SourceChain, msg.SourceAddress, data.Receiver, msg.Payload) | ||
case types.TypeMessageWithToken: | ||
amt, ok := sdkmath.NewIntFromString(data.Amount) | ||
if !ok { | ||
return channeltypes.NewErrorAcknowledgement(errorsmod.Wrapf(transfertypes.ErrInvalidAmount, "unable to parse transfer amount (%s) into sdk.Int", data.Amount)) | ||
} | ||
|
||
denom := types.ParseDenom(packet, data.Denom) | ||
err = im.handler.HandleGeneralMessageWithToken(ctx, msg.SourceChain, msg.SourceAddress, data.Receiver, msg.Payload, sdk.NewCoin(denom, amt)) | ||
default: | ||
err = fmt.Errorf("unrecognized mesasge 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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package types | ||
|
||
import ( | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
) | ||
|
||
// GeneralMessageHandler handles messages from axelar | ||
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 | ||
} | ||
|
||
// EmptyHandler implements the GeneralMessageHandler | ||
type EmptyHandler struct{} | ||
|
||
// HandleGeneralMessage implements the GeneralMessageHandler | ||
func (h EmptyHandler) HandleGeneralMessage(ctx sdk.Context, srcChain, srcAddress string, destAddress string, payload []byte) error { | ||
ctx.Logger().Info("HandleGeneralMessage called", | ||
"srcChain", srcChain, | ||
"srcAddress", srcAddress, | ||
"destAddress", destAddress, | ||
"payload", payload, | ||
"module", "axelar", | ||
) | ||
return nil | ||
} | ||
|
||
// HandleGeneralMessageWithToken implements the GeneralMessageHandler | ||
func (h EmptyHandler) HandleGeneralMessageWithToken(ctx sdk.Context, srcChain, srcAddress string, destAddress string, payload []byte, coin sdk.Coin) error { | ||
ctx.Logger().Info("HandleGeneralMessageWithToken called", | ||
"srcChain", srcChain, | ||
"srcAddress", srcAddress, | ||
"destAddress", destAddress, | ||
"payload", payload, | ||
"coin", coin, | ||
"module", "axelar", | ||
) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package types | ||
|
||
import ( | ||
transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" | ||
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" | ||
) | ||
|
||
// TODO: AxelarGMPAcc should be moved to config | ||
const AxelarGMPAcc = "axelar1dv4u5k73pzqrxlzujxg3qp8kvc3pje7jtdvu72npnt5zhq05ejcsn5qme5" | ||
|
||
// Message is attached in ICS20 packet memo field | ||
type Message struct { | ||
SourceChain string `json:"source_chain"` | ||
SourceAddress string `json:"source_address"` | ||
Payload []byte `json:"payload"` | ||
Type int64 `json:"type"` | ||
} | ||
|
||
// MessageType is the type of message | ||
type MessageType int | ||
|
||
const ( | ||
// TypeUnrecognized means coin type is unrecognized | ||
TypeUnrecognized = iota | ||
// TypePureMessage is a general message | ||
TypePureMessage | ||
// TypeMessageWithToken is a general message with token | ||
TypeMessageWithToken | ||
) | ||
|
||
// ParseDenom convert denom to receiver chain representation | ||
func ParseDenom(packet channeltypes.Packet, denom string) string { | ||
if transfertypes.ReceiverChainIsSource(packet.GetSourcePort(), packet.GetSourceChannel(), denom) { | ||
// remove prefix added by sender chain | ||
voucherPrefix := transfertypes.GetDenomPrefix(packet.GetSourcePort(), packet.GetSourceChannel()) | ||
unprefixedDenom := denom[len(voucherPrefix):] | ||
|
||
// coin denomination used in sending from the escrow address | ||
denom = unprefixedDenom | ||
|
||
// The denomination used to send the coins is either the native denom or the hash of the path | ||
// if the denomination is not native. | ||
denomTrace := transfertypes.ParseDenomTrace(unprefixedDenom) | ||
if denomTrace.Path != "" { | ||
denom = denomTrace.IBCDenom() | ||
} | ||
return denom | ||
} | ||
|
||
prefixedDenom := transfertypes.GetDenomPrefix(packet.GetDestPort(), packet.GetDestChannel()) + denom | ||
denom = transfertypes.ParseDenomTrace(prefixedDenom).IBCDenom() | ||
|
||
return denom | ||
} |