diff --git a/cmd/tx.go b/cmd/tx.go index b9c54fb..0bf237f 100644 --- a/cmd/tx.go +++ b/cmd/tx.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "strconv" "strings" "github.com/spf13/cobra" @@ -33,13 +34,17 @@ func txRelayCmd(app *relayer.App) *cobra.Command { cmd := &cobra.Command{ Use: "relay [tunnel_id]", Aliases: []string{"rly"}, - Short: "Relay a specific message to the destination chain", - Args: withUsage(cobra.ExactArgs(2)), + Short: "Relay the next sequence message to the destination tunnel contract address", + Args: withUsage(cobra.ExactArgs(1)), Example: strings.TrimSpace(fmt.Sprintf(` -$ %s tx relay 1 1, # relay the message with tunnelID 1 and sequence 1`, appName)), +$ %s tx relay 1, # relay the next sequence message of the tunnelID 1`, appName)), RunE: func(cmd *cobra.Command, args []string) error { - _ = app - return nil + tunnelID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + return app.Relay(cmd.Context(), tunnelID) }, } diff --git a/go.mod b/go.mod index 8ce8c35..770c4d4 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/99designs/keyring v1.2.1 // indirect github.com/DataDog/datadog-go v3.2.0+incompatible // indirect github.com/DataDog/zstd v1.5.5 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/bandprotocol/go-owasm v0.3.1 // indirect @@ -128,7 +129,7 @@ require ( github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.20.1 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -167,7 +168,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect nhooyr.io/websocket v1.8.6 // indirect @@ -180,7 +180,7 @@ replace ( // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // // replace bandprotocol chain with private chain - github.com/bandprotocol/chain/v3 => github.com/bandprotocol/private-chain/v3 v3.0.0-20241022085810-642e764518fa + github.com/bandprotocol/chain/v3 => github.com/bandprotocol/private-chain/v3 v3.0.0-20241031180150-de8d5c14cdde // replace broken goleveldb github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // stick with compatible version of rapid in v0.47.x line diff --git a/go.sum b/go.sum index 599bd23..62d5362 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= @@ -61,8 +63,8 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/bandprotocol/go-owasm v0.3.1 h1:L38qAEmb0KyTICHBHJaBoo6yy5+BlbOzQeQ+ioUV5Uw= github.com/bandprotocol/go-owasm v0.3.1/go.mod h1:SAzGihlBl8eZDXA1dO2aeAZLm8J2QkNd+KvnA2Dw9Kg= -github.com/bandprotocol/private-chain/v3 v3.0.0-20241022085810-642e764518fa h1:uoMqJVyqsujYl+g2zhz/ztqBPia0HNg1YyDRsLEvDxo= -github.com/bandprotocol/private-chain/v3 v3.0.0-20241022085810-642e764518fa/go.mod h1:gddpk4SowgqQj2Cveg9DVkYO/u7S46Bz8UHoxu1rNdk= +github.com/bandprotocol/private-chain/v3 v3.0.0-20241031180150-de8d5c14cdde h1:BcDHxykep68HARNcu/eJJjrOCN/U/bRiMzbxoV184kE= +github.com/bandprotocol/private-chain/v3 v3.0.0-20241031180150-de8d5c14cdde/go.mod h1:nuzf8uzuukOjHDiawAdrfdP1MaEeZ10rWiNfVbkmtX4= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -630,8 +632,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.20.1 h1:IMJXHOD6eARkQpxo8KkhgEVFlBNm+nkrFUyGlIu7Na8= -github.com/prometheus/client_golang v1.20.1/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= diff --git a/internal/relayertest/mocks/chain_provider.go b/internal/relayertest/mocks/chain_provider.go index 6c1f9d1..47faab4 100644 --- a/internal/relayertest/mocks/chain_provider.go +++ b/internal/relayertest/mocks/chain_provider.go @@ -13,8 +13,8 @@ import ( context "context" reflect "reflect" - types "github.com/bandprotocol/falcon/relayer/chains/types" - types0 "github.com/bandprotocol/falcon/relayer/types" + types "github.com/bandprotocol/falcon/relayer/band/types" + types0 "github.com/bandprotocol/falcon/relayer/chains/types" gomock "go.uber.org/mock/gomock" ) @@ -57,10 +57,10 @@ func (mr *MockChainProviderMockRecorder) Init(ctx any) *gomock.Call { } // QueryTunnelInfo mocks base method. -func (m *MockChainProvider) QueryTunnelInfo(ctx context.Context, tunnelID uint64, tunnelDestinationAddr string) (*types.Tunnel, error) { +func (m *MockChainProvider) QueryTunnelInfo(ctx context.Context, tunnelID uint64, tunnelDestinationAddr string) (*types0.Tunnel, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "QueryTunnelInfo", ctx, tunnelID, tunnelDestinationAddr) - ret0, _ := ret[0].(*types.Tunnel) + ret0, _ := ret[0].(*types0.Tunnel) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -72,15 +72,15 @@ func (mr *MockChainProviderMockRecorder) QueryTunnelInfo(ctx, tunnelID, tunnelDe } // RelayPacket mocks base method. -func (m *MockChainProvider) RelayPacket(ctx context.Context, input *types0.RelayerTask) error { +func (m *MockChainProvider) RelayPacket(ctx context.Context, packet *types.Packet) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RelayPacket", ctx, input) + ret := m.ctrl.Call(m, "RelayPacket", ctx, packet) ret0, _ := ret[0].(error) return ret0 } // RelayPacket indicates an expected call of RelayPacket. -func (mr *MockChainProviderMockRecorder) RelayPacket(ctx, input any) *gomock.Call { +func (mr *MockChainProviderMockRecorder) RelayPacket(ctx, packet any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RelayPacket", reflect.TypeOf((*MockChainProvider)(nil).RelayPacket), ctx, input) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RelayPacket", reflect.TypeOf((*MockChainProvider)(nil).RelayPacket), ctx, packet) } diff --git a/relayer/app.go b/relayer/app.go index eb2afb5..afc6676 100644 --- a/relayer/app.go +++ b/relayer/app.go @@ -276,19 +276,54 @@ func (a *App) QueryTunnelPacketInfo(ctx context.Context, tunnelID uint64, sequen return c.GetTunnelPacket(ctx, tunnelID, sequence) } +// Relay relays the packet from the source chain to the destination chain. +func (a *App) Relay(ctx context.Context, tunnelID uint64) error { + a.Log.Debug("query tunnel info on band chain", zap.Uint64("tunnel_id", tunnelID)) + tunnel, err := a.BandClient.GetTunnel(ctx, tunnelID) + if err != nil { + return err + } + + chainProvider, ok := a.targetChains[tunnel.TargetChainID] + if !ok { + return fmt.Errorf("target chain provider not found: %s", tunnel.TargetChainID) + } + + tr := NewTunnelRelayer( + a.Log, + tunnel.ID, + tunnel.TargetAddress, + a.Config.Global.CheckingPacketInterval, + a.BandClient, + chainProvider, + ) + + return tr.CheckAndRelay(ctx) +} + // Start starts the tunnel relayer program. func (a *App) Start(ctx context.Context, tunnelIDs []uint64) error { a.Log.Info("starting tunnel relayer") - // TODO: load the tunnel information from the bandchain. - // If len(tunnelIDs == 0), load all tunnels info. - tunnels := []*bandtypes.Tunnel{ - { - ID: 1, - LatestSequence: 0, - TargetChainID: "testnet_evm", - TargetAddress: "0x5FbDB2315678afecb367f032d93F642f64180aa3", - }, + // query tunnels + var tunnels []bandtypes.Tunnel + if len(tunnelIDs) == 0 { + // TODO: query all tunnels + } else { + tunnels = make([]bandtypes.Tunnel, 0, len(tunnelIDs)) + for _, tunnelID := range tunnelIDs { + tunnel, err := a.BandClient.GetTunnel(ctx, tunnelID) + if err != nil { + return err + } + tunnels = append(tunnels, *tunnel) + } + } + + // TODO: query tunnels + if len(tunnels) == 0 { + a.Log.Error("no tunnel ID provided") + return fmt.Errorf("no tunnel ID provided") } // initialize the tunnel relayer diff --git a/relayer/band/encoding.go b/relayer/band/encoding.go index 9b1de70..4aa08b8 100644 --- a/relayer/band/encoding.go +++ b/relayer/band/encoding.go @@ -39,14 +39,12 @@ func MakeEncodingConfig() EncodingConfig { "tunnel.v1beta1.RouteI", (*tunneltypes.RouteI)(nil), &tunneltypes.TSSRoute{}, - &tunneltypes.AxelarRoute{}, ) interfaceRegistry.RegisterInterface( "tunnel.v1beta1.PacketContentI", (*tunneltypes.PacketContentI)(nil), &tunneltypes.TSSPacketContent{}, - &tunneltypes.AxelarPacketContent{}, ) cdc := codec.NewProtoCodec(interfaceRegistry) diff --git a/relayer/chains/evm/abi/TunnelRouter.json b/relayer/chains/evm/abi/TunnelRouter.json index 38fe441..04f0952 100644 --- a/relayer/chains/evm/abi/TunnelRouter.json +++ b/relayer/chains/evm/abi/TunnelRouter.json @@ -1,15 +1,28 @@ [ { - "type": "function", - "name": "isActive", "inputs": [ - { "name": "tunnelID", "type": "uint64", "internalType": "uint64" }, - { "name": "targetAddr", "type": "address", "internalType": "address" } + { "internalType": "uint64", "name": "tunnelId", "type": "uint64" }, + { "internalType": "address", "name": "addr", "type": "address" } ], + "stateMutability": "view", + "type": "function", + "name": "tunnelInfo", "outputs": [ - { "name": "is_active", "type": "bool", "internalType": "bool" } - ], - "stateMutability": "view" + { + "internalType": "struct ITunnelRouter.TunnelInfo", + "name": "tunnelInfo", + "type": "tuple", + "components": [ + { "internalType": "bool", "name": "isActive", "type": "bool" }, + { + "internalType": "uint64", + "name": "latestSequence", + "type": "uint64" + }, + { "internalType": "uint256", "name": "balance", "type": "uint256" } + ] + } + ] }, { "type": "function", diff --git a/relayer/chains/evm/abis.go b/relayer/chains/evm/abis.go index 93d9c02..a62b1fa 100644 --- a/relayer/chains/evm/abis.go +++ b/relayer/chains/evm/abis.go @@ -1,11 +1,20 @@ package evm -import _ "embed" +import ( + _ "embed" + "math/big" +) //go:embed abi/TunnelRouter.json var gasPriceTunnelRouterABI string -// TunnelRouterIsActiveOutput defines the output parameters for the TunnelRouter.isActive method. -type TunnelRouterIsActiveOutput struct { - IsActive bool `json:"is_active"` +// TunnelInfoOutput defines the output parameters for the TunnelRouter.isActive method. +type TunnelInfoOutput struct { + IsActive bool `json:"is_active"` + LatestSequence uint64 `json:"latest_sequence"` + Balance *big.Int `json:"balance"` +} + +type TunnelInfoOutputRaw struct { + Info TunnelInfoOutput `json:"tunnel_info"` } diff --git a/relayer/chains/evm/provider.go b/relayer/chains/evm/provider.go index 6c0dd9c..31b75e2 100644 --- a/relayer/chains/evm/provider.go +++ b/relayer/chains/evm/provider.go @@ -19,7 +19,6 @@ import ( "github.com/bandprotocol/falcon/relayer/chains" "github.com/bandprotocol/falcon/relayer/chains/evm/gas" chainstypes "github.com/bandprotocol/falcon/relayer/chains/types" - "github.com/bandprotocol/falcon/relayer/types" ) var _ chains.ChainProvider = (*EVMChainProvider)(nil) @@ -126,7 +125,7 @@ func (cp *EVMChainProvider) QueryTunnelInfo( return nil, fmt.Errorf("[EVMProvider] invalid address: %w", err) } - isActive, err := cp.queryTargetContractIsActive(ctx, tunnelID, addr) + info, err := cp.queryTunnelInfo(ctx, tunnelID, addr) if err != nil { cp.Log.Error( "query contract error", @@ -140,16 +139,18 @@ func (cp *EVMChainProvider) QueryTunnelInfo( } return &chainstypes.Tunnel{ - ID: tunnelID, - TargetAddress: tunnelDestinationAddr, - IsActive: isActive, + ID: tunnelID, + TargetAddress: tunnelDestinationAddr, + IsActive: info.IsActive, + LatestSequence: info.LatestSequence, + Balance: info.Balance, }, nil } // RelayPacket relays the packet from the source chain to the destination chain. func (cp *EVMChainProvider) RelayPacket( ctx context.Context, - task *types.RelayerTask, + packet *bandtypes.Packet, ) error { if err := cp.Client.Connect(ctx); err != nil { cp.Log.Error( @@ -165,19 +166,19 @@ func (cp *EVMChainProvider) RelayPacket( cp.Log.Info( "relaying a message", zap.String("chain_name", cp.ChainName), - zap.Uint64("tunnel_id", task.Packet.TunnelID), - zap.Uint64("sequence", task.Packet.Sequence), + zap.Uint64("tunnel_id", packet.TunnelID), + zap.Uint64("sequence", packet.Sequence), zap.Int("retry_count", retryCount), ) - txHash, err := cp.handleRelay(ctx, task, retryCount) + txHash, err := cp.handleRelay(ctx, packet, retryCount) if err != nil { cp.Log.Error( "HandleRelay error", zap.Error(err), zap.String("chain_name", cp.ChainName), - zap.Uint64("tunnel_id", task.Packet.TunnelID), - zap.Uint64("sequence", task.Packet.Sequence), + zap.Uint64("tunnel_id", packet.TunnelID), + zap.Uint64("sequence", packet.Sequence), zap.Int("retry_count", retryCount), ) retryCount += 1 @@ -188,8 +189,8 @@ func (cp *EVMChainProvider) RelayPacket( cp.Log.Info( "submitting a message", zap.String("chain_name", cp.ChainName), - zap.Uint64("tunnel_id", task.Packet.TunnelID), - zap.Uint64("sequence", task.Packet.Sequence), + zap.Uint64("tunnel_id", packet.TunnelID), + zap.Uint64("sequence", packet.Sequence), zap.String("tx_hash", txHash), zap.Int("retry_count", retryCount), ) @@ -204,8 +205,8 @@ func (cp *EVMChainProvider) RelayPacket( "Failed to check tx status", zap.Error(err), zap.String("chain_name", cp.ChainName), - zap.Uint64("tunnel_id", task.Packet.TunnelID), - zap.Uint64("sequence", task.Packet.Sequence), + zap.Uint64("tunnel_id", packet.TunnelID), + zap.Uint64("sequence", packet.Sequence), zap.String("tx_hash", txHash), zap.Int("retry_count", retryCount), ) @@ -223,8 +224,8 @@ func (cp *EVMChainProvider) RelayPacket( cp.Log.Info( "Packet is successfully relayed", zap.String("chain_name", cp.ChainName), - zap.Uint64("tunnel_id", task.Packet.TunnelID), - zap.Uint64("sequence", task.Packet.Sequence), + zap.Uint64("tunnel_id", packet.TunnelID), + zap.Uint64("sequence", packet.Sequence), zap.String("tx_hash", txHash), zap.Int("retry_count", retryCount), ) @@ -237,8 +238,8 @@ func (cp *EVMChainProvider) RelayPacket( "Waiting for tx to be mined", zap.Error(err), zap.String("chain_name", cp.ChainName), - zap.Uint64("tunnel_id", task.Packet.TunnelID), - zap.Uint64("sequence", task.Packet.Sequence), + zap.Uint64("tunnel_id", packet.TunnelID), + zap.Uint64("sequence", packet.Sequence), zap.String("tx_hash", txHash), zap.Int("retry_count", retryCount), ) @@ -252,8 +253,8 @@ func (cp *EVMChainProvider) RelayPacket( zap.Error(checkTxErr), zap.String("status", txStatus.String()), zap.String("chain_name", cp.ChainName), - zap.Uint64("tunnel_id", task.Packet.TunnelID), - zap.Uint64("sequence", task.Packet.Sequence), + zap.Uint64("tunnel_id", packet.TunnelID), + zap.Uint64("sequence", packet.Sequence), zap.String("tx_hash", txHash), zap.Int("retry_count", retryCount), ) @@ -267,10 +268,10 @@ func (cp *EVMChainProvider) RelayPacket( // handleRelay handles the relay message from the source chain to the destination chain. func (cp *EVMChainProvider) handleRelay( ctx context.Context, - task *types.RelayerTask, + packet *bandtypes.Packet, retryCount int, ) (txHash string, err error) { - calldata, err := cp.createCalldata(task) + calldata, err := cp.createCalldata(packet) if err != nil { return "", fmt.Errorf("failed to create calldata: %w", err) } @@ -284,8 +285,8 @@ func (cp *EVMChainProvider) handleRelay( fmt.Sprintf("Relaying packet using address: %v", sender.address), zap.String("evm_sender_address", sender.address.String()), zap.String("chain_name", cp.ChainName), - zap.Uint64("tunnel_id", task.Packet.TunnelID), - zap.Uint64("sequence", task.Packet.Sequence), + zap.Uint64("tunnel_id", packet.TunnelID), + zap.Uint64("sequence", packet.Sequence), ) tx, err := cp.newRelayTx(ctx, calldata, sender.address, retryCount) @@ -351,28 +352,28 @@ func (cp *EVMChainProvider) checkConfirmedTx( return NewConfirmTxResult(txHash, TX_STATUS_SUCCESS, gasUsed, effGasPrice), nil } -// queryTargetContractIsActive queries the target contract is active or not. -func (cp *EVMChainProvider) queryTargetContractIsActive( +// queryTunnelInfo queries the target contract information. +func (cp *EVMChainProvider) queryTunnelInfo( ctx context.Context, tunnelID uint64, addr gethcommon.Address, -) (bool, error) { - calldata, err := cp.TunnelRouterABI.Pack("isActive", tunnelID, addr) +) (*TunnelInfoOutput, error) { + calldata, err := cp.TunnelRouterABI.Pack("tunnelInfo", tunnelID, addr) if err != nil { - return false, fmt.Errorf("failed to pack calldata: %w", err) + return nil, fmt.Errorf("failed to pack calldata: %w", err) } b, err := cp.Client.Query(ctx, cp.TunnelRouterAddress, calldata) if err != nil { - return false, fmt.Errorf("failed to query data: %w", err) + return nil, fmt.Errorf("failed to query data: %w", err) } - var output TunnelRouterIsActiveOutput - if err := cp.TunnelRouterABI.UnpackIntoInterface(&output, "isActive", b); err != nil { - return false, fmt.Errorf("failed to unpack data: %w", err) + var output TunnelInfoOutputRaw + if err := cp.TunnelRouterABI.UnpackIntoInterface(&output, "tunnelInfo", b); err != nil { + return nil, fmt.Errorf("failed to unpack data: %w", err) } - return output.IsActive, nil + return &output.Info, nil } // newRelayTx creates a new relay transaction. @@ -440,12 +441,12 @@ func (cp *EVMChainProvider) newRelayTx( } // createCalldata creates the calldata for the relay transaction. -func (cp *EVMChainProvider) createCalldata(task *types.RelayerTask) ([]byte, error) { +func (cp *EVMChainProvider) createCalldata(packet *bandtypes.Packet) ([]byte, error) { var signing *bandtypes.Signing - if task.Packet.IncomingGroupSigning != nil { - signing = task.Packet.IncomingGroupSigning - } else if task.Packet.CurrentGroupSigning != nil { - signing = task.Packet.CurrentGroupSigning + if packet.IncomingGroupSigning != nil { + signing = packet.IncomingGroupSigning + } else if packet.CurrentGroupSigning != nil { + signing = packet.CurrentGroupSigning } else { return nil, fmt.Errorf("missing signing") } diff --git a/relayer/chains/provider.go b/relayer/chains/provider.go index e0daaed..58d19b3 100644 --- a/relayer/chains/provider.go +++ b/relayer/chains/provider.go @@ -5,8 +5,8 @@ import ( "go.uber.org/zap" + bandtypes "github.com/bandprotocol/falcon/relayer/band/types" chainstypes "github.com/bandprotocol/falcon/relayer/chains/types" - "github.com/bandprotocol/falcon/relayer/types" ) // ChainProvider defines the interface for the chain interaction with the destination chain. @@ -22,7 +22,7 @@ type ChainProvider interface { ) (*chainstypes.Tunnel, error) // RelayPacket relays the packet from the source chain to the destination chain. - RelayPacket(ctx context.Context, task *types.RelayerTask) error + RelayPacket(ctx context.Context, packet *bandtypes.Packet) error } // BaseChainProvider is a base object for connecting with the chain network. diff --git a/relayer/chains/types/tunnel.go b/relayer/chains/types/tunnel.go index 6cf9c8e..aaddc76 100644 --- a/relayer/chains/types/tunnel.go +++ b/relayer/chains/types/tunnel.go @@ -1,10 +1,14 @@ package types +import "math/big" + // Tunnel defines the tunnel information on target chain. type Tunnel struct { - ID uint64 `json:"-"` - TargetAddress string `json:"-"` - IsActive bool `json:"is_active"` + ID uint64 `json:"-"` + TargetAddress string `json:"-"` + IsActive bool `json:"is_active"` + LatestSequence uint64 `json:"latest_sequence"` + Balance *big.Int `json:"balance"` } // NewTunnel creates a new tunnel object. diff --git a/relayer/tunnel_relayer.go b/relayer/tunnel_relayer.go index 1e725d2..41edda3 100644 --- a/relayer/tunnel_relayer.go +++ b/relayer/tunnel_relayer.go @@ -3,6 +3,7 @@ package relayer import ( "context" "encoding/hex" + "fmt" "time" "go.uber.org/zap" @@ -10,7 +11,6 @@ import ( "github.com/bandprotocol/falcon/relayer/band" bandtypes "github.com/bandprotocol/falcon/relayer/band/types" "github.com/bandprotocol/falcon/relayer/chains" - "github.com/bandprotocol/falcon/relayer/types" ) // TunnelRelayer is a relayer that listens to the tunnel and relays the packet @@ -43,23 +43,39 @@ func NewTunnelRelayer( } func (t *TunnelRelayer) CheckAndRelay(ctx context.Context) error { - // TODO: Check if there is any new packet to be relayed in BandChain - task, err := t.MockRelayerTask() + info, err := t.TargetChainProvider.QueryTunnelInfo(ctx, t.TunnelID, t.ContractAddress) + if err != nil { + return err + } + if !info.IsActive { + t.Log.Error("tunnel is not active on target chain", zap.Uint64("tunnel_id", t.TunnelID)) + return fmt.Errorf("tunnel is not active on target chain") + } + + nextSeq := info.LatestSequence + 1 + t.Log.Debug( + "querying packet information", + zap.Uint64("tunnel_id", t.TunnelID), + zap.Uint64("sequence", nextSeq), + ) + + packet, err := t.BandClient.GetTunnelPacket(ctx, t.TunnelID, nextSeq) if err != nil { t.Log.Error( - "failed to mock relayer task", + "failed to get packet", zap.Error(err), zap.Uint64("tunnel_id", t.TunnelID), + zap.Uint64("sequence", info.LatestSequence), ) return err } - if err := t.TargetChainProvider.RelayPacket(ctx, task); err != nil { + if err := t.TargetChainProvider.RelayPacket(ctx, packet); err != nil { t.Log.Error( "failed to relay packet", zap.Error(err), zap.Uint64("tunnel_id", t.TunnelID), - zap.Uint64("sequence", task.Packet.Sequence), + zap.Uint64("sequence", packet.Sequence), ) return err } @@ -68,7 +84,7 @@ func (t *TunnelRelayer) CheckAndRelay(ctx context.Context) error { } // TODO: remove this after the implementation is done -func (t *TunnelRelayer) MockRelayerTask() (*types.RelayerTask, error) { +func (t *TunnelRelayer) MockRelayerTask() (*bandtypes.Packet, error) { msgHex := "0E1AC2C4A50A82AA49717691FC1AE2E5FA68EFF45BD8576B0F2BE7A0850FA7C6" + "78512D24E95216DC140F557181A03631715A023424CBAD94601F3546CDFC3DE4" + "78512D24E95216DC140F557181A03631715A023424CBAD94601F3546CDFC3DE4" + @@ -106,16 +122,14 @@ func (t *TunnelRelayer) MockRelayerTask() (*types.RelayerTask, error) { return nil, err } - return &types.RelayerTask{ - Packet: &bandtypes.Packet{ - TunnelID: t.TunnelID, - Sequence: uint64(2), - IncomingGroupSigning: &bandtypes.Signing{ - Message: msg, - EVMSignature: &bandtypes.EVMSignature{ - RAddress: rAddr, - Signature: signature, - }, + return &bandtypes.Packet{ + TunnelID: t.TunnelID, + Sequence: uint64(2), + IncomingGroupSigning: &bandtypes.Signing{ + Message: msg, + EVMSignature: &bandtypes.EVMSignature{ + RAddress: rAddr, + Signature: signature, }, }, }, nil diff --git a/relayer/types/relayer_task.go b/relayer/types/relayer_task.go deleted file mode 100644 index 12d1421..0000000 --- a/relayer/types/relayer_task.go +++ /dev/null @@ -1,20 +0,0 @@ -package types - -import bandtypes "github.com/bandprotocol/falcon/relayer/band/types" - -// RelayerTask defines a task for the relayer. -type RelayerTask struct { - Tunnel *bandtypes.Tunnel - Packet *bandtypes.Packet -} - -// NewTssMessage creates a new TSS message object. -func NewRelayerTask( - tunnel *bandtypes.Tunnel, - packet *bandtypes.Packet, -) RelayerTask { - return RelayerTask{ - Tunnel: tunnel, - Packet: packet, - } -}