diff --git a/Makefile b/Makefile index c20e4601a..692b12c27 100644 --- a/Makefile +++ b/Makefile @@ -58,8 +58,7 @@ test-integration: @go test -mod=readonly -v -timeout 20m ./_test/ test-gaia: - @go test -mod=readonly -v -run TestGaiaToGaiaRelaying ./_test/ - @go test -mod=readonly -v -run TestRelayAllChannelsOnConnection ./_test/ + @go test -mod=readonly -v -run 'TestGaiaToGaiaRelaying|TestGaiaToGaiaRelaying|TestUnorderedChannelBlockHeightTimeout|TestUnorderedChannelTimestampTimeout' ./_test test-akash: @go test -mod=readonly -v -run TestAkashToGaiaRelaying ./_test/ diff --git a/_test/relayer_chain_test.go b/_test/relayer_chain_test.go index 14009c7fe..5e5f3c002 100644 --- a/_test/relayer_chain_test.go +++ b/_test/relayer_chain_test.go @@ -718,7 +718,7 @@ func TestUnorderedChannelTimestampTimeout(t *testing.T) { filter := relayer.ChannelFilter{} _ = relayer.StartRelayer(ctx, log, src, dst, filter, 2*cmd.MB, 5) - time.Sleep(time.Second * 5) + time.Sleep(time.Second * 10) // check balance on src against expected srcGot, err := src.ChainProvider.QueryBalance(ctx, src.ChainProvider.Key()) diff --git a/cmd/tx.go b/cmd/tx.go index 6b98441f6..d22f1babf 100644 --- a/cmd/tx.go +++ b/cmd/tx.go @@ -2,7 +2,6 @@ package cmd import ( "fmt" - "strconv" "strings" "time" @@ -34,7 +33,6 @@ Most of these commands take a [path] argument. Make sure: linkCmd(a), linkThenStartCmd(a), relayMsgsCmd(a), - relayMsgCmd(a), relayAcksCmd(a), xfersend(a), lineBreakCommand(), @@ -697,55 +695,6 @@ $ %s tx link-then-start demo-path --timeout 5s`, appName, appName)), return overrideFlag(a.Viper, channelParameterFlags(a.Viper, clientParameterFlags(a.Viper, strategyFlag(a.Viper, retryFlag(a.Viper, timeoutFlag(a.Viper, cmd)))))) } -func relayMsgCmd(a *appState) *cobra.Command { - cmd := &cobra.Command{ - Use: "relay-packet path_name src_channel_id seq_num", - Aliases: []string{"relay-pkt"}, - Short: "relay a non-relayed packet with a specific sequence number, in both directions", - Args: withUsage(cobra.ExactArgs(3)), - Example: strings.TrimSpace(fmt.Sprintf(` -$ %s transact relay-packet demo-path channel-1 1 -$ %s tx relay-pkt demo-path channel-1 1`, - appName, appName, - )), - RunE: func(cmd *cobra.Command, args []string) error { - c, src, dst, err := a.Config.ChainsFromPath(args[0]) - if err != nil { - return err - } - - if err = ensureKeysExist(c); err != nil { - return err - } - - maxTxSize, maxMsgLength, err := GetStartOptions(cmd) - if err != nil { - return err - } - - seqNum, err := strconv.Atoi(args[2]) - if err != nil { - return err - } - - channelID := args[1] - channel, err := relayer.QueryChannel(cmd.Context(), c[src], channelID) - if err != nil { - return err - } - - sp, err := relayer.UnrelayedSequences(cmd.Context(), c[src], c[dst], channel) - if err != nil { - return err - } - - return relayer.RelayPacket(cmd.Context(), a.Log, c[src], c[dst], sp, maxTxSize, maxMsgLength, uint64(seqNum), channel) - }, - } - - return strategyFlag(a.Viper, cmd) -} - func relayMsgsCmd(a *appState) *cobra.Command { cmd := &cobra.Command{ Use: "relay-packets path_name src_channel_id", diff --git a/relayer/naive-strategy.go b/relayer/naive-strategy.go index 0d1264e70..22b9214ae 100644 --- a/relayer/naive-strategy.go +++ b/relayer/naive-strategy.go @@ -99,12 +99,16 @@ func UnrelayedSequences(ctx context.Context, src, dst *Chain, srcChannel *chanty return nil, err } + var ( + srcUnreceivedPackets, dstUnreceivedPackets []uint64 + ) + eg, egCtx = errgroup.WithContext(ctx) // Re-set eg and egCtx after previous Wait. eg.Go(func() error { - // Query all packets sent by src that have been received by dst + // Query all packets sent by src that have not been received by dst. return retry.Do(func() error { var err error - rs.Src, err = dst.ChainProvider.QueryUnreceivedPackets(egCtx, uint64(dsth), srcChannel.Counterparty.ChannelId, srcChannel.Counterparty.PortId, srcPacketSeq) + srcUnreceivedPackets, err = dst.ChainProvider.QueryUnreceivedPackets(egCtx, uint64(dsth), srcChannel.Counterparty.ChannelId, srcChannel.Counterparty.PortId, srcPacketSeq) return err }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { dst.log.Info( @@ -119,10 +123,10 @@ func UnrelayedSequences(ctx context.Context, src, dst *Chain, srcChannel *chanty }) eg.Go(func() error { - // Query all packets sent by dst that have been received by src + // Query all packets sent by dst that have not been received by src. return retry.Do(func() error { var err error - rs.Dst, err = src.ChainProvider.QueryUnreceivedPackets(egCtx, uint64(srch), srcChannel.ChannelId, srcChannel.PortId, dstPacketSeq) + dstUnreceivedPackets, err = src.ChainProvider.QueryUnreceivedPackets(egCtx, uint64(srch), srcChannel.ChannelId, srcChannel.PortId, dstPacketSeq) return err }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { src.log.Info( @@ -140,6 +144,43 @@ func UnrelayedSequences(ctx context.Context, src, dst *Chain, srcChannel *chanty return nil, err } + // If this is an UNORDERED channel we can return at this point. + if srcChannel.Ordering != chantypes.ORDERED { + rs.Src = srcUnreceivedPackets + rs.Dst = dstUnreceivedPackets + return rs, nil + } + + // For ordered channels we want to only relay the packet whose sequence number is equal to + // the expected next packet receive sequence from the counterparty. + if len(srcUnreceivedPackets) > 0 { + nextSeqResp, err := dst.ChainProvider.QueryNextSeqRecv(ctx, dsth, srcChannel.Counterparty.ChannelId, srcChannel.Counterparty.PortId) + if err != nil { + return nil, err + } + + for _, seq := range srcUnreceivedPackets { + if seq == nextSeqResp.NextSequenceReceive { + rs.Src = append(rs.Src, seq) + break + } + } + } + + if len(dstUnreceivedPackets) > 0 { + nextSeqResp, err := src.ChainProvider.QueryNextSeqRecv(ctx, srch, srcChannel.ChannelId, srcChannel.PortId) + if err != nil { + return nil, err + } + + for _, seq := range dstUnreceivedPackets { + if seq == nextSeqResp.NextSequenceReceive { + rs.Dst = append(rs.Dst, seq) + break + } + } + } + return rs, nil } @@ -404,12 +445,14 @@ func RelayPackets(ctx context.Context, log *zap.Logger, src, dst *Chain, sp *Rel eg, egCtx := errgroup.WithContext(ctx) // add messages for sequences on src eg.Go(func() error { - return AddMessagesForSequences(egCtx, sp.Src, src, dst, srch, dsth, &msgs.Src, &msgs.Dst, srcChannel.ChannelId, srcChannel.PortId, srcChannel.Counterparty.ChannelId, srcChannel.Counterparty.PortId) + return AddMessagesForSequences(egCtx, sp.Src, src, dst, srch, dsth, &msgs.Src, &msgs.Dst, + srcChannel.ChannelId, srcChannel.PortId, srcChannel.Counterparty.ChannelId, srcChannel.Counterparty.PortId, srcChannel.Ordering) }) // add messages for sequences on dst eg.Go(func() error { - return AddMessagesForSequences(egCtx, sp.Dst, dst, src, dsth, srch, &msgs.Dst, &msgs.Src, srcChannel.Counterparty.ChannelId, srcChannel.Counterparty.PortId, srcChannel.ChannelId, srcChannel.PortId) + return AddMessagesForSequences(egCtx, sp.Dst, dst, src, dsth, srch, &msgs.Dst, &msgs.Src, + srcChannel.Counterparty.ChannelId, srcChannel.Counterparty.PortId, srcChannel.ChannelId, srcChannel.PortId, srcChannel.Ordering) }) if err = eg.Wait(); err != nil { @@ -471,15 +514,25 @@ func RelayPackets(ctx context.Context, log *zap.Logger, src, dst *Chain, sp *Rel // AddMessagesForSequences constructs RecvMsgs and TimeoutMsgs from sequence numbers on a src chain // and adds them to the appropriate queue of msgs for both src and dst -func AddMessagesForSequences(ctx context.Context, sequences []uint64, src, dst *Chain, srch, dsth int64, srcMsgs, dstMsgs *[]provider.RelayerMessage, srcChanID, srcPortID, dstChanID, dstPortID string) error { +func AddMessagesForSequences( + ctx context.Context, + sequences []uint64, + src, dst *Chain, + srch, dsth int64, + srcMsgs, dstMsgs *[]provider.RelayerMessage, + srcChanID, srcPortID, dstChanID, dstPortID string, + order chantypes.Order, +) error { for _, seq := range sequences { - var ( - recvMsg, timeoutMsg provider.RelayerMessage - err error + recvMsg, timeoutMsg, err := src.ChainProvider.RelayPacketFromSequence( + ctx, + src.ChainProvider, dst.ChainProvider, + uint64(srch), uint64(dsth), + seq, + dstChanID, dstPortID, dst.ClientID(), + srcChanID, srcPortID, src.ClientID(), + order, ) - - recvMsg, timeoutMsg, err = src.ChainProvider.RelayPacketFromSequence(ctx, src.ChainProvider, dst.ChainProvider, - uint64(srch), uint64(dsth), seq, dstChanID, dstPortID, dst.ClientID(), srcChanID, srcPortID, src.ClientID()) if err != nil { src.log.Info( "Failed to relay packet from sequence", @@ -489,6 +542,7 @@ func AddMessagesForSequences(ctx context.Context, sequences []uint64, src, dst * zap.String("dst_chain_id", dst.ChainID()), zap.String("dst_channel_id", dstChanID), zap.String("dst_port_id", dstPortID), + zap.String("channel_order", order.String()), zap.Error(err), ) return err @@ -556,150 +610,3 @@ func PrependUpdateClientMsg(ctx context.Context, msgs *[]provider.RelayerMessage return nil } - -// RelayPacket creates transactions to relay packets from src to dst and from dst to src -func RelayPacket(ctx context.Context, log *zap.Logger, src, dst *Chain, sp *RelaySequences, maxTxSize, maxMsgLength, seqNum uint64, srcChannel *chantypes.IdentifiedChannel) error { - // set the maximum relay transaction constraints - msgs := &RelayMsgs{ - Src: []provider.RelayerMessage{}, - Dst: []provider.RelayerMessage{}, - MaxTxSize: maxTxSize, - MaxMsgLength: maxMsgLength, - } - - srch, dsth, err := QueryLatestHeights(ctx, src, dst) - if err != nil { - return err - } - - srcChanID := srcChannel.ChannelId - srcPortID := srcChannel.PortId - dstChanID := srcChannel.Counterparty.ChannelId - dstPortID := srcChannel.Counterparty.PortId - - // add messages for sequences on src - for _, seq := range sp.Src { - if seq == seqNum { - // Query src for the sequence number to get type of packet - var recvMsg, timeoutMsg provider.RelayerMessage - if err = retry.Do(func() error { - recvMsg, timeoutMsg, err = src.ChainProvider.RelayPacketFromSequence(ctx, src.ChainProvider, dst.ChainProvider, uint64(srch), uint64(dsth), seq, dstChanID, dstPortID, dst.ClientID(), srcChanID, srcPortID, src.ClientID()) - if err != nil { - log.Warn( - "Failed to relay packet from seq on src", - zap.String("src_chain_id", src.ChainID()), - zap.String("dst_chain_id", dst.ChainID()), - zap.Error(err), - ) - } - return err - }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - srch, dsth, _ = QueryLatestHeights(ctx, src, dst) - })); err != nil { - return err - } - - // depending on the type of message to be relayed, we need to - // send to different chains - if recvMsg != nil { - msgs.Dst = append(msgs.Dst, recvMsg) - } - - if timeoutMsg != nil { - msgs.Src = append(msgs.Src, timeoutMsg) - } - } - } - - // add messages for sequences on dst - for _, seq := range sp.Dst { - if seq == seqNum { - // Query dst for the sequence number to get type of packet - var recvMsg, timeoutMsg provider.RelayerMessage - if err = retry.Do(func() error { - recvMsg, timeoutMsg, err = dst.ChainProvider.RelayPacketFromSequence(ctx, dst.ChainProvider, src.ChainProvider, uint64(dsth), uint64(srch), seq, srcChanID, srcPortID, src.ClientID(), dstChanID, dstPortID, dst.ClientID()) - if err != nil { - log.Warn("Failed to relay packet from seq on dst", zap.Error(err)) - } - return nil - }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - srch, dsth, _ = QueryLatestHeights(ctx, src, dst) - })); err != nil { - return err - } - - // depending on the type of message to be relayed, we need to - // send to different chains - if recvMsg != nil { - msgs.Src = append(msgs.Src, recvMsg) - } - - if timeoutMsg != nil { - msgs.Dst = append(msgs.Dst, timeoutMsg) - } - } - } - - if !msgs.Ready() { - log.Info( - "No packets to relay", - zap.String("src_chain_id", src.ChainID()), - zap.String("src_port_id", srcPortID), - zap.String("dst_chain_id", dst.ChainID()), - zap.String("dst_port_id", dstPortID), - ) - return nil - } - - // Prepend non-empty msg lists with UpdateClient - if len(msgs.Dst) != 0 { - srcHeader, err := src.ChainProvider.GetIBCUpdateHeader(ctx, srch, dst.ChainProvider, dst.ClientID()) - if err != nil { - return err - } - updateMsg, err := dst.ChainProvider.UpdateClient(dst.ClientID(), srcHeader) - if err != nil { - return err - } - - msgs.Dst = append([]provider.RelayerMessage{updateMsg}, msgs.Dst...) - } - - if len(msgs.Src) != 0 { - dstHeader, err := dst.ChainProvider.GetIBCUpdateHeader(ctx, dsth, src.ChainProvider, src.ClientID()) - if err != nil { - return err - } - updateMsg, err := src.ChainProvider.UpdateClient(src.ClientID(), dstHeader) - if err != nil { - return err - } - - msgs.Src = append([]provider.RelayerMessage{updateMsg}, msgs.Src...) - } - - // send messages to their respective chains - result := msgs.Send(ctx, log, AsRelayMsgSender(src), AsRelayMsgSender(dst)) - if err := result.Error(); err != nil { - if result.PartiallySent() { - log.Info( - "Partial success when relaying packet", - zap.String("src_chain_id", src.ChainID()), - zap.String("src_port_id", srcPortID), - zap.String("dst_chain_id", dst.ChainID()), - zap.String("dst_port_id", dstPortID), - zap.Error(err), - ) - } - return err - } - - if result.SuccessfulSrcBatches > 0 { - src.logPacketsRelayed(dst, result.SuccessfulSrcBatches, srcChannel) - } - if result.SuccessfulDstBatches > 0 { - dst.logPacketsRelayed(src, result.SuccessfulDstBatches, srcChannel) - } - - return nil -} diff --git a/relayer/pathEnd.go b/relayer/pathEnd.go index 086245084..90822988e 100644 --- a/relayer/pathEnd.go +++ b/relayer/pathEnd.go @@ -33,6 +33,18 @@ func OrderFromString(order string) chantypes.Order { } } +// StringFromOrder returns the string representation of a channel order. +func StringFromOrder(order chantypes.Order) string { + switch order { + case chantypes.UNORDERED: + return "unordered" + case chantypes.ORDERED: + return "ordered" + default: + return "" + } +} + var marshalledChains = map[PathEnd]*Chain{} // MarshalChain is PathEnd diff --git a/relayer/pathEnd_test.go b/relayer/pathEnd_test.go new file mode 100644 index 000000000..ef514207f --- /dev/null +++ b/relayer/pathEnd_test.go @@ -0,0 +1,41 @@ +package relayer + +import ( + chantypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + "github.com/stretchr/testify/require" + "testing" +) + +func TestOrderFromString(t *testing.T) { + const ( + ordered = "ordered" + unordered = "unordered" + none = "" + ) + + o := OrderFromString(ordered) + require.Equal(t, chantypes.ORDERED, o) + + u := OrderFromString(unordered) + require.Equal(t, chantypes.UNORDERED, u) + + empty := OrderFromString(none) + require.Equal(t, chantypes.NONE, empty) +} + +func TestStringFromOrder(t *testing.T) { + const ( + ordered = chantypes.ORDERED + unordered = chantypes.UNORDERED + none = chantypes.NONE + ) + + o := StringFromOrder(ordered) + require.Equal(t, "ordered", o) + + u := StringFromOrder(unordered) + require.Equal(t, "unordered", u) + + empty := StringFromOrder(none) + require.Equal(t, "", empty) +} diff --git a/relayer/provider/cosmos/provider.go b/relayer/provider/cosmos/provider.go index d424d5322..8f603ea69 100644 --- a/relayer/provider/cosmos/provider.go +++ b/relayer/provider/cosmos/provider.go @@ -888,43 +888,119 @@ func (cc *CosmosProvider) MsgTransfer(amount sdk.Coin, dstChainId, dstAddr, srcP // MsgRelayTimeout constructs the MsgTimeout which is to be sent to the sending chain. // The counterparty represents the receiving chain where the receipts would have been // stored. -func (cc *CosmosProvider) MsgRelayTimeout(ctx context.Context, dst provider.ChainProvider, dsth int64, packet provider.RelayPacket, dstChanId, dstPortId, srcChanId, srcPortId string) (provider.RelayerMessage, error) { +func (cc *CosmosProvider) MsgRelayTimeout( + ctx context.Context, + dst provider.ChainProvider, + dsth int64, + packet provider.RelayPacket, + dstChanId, dstPortId, srcChanId, srcPortId string, + order chantypes.Order, +) (provider.RelayerMessage, error) { var ( acc string err error + msg provider.RelayerMessage ) if acc, err = cc.Address(); err != nil { return nil, err } + switch order { + case chantypes.UNORDERED: + msg, err = cc.unorderedChannelTimeoutMsg(ctx, dst, dsth, packet, acc, dstChanId, dstPortId, srcChanId, srcPortId) + if err != nil { + return nil, err + } + case chantypes.ORDERED: + msg, err = cc.orderedChannelTimeoutMsg(ctx, dst, dsth, packet, acc, dstChanId, dstPortId, srcChanId, srcPortId) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("invalid order type %s, order should be %s or %s", + order, chantypes.ORDERED, chantypes.UNORDERED) + } + + return msg, nil +} + +func (cc *CosmosProvider) orderedChannelTimeoutMsg( + ctx context.Context, + dst provider.ChainProvider, + dsth int64, + packet provider.RelayPacket, + acc, dstChanId, dstPortId, srcChanId, srcPortId string, +) (provider.RelayerMessage, error) { + seqRes, err := dst.QueryNextSeqRecv(ctx, dsth, dstChanId, dstPortId) + if err != nil { + return nil, err + } + + if seqRes == nil { + return nil, fmt.Errorf("timeout packet [%s]seq{%d} has no associated proofs", cc.PCfg.ChainID, packet.Seq()) + } + + if seqRes.Proof == nil { + return nil, fmt.Errorf("timeout packet next sequence received proof seq(%d) is nil", packet.Seq()) + } + + msg := &chantypes.MsgTimeout{ + Packet: chantypes.Packet{ + Sequence: packet.Seq(), + SourcePort: srcPortId, + SourceChannel: srcChanId, + DestinationPort: dstPortId, + DestinationChannel: dstChanId, + Data: packet.Data(), + TimeoutHeight: packet.Timeout(), + TimeoutTimestamp: packet.TimeoutStamp(), + }, + ProofUnreceived: seqRes.Proof, + ProofHeight: seqRes.ProofHeight, + NextSequenceRecv: packet.Seq(), + Signer: acc, + } + + return NewCosmosMessage(msg), nil +} + +func (cc *CosmosProvider) unorderedChannelTimeoutMsg( + ctx context.Context, + dst provider.ChainProvider, + dsth int64, + packet provider.RelayPacket, + acc, dstChanId, dstPortId, srcChanId, srcPortId string, +) (provider.RelayerMessage, error) { recvRes, err := dst.QueryPacketReceipt(ctx, dsth, dstChanId, dstPortId, packet.Seq()) - switch { - case err != nil: + if err != nil { return nil, err - case recvRes.Proof == nil: - return nil, fmt.Errorf("timeout packet receipt proof seq(%d) is nil", packet.Seq()) - case recvRes == nil: + } + + if recvRes == nil { return nil, fmt.Errorf("timeout packet [%s]seq{%d} has no associated proofs", cc.PCfg.ChainID, packet.Seq()) - default: - msg := &chantypes.MsgTimeout{ - Packet: chantypes.Packet{ - Sequence: packet.Seq(), - SourcePort: srcPortId, - SourceChannel: srcChanId, - DestinationPort: dstPortId, - DestinationChannel: dstChanId, - Data: packet.Data(), - TimeoutHeight: packet.Timeout(), - TimeoutTimestamp: packet.TimeoutStamp(), - }, - ProofUnreceived: recvRes.Proof, - ProofHeight: recvRes.ProofHeight, - NextSequenceRecv: packet.Seq(), - Signer: acc, - } + } - return NewCosmosMessage(msg), nil + if recvRes.Proof == nil { + return nil, fmt.Errorf("timeout packet receipt proof seq(%d) is nil", packet.Seq()) + } + + msg := &chantypes.MsgTimeout{ + Packet: chantypes.Packet{ + Sequence: packet.Seq(), + SourcePort: srcPortId, + SourceChannel: srcChanId, + DestinationPort: dstPortId, + DestinationChannel: dstChanId, + Data: packet.Data(), + TimeoutHeight: packet.Timeout(), + TimeoutTimestamp: packet.TimeoutStamp(), + }, + ProofUnreceived: recvRes.Proof, + ProofHeight: recvRes.ProofHeight, + NextSequenceRecv: packet.Seq(), + Signer: acc, } + return NewCosmosMessage(msg), nil } // MsgRelayRecvPacket constructs the MsgRecvPacket which is to be sent to the receiving chain. @@ -968,7 +1044,13 @@ func (cc *CosmosProvider) MsgRelayRecvPacket(ctx context.Context, dst provider.C } // RelayPacketFromSequence relays a packet with a given seq on src and returns recvPacket msgs, timeoutPacketmsgs and error -func (cc *CosmosProvider) RelayPacketFromSequence(ctx context.Context, src, dst provider.ChainProvider, srch, dsth, seq uint64, dstChanId, dstPortId, dstClientId, srcChanId, srcPortId, srcClientId string) (provider.RelayerMessage, provider.RelayerMessage, error) { +func (cc *CosmosProvider) RelayPacketFromSequence( + ctx context.Context, + src, dst provider.ChainProvider, + srch, dsth, seq uint64, + dstChanId, dstPortId, dstClientId, srcChanId, srcPortId, srcClientId string, + order chantypes.Order, +) (provider.RelayerMessage, provider.RelayerMessage, error) { txs, err := cc.QueryTxs(ctx, 1, 1000, rcvPacketQuery(srcChanId, int(seq))) switch { case err != nil: @@ -1009,7 +1091,7 @@ func (cc *CosmosProvider) RelayPacketFromSequence(ctx context.Context, src, dst return nil, nil, fmt.Errorf("wrong sequence: expected(%d) got(%d)", seq, pkt.Seq()) } - timeout, err := src.MsgRelayTimeout(ctx, dst, int64(dsth), pkt, dstChanId, dstPortId, srcChanId, srcPortId) + timeout, err := src.MsgRelayTimeout(ctx, dst, int64(dsth), pkt, dstChanId, dstPortId, srcChanId, srcPortId, order) if err != nil { return nil, nil, err } diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 0bc8a5dd8..c57553085 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -102,10 +102,10 @@ type ChainProvider interface { MsgRelayAcknowledgement(ctx context.Context, dst ChainProvider, dstChanId, dstPortId, srcChanId, srcPortId string, dsth int64, packet RelayPacket) (RelayerMessage, error) MsgTransfer(amount sdk.Coin, dstChainId, dstAddr, srcPortId, srcChanId string, timeoutHeight, timeoutTimestamp uint64) (RelayerMessage, error) - MsgRelayTimeout(ctx context.Context, dst ChainProvider, dsth int64, packet RelayPacket, dstChanId, dstPortId, srcChanId, srcPortId string) (RelayerMessage, error) + MsgRelayTimeout(ctx context.Context, dst ChainProvider, dsth int64, packet RelayPacket, dstChanId, dstPortId, srcChanId, srcPortId string, order chantypes.Order) (RelayerMessage, error) MsgRelayRecvPacket(ctx context.Context, dst ChainProvider, dsth int64, packet RelayPacket, dstChanId, dstPortId, srcChanId, srcPortId string) (RelayerMessage, error) MsgUpgradeClient(srcClientId string, consRes *clienttypes.QueryConsensusStateResponse, clientRes *clienttypes.QueryClientStateResponse) (RelayerMessage, error) - RelayPacketFromSequence(ctx context.Context, src, dst ChainProvider, srch, dsth, seq uint64, dstChanId, dstPortId, dstClientId, srcChanId, srcPortId, srcClientId string) (RelayerMessage, RelayerMessage, error) + RelayPacketFromSequence(ctx context.Context, src, dst ChainProvider, srch, dsth, seq uint64, dstChanId, dstPortId, dstClientId, srcChanId, srcPortId, srcClientId string, order chantypes.Order) (RelayerMessage, RelayerMessage, error) AcknowledgementFromSequence(ctx context.Context, dst ChainProvider, dsth, seq uint64, dstChanId, dstPortId, srcChanId, srcPortId string) (RelayerMessage, error) SendMessage(ctx context.Context, msg RelayerMessage) (*RelayerTxResponse, bool, error) diff --git a/relayer/strategies.go b/relayer/strategies.go index 734ed82ba..508b60ded 100644 --- a/relayer/strategies.go +++ b/relayer/strategies.go @@ -48,9 +48,19 @@ func relayerMainLoop(ctx context.Context, log *zap.Logger, src, dst *Chain, filt // Apply the channel filter rule (i.e. build allowlist, denylist or relay on all channels available) srcChannels = applyChannelFilterRule(filter, srcChannels) + // TODO once upstream changes are merged for emitting the channel version in ibc-go, + // we will want to add back logic for finishing the channel handshake for interchain accounts. + // Essentially the interchain accounts module will initiate the handshake and then the relayer finishes it. + // So we will occasionally query recent txs and check the events for `ChannelOpenInit`, at which point + // we will attempt to finish opening the channel. + // Filter for open channels that are not already in our slice of open channels srcOpenChannels = filterOpenChannels(srcChannels, srcOpenChannels) + if len(srcOpenChannels) == 0 { + continue + } + // Spin up a goroutine to relay packets & acks for each channel that isn't already being relayed against for _, channel := range srcOpenChannels { if !channel.active {