From 2c07f05ab9f74980e53b994c2734bfd046619249 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 22 Aug 2023 07:42:47 +0545 Subject: [PATCH 01/61] fix: add missing mutex in query proof --- relayer/chains/wasm/query.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 44176237f..c12228f17 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -334,12 +334,12 @@ func (ap *WasmProvider) QueryClientConsensusState(ctx context.Context, chainHeig } func (ap *WasmProvider) QueryIBCHandlerContract(ctx context.Context, param wasmtypes.RawContractMessage) (*wasmtypes.QuerySmartContractStateResponse, error) { - done := ap.SetSDKContext() - defer done() + done := ap.SetSDKContext() + defer done() return ap.QueryClient.SmartContractState(ctx, &wasmtypes.QuerySmartContractStateRequest{ - Address: ap.PCfg.IbcHandlerAddress, - QueryData: param, - }) + Address: ap.PCfg.IbcHandlerAddress, + QueryData: param, + }) } func (ap *WasmProvider) QueryIBCHandlerContractProcessed(ctx context.Context, param wasmtypes.RawContractMessage) ([]byte, error) { @@ -492,6 +492,8 @@ func (ap *WasmProvider) QueryConnection(ctx context.Context, height int64, conne } func (ap *WasmProvider) QueryWasmProof(ctx context.Context, storageKey []byte, height int64) ([]byte, error) { + done := ap.SetSDKContext() + done() ibcAddr, err := sdk.AccAddressFromBech32(ap.PCfg.IbcHandlerAddress) if err != nil { return nil, err From 244d363e90787b9ca6348c4d4853c6d0b2b2972a Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 22 Aug 2023 07:43:20 +0545 Subject: [PATCH 02/61] chore: add retry logic in wasm query method --- relayer/chains/wasm/query.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index c12228f17..33e59f49b 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -11,6 +11,7 @@ import ( "time" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/avast/retry-go/v4" abci "github.com/cometbft/cometbft/abci/types" rpcclient "github.com/cometbft/cometbft/rpc/client" tmtypes "github.com/cometbft/cometbft/types" @@ -19,6 +20,7 @@ import ( "github.com/cosmos/gogoproto/proto" tmclient "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" "github.com/icon-project/IBC-Integration/libraries/go/common/icon" + "go.uber.org/zap" querytypes "github.com/cosmos/cosmos-sdk/types/query" bankTypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -333,13 +335,25 @@ func (ap *WasmProvider) QueryClientConsensusState(ctx context.Context, chainHeig return clienttypes.NewQueryConsensusStateResponse(anyConsensusState, nil, clienttypes.NewHeight(0, uint64(chainHeight))), nil } -func (ap *WasmProvider) QueryIBCHandlerContract(ctx context.Context, param wasmtypes.RawContractMessage) (*wasmtypes.QuerySmartContractStateResponse, error) { +func (ap *WasmProvider) QueryIBCHandlerContract(ctx context.Context, param wasmtypes.RawContractMessage) (op *wasmtypes.QuerySmartContractStateResponse, err error) { + return op, retry.Do(func() error { done := ap.SetSDKContext() defer done() - return ap.QueryClient.SmartContractState(ctx, &wasmtypes.QuerySmartContractStateRequest{ + op, err = ap.QueryClient.SmartContractState(ctx, &wasmtypes.QuerySmartContractStateRequest{ Address: ap.PCfg.IbcHandlerAddress, QueryData: param, }) + return err + }, retry.Context(ctx), retry.Attempts(latestHeightQueryRetries), retry.Delay(50*time.Millisecond), retry.LastErrorOnly(true), retry.OnRetry(func(n uint, err error) { + ap.log.Error( + "Failed to query", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", latestHeightQueryRetries), + zap.Any("Param", param), + zap.Error(err), + ) + })) + } func (ap *WasmProvider) QueryIBCHandlerContractProcessed(ctx context.Context, param wasmtypes.RawContractMessage) ([]byte, error) { From fb281b4503ede6c3bb5c31d58b0139681560cf0c Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 22 Aug 2023 07:44:18 +0545 Subject: [PATCH 03/61] fix: add delay for pathprocessor sync --- relayer/chains/icon/icon_chain_processor.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/relayer/chains/icon/icon_chain_processor.go b/relayer/chains/icon/icon_chain_processor.go index 514e201f9..51b5dba00 100644 --- a/relayer/chains/icon/icon_chain_processor.go +++ b/relayer/chains/icon/icon_chain_processor.go @@ -285,7 +285,6 @@ func (icp *IconChainProcessor) monitoring(ctx context.Context, persistence *quer return err } } - // } icp.log.Info("Start to query from height", zap.Int64("height", processedheight)) // subscribe to monitor block @@ -297,7 +296,7 @@ func (icp *IconChainProcessor) monitoring(ctx context.Context, persistence *quer icp.firstTime = true blockReq := &types.BlockRequest{ - Height: types.NewHexInt(int64(icp.chainProvider.PCfg.StartHeight)), + Height: types.NewHexInt(int64(icp.StartFromHeight(ctx))), EventFilters: GetMonitorEventFilters(icp.chainProvider.PCfg.IbcHandlerAddress), } @@ -379,6 +378,9 @@ loop: break } time.Sleep(10 * time.Millisecond) + if icp.firstTime { + time.Sleep(4000 * time.Millisecond) + } icp.firstTime = false if br = nil; len(btpBlockRespCh) > 0 { br = <-btpBlockRespCh @@ -400,7 +402,7 @@ loop: if err != nil { return err } else if height != processedheight+i { - icp.log.Warn("Reconnect: missing block notification ", + icp.log.Warn("Reconnect: missing block notification", zap.Int64("got", height), zap.Int64("expected", processedheight+i), ) @@ -697,6 +699,7 @@ func (icp *IconChainProcessor) clientState(ctx context.Context, clientID string) if state, ok := icp.latestClientState[clientID]; ok { return state, nil } + cs, err := icp.chainProvider.QueryClientStateWithoutProof(ctx, int64(icp.latestBlock.Height), clientID) if err != nil { return provider.ClientState{}, err From 5c72d1923a4f631660dc0adf35e30e60bc796aeb Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 22 Aug 2023 07:45:05 +0545 Subject: [PATCH 04/61] fix: remove tp when getting client state --- relayer/chains/wasm/wasm_chain_processor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/chains/wasm/wasm_chain_processor.go b/relayer/chains/wasm/wasm_chain_processor.go index 172185bc6..d6165899d 100644 --- a/relayer/chains/wasm/wasm_chain_processor.go +++ b/relayer/chains/wasm/wasm_chain_processor.go @@ -176,7 +176,7 @@ func (ccp *WasmChainProcessor) nodeStatusWithRetry(ctx context.Context) (status // clientState will return the most recent client state if client messages // have already been observed for the clientID, otherwise it will query for it. func (ccp *WasmChainProcessor) clientState(ctx context.Context, clientID string) (provider.ClientState, error) { - if state, ok := ccp.latestClientState[clientID]; ok && state.TrustingPeriod > 0 { + if state, ok := ccp.latestClientState[clientID]; ok { return state, nil } cs, err := ccp.chainProvider.QueryClientState(ctx, int64(ccp.latestBlock.Height), clientID) From df20a84ed92872fbc65cd43cc1ee0b5b6c2dd1da Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 22 Aug 2023 10:16:49 +0545 Subject: [PATCH 05/61] fix: adding defer in queryWasmProof --- relayer/chains/wasm/query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 33e59f49b..87cf03b3a 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -507,7 +507,7 @@ func (ap *WasmProvider) QueryConnection(ctx context.Context, height int64, conne func (ap *WasmProvider) QueryWasmProof(ctx context.Context, storageKey []byte, height int64) ([]byte, error) { done := ap.SetSDKContext() - done() + defer done() ibcAddr, err := sdk.AccAddressFromBech32(ap.PCfg.IbcHandlerAddress) if err != nil { return nil, err From afbcf3033230560599ab7ece93cd3ca29da2bd3b Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 22 Aug 2023 10:51:48 +0545 Subject: [PATCH 06/61] fix: change to processheight --- relayer/chains/icon/icon_chain_processor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/chains/icon/icon_chain_processor.go b/relayer/chains/icon/icon_chain_processor.go index 51b5dba00..e8f6a1e72 100644 --- a/relayer/chains/icon/icon_chain_processor.go +++ b/relayer/chains/icon/icon_chain_processor.go @@ -296,7 +296,7 @@ func (icp *IconChainProcessor) monitoring(ctx context.Context, persistence *quer icp.firstTime = true blockReq := &types.BlockRequest{ - Height: types.NewHexInt(int64(icp.StartFromHeight(ctx))), + Height: types.NewHexInt(int64(processedheight)), EventFilters: GetMonitorEventFilters(icp.chainProvider.PCfg.IbcHandlerAddress), } From f581195f56a0c9a5d9c07dbc78970dcc3ee4ae3e Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 22 Aug 2023 11:04:26 +0545 Subject: [PATCH 07/61] fix: limit max block fetch at a time in wasm processor --- relayer/chains/icon/provider.go | 2 +- relayer/chains/wasm/wasm_chain_processor.go | 12 ++++++++++-- relayer/common/const.go | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/relayer/chains/icon/provider.go b/relayer/chains/icon/provider.go index 9d1ad4508..031453455 100644 --- a/relayer/chains/icon/provider.go +++ b/relayer/chains/icon/provider.go @@ -225,7 +225,7 @@ func (icp *IconProvider) NewClientState( return nil, fmt.Errorf("Blockinterval cannot be empty in Icon config") } - trustingBlockPeriod := uint64(dstTrustingPeriod) / (icp.PCfg.BlockInterval * uint64(common.NanosecondRatio)) + trustingBlockPeriod := uint64(dstTrustingPeriod) / (icp.PCfg.BlockInterval * uint64(common.NanoToMilliRatio)) return &icon.ClientState{ // In case of Icon: Trusting Period is block Difference // see: light.proto in ibc-integration diff --git a/relayer/chains/wasm/wasm_chain_processor.go b/relayer/chains/wasm/wasm_chain_processor.go index d6165899d..883099d87 100644 --- a/relayer/chains/wasm/wasm_chain_processor.go +++ b/relayer/chains/wasm/wasm_chain_processor.go @@ -90,6 +90,7 @@ const ( defaultMinQueryLoopDuration = 1 * time.Second defaultBalanceUpdateWaitDuration = 60 * time.Second inSyncNumBlocksThreshold = 2 + MaxBlockFetch = 100 ) // latestClientState is a map of clientID to the latest clientInfo for that client. @@ -221,7 +222,7 @@ func (ccp *WasmChainProcessor) StartFromHeight(ctx context.Context) int { func (ccp *WasmChainProcessor) Run(ctx context.Context, initialBlockHistory uint64) error { // this will be used for persistence across query cycle loop executions persistence := queryCyclePersistence{ - minQueryLoopDuration: time.Duration(ccp.chainProvider.PCfg.BlockInterval * uint64(common.NanosecondRatio)), + minQueryLoopDuration: time.Duration(ccp.chainProvider.PCfg.BlockInterval * uint64(common.NanoToMilliRatio)), lastBalanceUpdate: time.Unix(0, 0), balanceUpdateWaitDuration: defaultBalanceUpdateWaitDuration, } @@ -410,7 +411,14 @@ func (ccp *WasmChainProcessor) queryCycle(ctx context.Context, persistence *quer chainID := ccp.chainProvider.ChainId() var latestHeader provider.IBCHeader - for i := persistence.latestQueriedBlock + 1; i <= persistence.latestHeight; i++ { + syncUpHeight := func() int64 { + if persistence.latestHeight-persistence.latestQueriedBlock > MaxBlockFetch { + return persistence.latestQueriedBlock + MaxBlockFetch + } + return persistence.latestHeight + } + + for i := persistence.latestQueriedBlock + 1; i <= syncUpHeight(); i++ { var eg errgroup.Group var blockRes *ctypes.ResultBlockResults var lightBlock *types.LightBlock diff --git a/relayer/common/const.go b/relayer/common/const.go index 596e9630b..55dee1afc 100644 --- a/relayer/common/const.go +++ b/relayer/common/const.go @@ -15,7 +15,7 @@ var ( ConnectionKey = "connection" ChannelKey = "channel" ONE_HOUR = 60 * 60 * 1000 - NanosecondRatio = 1000_000 + NanoToMilliRatio = 1000_000 ) var ( From a2b9187b4989000b046cafc8722a16bfdf97cd0f Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 23 Aug 2023 10:46:58 +0545 Subject: [PATCH 08/61] fix: btp block update miss --- relayer/chains/icon/icon_chain_processor.go | 1 - relayer/chains/icon/provider_test.go | 4 +- relayer/chains/wasm/tx.go | 2 - relayer/chains/wasm/wasm_chain_processor.go | 1 + relayer/processor/message_processor.go | 67 +++++++++++--------- relayer/processor/path_end_runtime.go | 13 ++-- relayer/processor/path_processor_internal.go | 46 ++++++++++++++ relayer/processor/types.go | 46 ++++++++++++++ relayer/processor/utils.go | 4 ++ 9 files changed, 143 insertions(+), 41 deletions(-) diff --git a/relayer/chains/icon/icon_chain_processor.go b/relayer/chains/icon/icon_chain_processor.go index e8f6a1e72..ceba82f72 100644 --- a/relayer/chains/icon/icon_chain_processor.go +++ b/relayer/chains/icon/icon_chain_processor.go @@ -657,7 +657,6 @@ func (icp *IconChainProcessor) handleBTPBlockRequest( } request.response.Header = NewIconIBCHeader(btpHeader, validators, int64(btpHeader.MainHeight)) request.response.IsProcessed = processed - } func (icp *IconChainProcessor) handlePathProcessorUpdate(ctx context.Context, diff --git a/relayer/chains/icon/provider_test.go b/relayer/chains/icon/provider_test.go index 7544bc7df..c52e7e83a 100644 --- a/relayer/chains/icon/provider_test.go +++ b/relayer/chains/icon/provider_test.go @@ -475,5 +475,5 @@ func TestHash(t *testing.T) { // isValid, err := VerifyBtpProof(decision, signedHeader.Signatures, proofContext) // assert.NoError(t, err) -// assert.True(t, isValid) -// } +// assert.True(t, isValid) +// } diff --git a/relayer/chains/wasm/tx.go b/relayer/chains/wasm/tx.go index 00692f19b..f1bdafdf6 100644 --- a/relayer/chains/wasm/tx.go +++ b/relayer/chains/wasm/tx.go @@ -1262,8 +1262,6 @@ func (cc *WasmProvider) QueryABCI(ctx context.Context, req abci.RequestQuery) (a func (cc *WasmProvider) handleAccountSequenceMismatchError(err error) { clientCtx := cc.ClientContext() - fmt.Println("client context is ", clientCtx.GetFromAddress()) - _, seq, err := cc.ClientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, clientCtx.GetFromAddress()) // sequences := numRegex.FindAllString(err.Error(), -1) diff --git a/relayer/chains/wasm/wasm_chain_processor.go b/relayer/chains/wasm/wasm_chain_processor.go index 883099d87..8cccfb723 100644 --- a/relayer/chains/wasm/wasm_chain_processor.go +++ b/relayer/chains/wasm/wasm_chain_processor.go @@ -123,6 +123,7 @@ func (l latestClientState) update(ctx context.Context, clientInfo clientInfo, cc // update latest if no existing state or provided consensus height is newer l[clientInfo.clientID] = clientState + } // Provider returns the ChainProvider, which provides the methods for querying, assembling IBC messages, and sending transactions. diff --git a/relayer/processor/message_processor.go b/relayer/processor/message_processor.go index 63102b95f..4ad75921a 100644 --- a/relayer/processor/message_processor.go +++ b/relayer/processor/message_processor.go @@ -104,26 +104,18 @@ func (mp *messageProcessor) processMessages( // Otherwise, it will be attempted if either 2/3 of the trusting period // or the configured client update threshold duration has passed. func (mp *messageProcessor) shouldUpdateClientNow(ctx context.Context, src, dst *pathEndRuntime) (bool, error) { - var err error // handle if dst is IconLightClient if IsBTPLightClient(dst.clientState) { - - // if the latestblock is less than clientState height - if dst.clientState.ConsensusHeight.RevisionHeight >= src.latestBlock.Height { + if src.BTPHeightQueue.Size() == 0 { return false, nil } - header, found := src.ibcHeaderCache[src.latestBlock.Height] - if !found { - header, err = src.chainProvider.QueryIBCHeader(ctx, int64(src.latestBlock.Height)) - if err != nil { - return false, err - } - } - if header.IsCompleteBlock() { - return true, nil + btpHeightInfo := src.BTPHeightQueue.MustGetQueue() + + if btpHeightInfo.IsProcessing { + return false, nil } - return false, nil + return true, nil } // for lightClient other than ICON this will be helpful @@ -313,15 +305,25 @@ func (mp *messageProcessor) handleMsgUpdateClientForIcon(ctx context.Context, sr clientID := dst.info.ClientID latestConsensusHeight := dst.clientState.ConsensusHeight + if src.BTPHeightQueue.Size() == 0 { + return nil + } + btpHeightInfo := src.BTPHeightQueue.MustGetQueue() + if !shouldUpdate { return nil } - if !src.latestHeader.IsCompleteBlock() { + header, err := src.chainProvider.QueryIBCHeader(ctx, btpHeightInfo.Height) + if err != nil { + return fmt.Errorf("Failed to query header for height %d", btpHeightInfo.Height) + } + + if !header.IsCompleteBlock() { return fmt.Errorf("Should Update is true but the Header is incomplete") } - if src.latestHeader.Height() <= latestConsensusHeight.RevisionHeight { + if header.Height() <= latestConsensusHeight.RevisionHeight { mp.log.Debug("Src latest header is less then latest client State", zap.String("chain-id", src.info.ChainID), zap.Int64("latest-header-height", int64(src.latestHeader.Height())), @@ -331,7 +333,7 @@ func (mp *messageProcessor) handleMsgUpdateClientForIcon(ctx context.Context, sr } msgUpdateClientHeader, err := src.chainProvider.MsgUpdateClientHeader( - src.latestHeader, + header, latestConsensusHeight, dst.clientTrustedState.IBCHeader, ) @@ -348,18 +350,6 @@ func (mp *messageProcessor) handleMsgUpdateClientForIcon(ctx context.Context, sr return nil } -func (mp *messageProcessor) findNextIBCHeader(ctx context.Context, src, dst *pathEndRuntime) (provider.IBCHeader, error) { - clientConsensusHeight := dst.clientState.ConsensusHeight - if IsBTPLightClient(dst.clientState) { - header, found := nextIconIBCHeader(src.ibcHeaderCache.Clone(), dst.lastClientUpdateHeight) - if !found { - return nil, fmt.Errorf("unable to find Icon IBC header for Next height of %d ", clientConsensusHeight.RevisionHeight) - } - return header, nil - } - return src.chainProvider.QueryIBCHeader(ctx, int64(clientConsensusHeight.RevisionHeight+1)) -} - // trackAndSendMessages will increment attempt counters for each message and send each message. // Messages will be batched if the broadcast mode is configured to 'batch' and there was not an error // in a previous batch. @@ -414,10 +404,27 @@ func (mp *messageProcessor) sendClientUpdate( dst.lastClientUpdateHeightMu.Lock() dst.lastClientUpdateHeight = dst.latestBlock.Height dst.lastClientUpdateHeightMu.Unlock() + // if IsBTPLightClient(dst.clientState) { + // dst.lastClientUpdateHeightMu.Lock() + // dst.lastClientUpdateHeight = uint64(dst.BTPHeightQueue.MustGetQueue().Height) + // dst.lastClientUpdateHeightMu.Unlock() + // } msgs := []provider.RelayerMessage{mp.msgUpdateClient} - if err := dst.chainProvider.SendMessagesToMempool(broadcastCtx, msgs, mp.memo, ctx, nil); err != nil { + callback := func(rtr *provider.RelayerTxResponse, err error) { + + if IsBTPLightClient(dst.clientState) { + if rtr.Code == 0 { + src.BTPHeightQueue.Dequeue() + return + } + NewBlockInfoHeightQueue().MustGetQueue() + src.BTPHeightQueue.ReplaceQueue(0, BlockInfoHeight{Height: int64(dst.lastClientUpdateHeight), IsProcessing: false}) + } + } + + if err := dst.chainProvider.SendMessagesToMempool(broadcastCtx, msgs, mp.memo, ctx, callback); err != nil { mp.log.Error("Error sending client update message", zap.String("path_name", src.info.PathName), zap.String("src_chain_id", src.info.ChainID), diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index c81e2c19f..39601f781 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -54,7 +54,8 @@ type pathEndRuntime struct { lastClientUpdateHeight uint64 lastClientUpdateHeightMu sync.Mutex - metrics *PrometheusMetrics + metrics *PrometheusMetrics + BTPHeightQueue *Queue[BlockInfoHeight] } func newPathEndRuntime(log *zap.Logger, pathEnd PathEnd, metrics *PrometheusMetrics) *pathEndRuntime { @@ -76,6 +77,7 @@ func newPathEndRuntime(log *zap.Logger, pathEnd PathEnd, metrics *PrometheusMetr clientICQProcessing: make(clientICQProcessingCache), connSubscribers: make(map[string][]func(provider.ConnectionInfo)), metrics: metrics, + BTPHeightQueue: NewBlockInfoHeightQueue(), } } @@ -385,15 +387,14 @@ func (pathEnd *pathEndRuntime) mergeCacheData(ctx context.Context, cancel func() pathEnd.latestBlock = d.LatestBlock pathEnd.latestBlockMu.Unlock() - if d.IsGenesis { - pathEnd.lastClientUpdateHeightMu.Lock() - pathEnd.lastClientUpdateHeight = d.LatestBlock.Height - pathEnd.lastClientUpdateHeightMu.Unlock() - } pathEnd.inSync = d.InSync pathEnd.latestHeader = d.LatestHeader pathEnd.clientState = d.ClientState + if pathEnd.chainProvider.Type() == common.IconModule && d.LatestHeader.IsCompleteBlock() { + pathEnd.BTPHeightQueue.Enqueue(BlockInfoHeight{Height: int64(d.LatestHeader.Height()), IsProcessing: false}) + } + terminate, err := pathEnd.checkForMisbehaviour(ctx, pathEnd.clientState, counterParty) if err != nil { pathEnd.log.Error( diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index b5c55cd73..20cbc7a44 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -8,6 +8,7 @@ import ( "sort" "sync" + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" conntypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" @@ -938,6 +939,10 @@ func (pp *PathProcessor) processLatestMessages(ctx context.Context, cancel func( pp.updateClientTrustedState(pp.pathEnd1, pp.pathEnd2) pp.updateClientTrustedState(pp.pathEnd2, pp.pathEnd1) + //for btp updateClient steps + pp.UpdateBTPHeight(ctx, pp.pathEnd1, pp.pathEnd2) + pp.UpdateBTPHeight(ctx, pp.pathEnd2, pp.pathEnd1) + channelPairs := pp.channelPairs() pp.queuePreInitMessages(cancel) @@ -1542,3 +1547,44 @@ func (pp *PathProcessor) shouldTerminateForFlushComplete() bool { pp.log.Info("Found termination condition for flush, all caches cleared") return true } + +func (pp *PathProcessor) UpdateBTPHeight(ctx context.Context, src *pathEndRuntime, dst *pathEndRuntime) { + srcIsIcon := src.chainProvider.Type() == common.IconModule + dstIsBtpClient := IsBTPLightClient(dst.clientState) + + fmt.Println(dst.clientState.ConsensusHeight.RevisionHeight) + + if !srcIsIcon && !dstIsBtpClient { + return + } + + if srcIsIcon && !dstIsBtpClient || !srcIsIcon && dstIsBtpClient { + pp.log.Error("Src Icon module mismatch with dst btp client", + zap.String("Src Chain Type ", src.chainProvider.Type()), + zap.String("Dst client Id", dst.clientState.ClientID), + ) + return + } + + if src.BTPHeightQueue.Size() == 0 { + return + } + for src.BTPHeightQueue.Size() > 0 { + btpHeightInfo := src.BTPHeightQueue.MustGetQueue() + + if dst.clientState.ConsensusHeight.RevisionHeight < uint64(btpHeightInfo.Height) { + break + } + if dst.clientState.ConsensusHeight.RevisionHeight == uint64(btpHeightInfo.Height) { + src.BTPHeightQueue.Dequeue() + continue + } + if dst.clientState.ConsensusHeight.RevisionHeight > uint64(btpHeightInfo.Height) { + cs, err := dst.chainProvider.QueryClientConsensusState(ctx, int64(dst.latestBlock.Height), dst.clientState.ClientID, clienttypes.NewHeight(0, uint64(btpHeightInfo.Height))) + if err == nil && cs != nil { + // removing latest height element + src.BTPHeightQueue.Dequeue() + } + } + } +} diff --git a/relayer/processor/types.go b/relayer/processor/types.go index 331c6a70f..df13a5c0a 100644 --- a/relayer/processor/types.go +++ b/relayer/processor/types.go @@ -592,3 +592,49 @@ func ConnectionInfoConnectionKey(info provider.ConnectionInfo) ConnectionKey { CounterpartyConnID: info.CounterpartyConnID, } } + +type BlockInfoHeight struct { + Height int64 + IsProcessing bool +} + +type Queue[T any] struct { + items []T +} + +func (q *Queue[T]) Enqueue(item T) { + q.items = append(q.items, item) +} + +func (q *Queue[T]) MustGetQueue() T { + if q.Size() == 0 { + var element T + return element + } + item := q.items[0] + return item +} + +func (q *Queue[T]) ReplaceQueue(index int, element T) { + if q.Size() > index { + q.items[index] = element + } +} + +func (q *Queue[T]) Dequeue() (T, error) { + if q.Size() == 0 { + var element T + return element, fmt.Errorf("all element dequed") + } + item := q.items[0] + q.items = q.items[1:] + return item, nil +} + +func (q *Queue[T]) Size() int { + return len(q.items) +} + +func NewBlockInfoHeightQueue() *Queue[BlockInfoHeight] { + return &Queue[BlockInfoHeight]{} +} diff --git a/relayer/processor/utils.go b/relayer/processor/utils.go index 21f1d038a..1837546f9 100644 --- a/relayer/processor/utils.go +++ b/relayer/processor/utils.go @@ -53,3 +53,7 @@ func nextIconIBCHeader(heightMap IBCHeaderCache, height uint64) (provider.IBCHea header, ok := heightMap[nextHeight] return header, ok } + +func FindConsensusHeightFromEventLog([]provider.RelayerEvent) int64 { + return 0 +} From 9c3d3bd2b990bba6e0c0f1a561a678c8d05e085a Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 23 Aug 2023 11:12:09 +0545 Subject: [PATCH 09/61] fix:add values --- relayer/processor/message_processor.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/relayer/processor/message_processor.go b/relayer/processor/message_processor.go index 4ad75921a..ae0a0f1f8 100644 --- a/relayer/processor/message_processor.go +++ b/relayer/processor/message_processor.go @@ -404,11 +404,11 @@ func (mp *messageProcessor) sendClientUpdate( dst.lastClientUpdateHeightMu.Lock() dst.lastClientUpdateHeight = dst.latestBlock.Height dst.lastClientUpdateHeightMu.Unlock() - // if IsBTPLightClient(dst.clientState) { - // dst.lastClientUpdateHeightMu.Lock() - // dst.lastClientUpdateHeight = uint64(dst.BTPHeightQueue.MustGetQueue().Height) - // dst.lastClientUpdateHeightMu.Unlock() - // } + if IsBTPLightClient(dst.clientState) { + dst.lastClientUpdateHeightMu.Lock() + dst.lastClientUpdateHeight = uint64(dst.BTPHeightQueue.MustGetQueue().Height) + dst.lastClientUpdateHeightMu.Unlock() + } msgs := []provider.RelayerMessage{mp.msgUpdateClient} @@ -419,8 +419,11 @@ func (mp *messageProcessor) sendClientUpdate( src.BTPHeightQueue.Dequeue() return } - NewBlockInfoHeightQueue().MustGetQueue() - src.BTPHeightQueue.ReplaceQueue(0, BlockInfoHeight{Height: int64(dst.lastClientUpdateHeight), IsProcessing: false}) + + blockHeightInfo := NewBlockInfoHeightQueue().MustGetQueue() + if blockHeightInfo.Height == int64(dst.lastClientUpdateHeight) { + src.BTPHeightQueue.ReplaceQueue(0, BlockInfoHeight{Height: int64(dst.lastClientUpdateHeight), IsProcessing: false}) + } } } From 4660bc8dcaaec7a285dd95ed31ae3b9ada87581b Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 23 Aug 2023 11:19:43 +0545 Subject: [PATCH 10/61] fix: the logic --- relayer/processor/message_processor.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/relayer/processor/message_processor.go b/relayer/processor/message_processor.go index ae0a0f1f8..35a4986ec 100644 --- a/relayer/processor/message_processor.go +++ b/relayer/processor/message_processor.go @@ -415,12 +415,17 @@ func (mp *messageProcessor) sendClientUpdate( callback := func(rtr *provider.RelayerTxResponse, err error) { if IsBTPLightClient(dst.clientState) { + if dst.BTPHeightQueue.Size() == 0 { + return + } + blockHeightInfo := dst.BTPHeightQueue.MustGetQueue() if rtr.Code == 0 { - src.BTPHeightQueue.Dequeue() + if blockHeightInfo.Height == int64(dst.lastClientUpdateHeight) { + src.BTPHeightQueue.Dequeue() + } return } - - blockHeightInfo := NewBlockInfoHeightQueue().MustGetQueue() + // this would represent a failure case in that case isProcessing should be false if blockHeightInfo.Height == int64(dst.lastClientUpdateHeight) { src.BTPHeightQueue.ReplaceQueue(0, BlockInfoHeight{Height: int64(dst.lastClientUpdateHeight), IsProcessing: false}) } From 95396e6c4104171f63ddc378f77e05da06ac4768 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 23 Aug 2023 20:11:41 +0545 Subject: [PATCH 11/61] fix: queue logic --- relayer/chains/icon/icon_chain_processor.go | 3 -- relayer/chains/wasm/query.go | 37 +++++++------ relayer/chains/wasm/tx.go | 28 +++++----- relayer/processor/message_processor.go | 56 ++++++++++++++++---- relayer/processor/path_end_runtime.go | 1 + relayer/processor/path_processor_internal.go | 5 +- relayer/processor/types.go | 30 +++++++++-- 7 files changed, 107 insertions(+), 53 deletions(-) diff --git a/relayer/chains/icon/icon_chain_processor.go b/relayer/chains/icon/icon_chain_processor.go index ceba82f72..4feaaa9a6 100644 --- a/relayer/chains/icon/icon_chain_processor.go +++ b/relayer/chains/icon/icon_chain_processor.go @@ -378,9 +378,6 @@ loop: break } time.Sleep(10 * time.Millisecond) - if icp.firstTime { - time.Sleep(4000 * time.Millisecond) - } icp.firstTime = false if br = nil; len(btpBlockRespCh) > 0 { br = <-btpBlockRespCh diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 87cf03b3a..b10bc8533 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -11,7 +11,6 @@ import ( "time" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/avast/retry-go/v4" abci "github.com/cometbft/cometbft/abci/types" rpcclient "github.com/cometbft/cometbft/rpc/client" tmtypes "github.com/cometbft/cometbft/types" @@ -20,7 +19,6 @@ import ( "github.com/cosmos/gogoproto/proto" tmclient "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" "github.com/icon-project/IBC-Integration/libraries/go/common/icon" - "go.uber.org/zap" querytypes "github.com/cosmos/cosmos-sdk/types/query" bankTypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -336,23 +334,24 @@ func (ap *WasmProvider) QueryClientConsensusState(ctx context.Context, chainHeig } func (ap *WasmProvider) QueryIBCHandlerContract(ctx context.Context, param wasmtypes.RawContractMessage) (op *wasmtypes.QuerySmartContractStateResponse, err error) { - return op, retry.Do(func() error { - done := ap.SetSDKContext() - defer done() - op, err = ap.QueryClient.SmartContractState(ctx, &wasmtypes.QuerySmartContractStateRequest{ - Address: ap.PCfg.IbcHandlerAddress, - QueryData: param, - }) - return err - }, retry.Context(ctx), retry.Attempts(latestHeightQueryRetries), retry.Delay(50*time.Millisecond), retry.LastErrorOnly(true), retry.OnRetry(func(n uint, err error) { - ap.log.Error( - "Failed to query", - zap.Uint("attempt", n+1), - zap.Uint("max_attempts", latestHeightQueryRetries), - zap.Any("Param", param), - zap.Error(err), - ) - })) + done := ap.SetSDKContext() + defer done() + return ap.QueryClient.SmartContractState(ctx, &wasmtypes.QuerySmartContractStateRequest{ + Address: ap.PCfg.IbcHandlerAddress, + QueryData: param, + }) + // return op, retry.Do(func() error { + // op, err = + // return err + // }, retry.Context(ctx), retry.Attempts(latestHeightQueryRetries), retry.Delay(50*time.Millisecond), retry.LastErrorOnly(true), retry.OnRetry(func(n uint, err error) { + // ap.log.Error( + // "Failed to query", + // zap.Uint("attempt", n+1), + // zap.Uint("max_attempts", latestHeightQueryRetries), + // zap.Any("Param", param), + // zap.Error(err), + // ) + // })) } diff --git a/relayer/chains/wasm/tx.go b/relayer/chains/wasm/tx.go index f1bdafdf6..64b34dfca 100644 --- a/relayer/chains/wasm/tx.go +++ b/relayer/chains/wasm/tx.go @@ -744,20 +744,20 @@ func (ap *WasmProvider) SendMessagesToMempool( return err } - if msg.Type() == MethodUpdateClient { - if err := retry.Do(func() error { - if err := ap.BroadcastTx(cliCtx, txBytes, []provider.RelayerMessage{msg}, asyncCtx, defaultBroadcastWaitTimeout, asyncCallback, true); err != nil { - if strings.Contains(err.Error(), sdkerrors.ErrWrongSequence.Error()) { - ap.handleAccountSequenceMismatchError(err) - } - } - return err - }, retry.Context(ctx), rtyAtt, retry.Delay(time.Millisecond*time.Duration(ap.PCfg.BlockInterval)), rtyErr); err != nil { - ap.log.Error("Failed to update client", zap.Any("Message", msg)) - return err - } - continue - } + // if msg.Type() == MethodUpdateClient { + // if err := retry.Do(func() error { + // if err := ap.BroadcastTx(cliCtx, txBytes, []provider.RelayerMessage{msg}, asyncCtx, defaultBroadcastWaitTimeout, asyncCallback, true); err != nil { + // if strings.Contains(err.Error(), sdkerrors.ErrWrongSequence.Error()) { + // ap.handleAccountSequenceMismatchError(err) + // } + // } + // return err + // }, retry.Context(ctx), rtyAtt, retry.Delay(time.Millisecond*time.Duration(ap.PCfg.BlockInterval)), rtyErr); err != nil { + // ap.log.Error("Failed to update client", zap.Any("Message", msg)) + // return err + // } + // continue + // } if err := ap.BroadcastTx(cliCtx, txBytes, []provider.RelayerMessage{msg}, asyncCtx, defaultBroadcastWaitTimeout, asyncCallback, false); err != nil { if strings.Contains(err.Error(), sdkerrors.ErrWrongSequence.Error()) { ap.handleAccountSequenceMismatchError(err) diff --git a/relayer/processor/message_processor.go b/relayer/processor/message_processor.go index 35a4986ec..da2673ab6 100644 --- a/relayer/processor/message_processor.go +++ b/relayer/processor/message_processor.go @@ -109,8 +109,10 @@ func (mp *messageProcessor) shouldUpdateClientNow(ctx context.Context, src, dst if src.BTPHeightQueue.Size() == 0 { return false, nil } - - btpHeightInfo := src.BTPHeightQueue.MustGetQueue() + btpHeightInfo, err := src.BTPHeightQueue.GetQueue() + if err != nil { + return false, nil + } if btpHeightInfo.IsProcessing { return false, nil @@ -308,7 +310,10 @@ func (mp *messageProcessor) handleMsgUpdateClientForIcon(ctx context.Context, sr if src.BTPHeightQueue.Size() == 0 { return nil } - btpHeightInfo := src.BTPHeightQueue.MustGetQueue() + btpHeightInfo, err := src.BTPHeightQueue.GetQueue() + if err != nil { + return nil + } if !shouldUpdate { return nil @@ -401,12 +406,24 @@ func (mp *messageProcessor) sendClientUpdate( dst.log.Debug("Will relay client update") - dst.lastClientUpdateHeightMu.Lock() - dst.lastClientUpdateHeight = dst.latestBlock.Height - dst.lastClientUpdateHeightMu.Unlock() if IsBTPLightClient(dst.clientState) { + blockInfoHeight, err := src.BTPHeightQueue.GetQueue() + if err != nil { + mp.log.Debug("No message in the queue", zap.Error(err)) + return + } dst.lastClientUpdateHeightMu.Lock() - dst.lastClientUpdateHeight = uint64(dst.BTPHeightQueue.MustGetQueue().Height) + dst.lastClientUpdateHeight = uint64(blockInfoHeight.Height) + dst.lastClientUpdateHeightMu.Unlock() + src.BTPHeightQueue.ReplaceQueue(zeroIndex, BlockInfoHeight{ + Height: int64(blockInfoHeight.Height), + IsProcessing: true, + RetryCount: blockInfoHeight.RetryCount + 1, + }) + + } else { + dst.lastClientUpdateHeightMu.Lock() + dst.lastClientUpdateHeight = dst.latestBlock.Height dst.lastClientUpdateHeightMu.Unlock() } @@ -414,11 +431,19 @@ func (mp *messageProcessor) sendClientUpdate( callback := func(rtr *provider.RelayerTxResponse, err error) { + mp.log.Debug("Executing callback of sendClientUpdate ", + zap.Any("Transaction Status", rtr.Code), + zap.Any("Response", rtr), + zap.Any("LastClientUpdateHeight", dst.lastClientUpdateHeight)) + if IsBTPLightClient(dst.clientState) { - if dst.BTPHeightQueue.Size() == 0 { + if src.BTPHeightQueue.Size() == 0 { + return + } + blockHeightInfo, err := src.BTPHeightQueue.GetQueue() + if err != nil { return } - blockHeightInfo := dst.BTPHeightQueue.MustGetQueue() if rtr.Code == 0 { if blockHeightInfo.Height == int64(dst.lastClientUpdateHeight) { src.BTPHeightQueue.Dequeue() @@ -427,7 +452,18 @@ func (mp *messageProcessor) sendClientUpdate( } // this would represent a failure case in that case isProcessing should be false if blockHeightInfo.Height == int64(dst.lastClientUpdateHeight) { - src.BTPHeightQueue.ReplaceQueue(0, BlockInfoHeight{Height: int64(dst.lastClientUpdateHeight), IsProcessing: false}) + if blockHeightInfo.RetryCount >= 5 { + // removing btpBLock update + src.BTPHeightQueue.Dequeue() + return + } + + src.BTPHeightQueue.ReplaceQueue(zeroIndex, BlockInfoHeight{ + Height: int64(dst.lastClientUpdateHeight), + IsProcessing: false, + RetryCount: blockHeightInfo.RetryCount + 1, + }) + } } } diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index 39601f781..9226d171c 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -451,6 +451,7 @@ func (pathEnd *pathEndRuntime) shouldSendPacketMessage(message packetIBCMessage, pathEndForHeight = pathEnd } + // should be setCounterparty because of this message is generated in response to TimeoutRequest packet if eventType == chantypes.EventTypeTimeoutPacket && IsBTPLightClient(pathEnd.clientState) { pathEndForHeight = counterparty } diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index 20cbc7a44..5cc49a470 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1552,8 +1552,6 @@ func (pp *PathProcessor) UpdateBTPHeight(ctx context.Context, src *pathEndRuntim srcIsIcon := src.chainProvider.Type() == common.IconModule dstIsBtpClient := IsBTPLightClient(dst.clientState) - fmt.Println(dst.clientState.ConsensusHeight.RevisionHeight) - if !srcIsIcon && !dstIsBtpClient { return } @@ -1569,7 +1567,8 @@ func (pp *PathProcessor) UpdateBTPHeight(ctx context.Context, src *pathEndRuntim if src.BTPHeightQueue.Size() == 0 { return } - for src.BTPHeightQueue.Size() > 0 { + size := src.BTPHeightQueue.Size() + for i := 0; i < size; i++ { btpHeightInfo := src.BTPHeightQueue.MustGetQueue() if dst.clientState.ConsensusHeight.RevisionHeight < uint64(btpHeightInfo.Height) { diff --git a/relayer/processor/types.go b/relayer/processor/types.go index df13a5c0a..9ff5d62e4 100644 --- a/relayer/processor/types.go +++ b/relayer/processor/types.go @@ -3,6 +3,7 @@ package processor import ( "fmt" "sort" + "sync" chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" "github.com/cosmos/relayer/v2/relayer/common" @@ -596,10 +597,12 @@ func ConnectionInfoConnectionKey(info provider.ConnectionInfo) ConnectionKey { type BlockInfoHeight struct { Height int64 IsProcessing bool + RetryCount int64 } type Queue[T any] struct { - items []T + items []T + itemMu *sync.Mutex } func (q *Queue[T]) Enqueue(item T) { @@ -608,20 +611,36 @@ func (q *Queue[T]) Enqueue(item T) { func (q *Queue[T]) MustGetQueue() T { if q.Size() == 0 { - var element T - return element + panic("the size of queue is zero") } item := q.items[0] return item } +func (q *Queue[T]) GetQueue() (T, error) { + + if q.Size() == 0 { + var element T + return element, fmt.Errorf("The queue is of empty length") + } + item := q.items[0] + return item, nil + +} + +var ( + zeroIndex = 0 +) + func (q *Queue[T]) ReplaceQueue(index int, element T) { + if q.Size() > index { q.items[index] = element } } func (q *Queue[T]) Dequeue() (T, error) { + if q.Size() == 0 { var element T return element, fmt.Errorf("all element dequed") @@ -636,5 +655,8 @@ func (q *Queue[T]) Size() int { } func NewBlockInfoHeightQueue() *Queue[BlockInfoHeight] { - return &Queue[BlockInfoHeight]{} + return &Queue[BlockInfoHeight]{ + items: make([]BlockInfoHeight, 0), + itemMu: &sync.Mutex{}, + } } From 6b8db31ff4b57204cd47be43be60d6158cce08b0 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 23 Aug 2023 20:21:10 +0545 Subject: [PATCH 12/61] fix:refractor --- relayer/processor/path_end_runtime.go | 3 ++- relayer/processor/types.go | 38 +++++++++++++++++---------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index 9226d171c..26cfd01f1 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -55,7 +55,7 @@ type pathEndRuntime struct { lastClientUpdateHeightMu sync.Mutex metrics *PrometheusMetrics - BTPHeightQueue *Queue[BlockInfoHeight] + BTPHeightQueue Queue[BlockInfoHeight] } func newPathEndRuntime(log *zap.Logger, pathEnd PathEnd, metrics *PrometheusMetrics) *pathEndRuntime { @@ -476,6 +476,7 @@ func (pathEnd *pathEndRuntime) shouldSendPacketMessage(message packetIBCMessage, ) return false } + } if !pathEnd.channelStateCache[k] { diff --git a/relayer/processor/types.go b/relayer/processor/types.go index 9ff5d62e4..d9a4b647a 100644 --- a/relayer/processor/types.go +++ b/relayer/processor/types.go @@ -11,6 +11,10 @@ import ( "go.uber.org/zap/zapcore" ) +var ( + zeroIndex = 0 +) + // MessageLifecycle is used to send an initial IBC message to a chain // once the chains are in sync for the PathProcessor. // It also allows setting a stop condition for the PathProcessor. @@ -594,22 +598,33 @@ func ConnectionInfoConnectionKey(info provider.ConnectionInfo) ConnectionKey { } } +// binaryTree + +type Queue[T any] interface { + Enqueue(item T) + Dequeue() (T, error) + MustGetQueue() T + GetQueue() (T, error) + ReplaceQueue(index int, item T) + Size() int +} + type BlockInfoHeight struct { Height int64 IsProcessing bool RetryCount int64 } -type Queue[T any] struct { +type ArrayQueue[T any] struct { items []T itemMu *sync.Mutex } -func (q *Queue[T]) Enqueue(item T) { +func (q *ArrayQueue[T]) Enqueue(item T) { q.items = append(q.items, item) } -func (q *Queue[T]) MustGetQueue() T { +func (q *ArrayQueue[T]) MustGetQueue() T { if q.Size() == 0 { panic("the size of queue is zero") } @@ -617,7 +632,7 @@ func (q *Queue[T]) MustGetQueue() T { return item } -func (q *Queue[T]) GetQueue() (T, error) { +func (q *ArrayQueue[T]) GetQueue() (T, error) { if q.Size() == 0 { var element T @@ -628,18 +643,13 @@ func (q *Queue[T]) GetQueue() (T, error) { } -var ( - zeroIndex = 0 -) - -func (q *Queue[T]) ReplaceQueue(index int, element T) { - +func (q *ArrayQueue[T]) ReplaceQueue(index int, element T) { if q.Size() > index { q.items[index] = element } } -func (q *Queue[T]) Dequeue() (T, error) { +func (q *ArrayQueue[T]) Dequeue() (T, error) { if q.Size() == 0 { var element T @@ -650,12 +660,12 @@ func (q *Queue[T]) Dequeue() (T, error) { return item, nil } -func (q *Queue[T]) Size() int { +func (q *ArrayQueue[T]) Size() int { return len(q.items) } -func NewBlockInfoHeightQueue() *Queue[BlockInfoHeight] { - return &Queue[BlockInfoHeight]{ +func NewBlockInfoHeightQueue() *ArrayQueue[BlockInfoHeight] { + return &ArrayQueue[BlockInfoHeight]{ items: make([]BlockInfoHeight, 0), itemMu: &sync.Mutex{}, } From 5145d20a1bf30370317825d650d65efccc975e4d Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 23 Aug 2023 21:18:55 +0545 Subject: [PATCH 13/61] fix: implement mutex in queue --- relayer/processor/path_end_runtime.go | 9 ++++- relayer/processor/types.go | 54 +++++++++++++++++++++------ 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index 26cfd01f1..0a0ef7cb2 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -77,7 +77,7 @@ func newPathEndRuntime(log *zap.Logger, pathEnd PathEnd, metrics *PrometheusMetr clientICQProcessing: make(clientICQProcessingCache), connSubscribers: make(map[string][]func(provider.ConnectionInfo)), metrics: metrics, - BTPHeightQueue: NewBlockInfoHeightQueue(), + BTPHeightQueue: NewBlockInfoHeightQueue[BlockInfoHeight](), } } @@ -477,6 +477,13 @@ func (pathEnd *pathEndRuntime) shouldSendPacketMessage(message packetIBCMessage, return false } + if counterparty.BTPHeightQueue.ItemExist(message.info.Height) { + pathEnd.log.Debug("Waiting to relay packet message until clientState is in queue", + zap.Inline(message), + zap.String("event_type", eventType), + ) + return false + } } if !pathEnd.channelStateCache[k] { diff --git a/relayer/processor/types.go b/relayer/processor/types.go index d9a4b647a..f32a636d3 100644 --- a/relayer/processor/types.go +++ b/relayer/processor/types.go @@ -598,42 +598,69 @@ func ConnectionInfoConnectionKey(info provider.ConnectionInfo) ConnectionKey { } } -// binaryTree - type Queue[T any] interface { Enqueue(item T) Dequeue() (T, error) MustGetQueue() T GetQueue() (T, error) + ItemExist(interface{}) bool ReplaceQueue(index int, item T) Size() int } +type ExistenceChecker interface { + Exists(target interface{}) bool +} + type BlockInfoHeight struct { Height int64 IsProcessing bool RetryCount int64 } -type ArrayQueue[T any] struct { - items []T - itemMu *sync.Mutex +func (bi BlockInfoHeight) Exists(target interface{}) bool { + if height, ok := target.(int64); ok { + return bi.Height == height + } + return false +} + +type ArrayQueue[T ExistenceChecker] struct { + items []T + mu *sync.Mutex } func (q *ArrayQueue[T]) Enqueue(item T) { + q.mu.Lock() + defer q.mu.Unlock() q.items = append(q.items, item) } func (q *ArrayQueue[T]) MustGetQueue() T { + q.mu.Lock() + defer q.mu.Unlock() if q.Size() == 0 { panic("the size of queue is zero") } + item := q.items[0] return item } -func (q *ArrayQueue[T]) GetQueue() (T, error) { +func (q *ArrayQueue[T]) ItemExist(target interface{}) bool { + q.mu.Lock() + defer q.mu.Unlock() + for _, item := range q.items { + if item.Exists(target) { + return true + } + } + return false +} +func (q *ArrayQueue[T]) GetQueue() (T, error) { + q.mu.Lock() + defer q.mu.Unlock() if q.Size() == 0 { var element T return element, fmt.Errorf("The queue is of empty length") @@ -644,13 +671,16 @@ func (q *ArrayQueue[T]) GetQueue() (T, error) { } func (q *ArrayQueue[T]) ReplaceQueue(index int, element T) { - if q.Size() > index { + q.mu.Lock() + defer q.mu.Unlock() + if index >= 0 && index < len(q.items) { q.items[index] = element } } func (q *ArrayQueue[T]) Dequeue() (T, error) { - + q.mu.Lock() + defer q.mu.Unlock() if q.Size() == 0 { var element T return element, fmt.Errorf("all element dequed") @@ -664,9 +694,9 @@ func (q *ArrayQueue[T]) Size() int { return len(q.items) } -func NewBlockInfoHeightQueue() *ArrayQueue[BlockInfoHeight] { - return &ArrayQueue[BlockInfoHeight]{ - items: make([]BlockInfoHeight, 0), - itemMu: &sync.Mutex{}, +func NewBlockInfoHeightQueue[T ExistenceChecker]() *ArrayQueue[T] { + return &ArrayQueue[T]{ + items: make([]T, 0), + mu: &sync.Mutex{}, } } From 87a9477e55809dff3770bc919a79d7a9939ffd1a Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Thu, 24 Aug 2023 12:39:14 +0545 Subject: [PATCH 14/61] fix: add prevconsensusstateheight method and use it to fetch trusted height --- relayer/chains/cosmos/query.go | 6 ++++ relayer/chains/icon/query.go | 5 +++ relayer/chains/penumbra/query.go | 5 +++ relayer/chains/wasm/query.go | 21 +++++++++++++ relayer/chains/wasm/types/types.go | 32 +++++++++++++++----- relayer/processor/message_processor.go | 17 ++++++++--- relayer/processor/path_end_runtime.go | 2 +- relayer/processor/path_processor_internal.go | 6 ++-- relayer/provider/provider.go | 2 +- 9 files changed, 80 insertions(+), 16 deletions(-) diff --git a/relayer/chains/cosmos/query.go b/relayer/chains/cosmos/query.go index 6e438727f..5e03ed3c6 100644 --- a/relayer/chains/cosmos/query.go +++ b/relayer/chains/cosmos/query.go @@ -28,6 +28,7 @@ import ( chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types" host "github.com/cosmos/ibc-go/v7/modules/core/24-host" + "github.com/cosmos/ibc-go/v7/modules/core/exported" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" tmclient "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" "github.com/cosmos/relayer/v2/relayer/provider" @@ -1169,3 +1170,8 @@ func (cc *CosmosProvider) QueryConsensusStateABCI(ctx context.Context, clientID ProofHeight: proofHeight, }, nil } + +func (ap *CosmosProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, chainHeight int64, clientId string, clientHeight int64) (exported.Height, error) { + panic("QueryClientPrevConsensusStateHeight not implemented") + +} diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index ce6b892f1..6d1668a5e 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -12,6 +12,7 @@ import ( "github.com/avast/retry-go/v4" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/gogoproto/proto" + "github.com/cosmos/ibc-go/v7/modules/core/exported" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" "github.com/pkg/errors" "go.uber.org/zap" @@ -837,6 +838,10 @@ func (icp *IconProvider) QueryIconProof(ctx context.Context, height int64, keyHa return nil, nil } +func (ip *IconProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, chainHeight int64, clientId string, clientHeight int64) (exported.Height, error) { + panic("QueryClientPrevConsensusStateHeight not implemented") +} + func (icp *IconProvider) HexStringToProtoUnmarshal(encoded string, v proto.Message) ([]byte, error) { if encoded == "" { return nil, fmt.Errorf("Encoded string is empty ") diff --git a/relayer/chains/penumbra/query.go b/relayer/chains/penumbra/query.go index da651ef93..e20a64889 100644 --- a/relayer/chains/penumbra/query.go +++ b/relayer/chains/penumbra/query.go @@ -25,6 +25,7 @@ import ( chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types" host "github.com/cosmos/ibc-go/v7/modules/core/24-host" + "github.com/cosmos/ibc-go/v7/modules/core/exported" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" tmclient "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" "github.com/cosmos/relayer/v2/relayer/provider" @@ -983,3 +984,7 @@ func (cc *PenumbraProvider) QueryICQWithProof(ctx context.Context, msgType strin //TODO implement me panic("implement me") } + +func (cc *PenumbraProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, chainHeight int64, clientId string, clientHeight int64) (exported.Height, error) { + panic("QueryClientPrevConsensusStateHeight not implemented") +} diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index b10bc8533..e7d48d495 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -27,6 +27,7 @@ import ( conntypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types" + "github.com/cosmos/ibc-go/v7/modules/core/exported" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" "github.com/cosmos/relayer/v2/relayer/chains/wasm/types" @@ -858,3 +859,23 @@ func (ap *WasmProvider) QueryDenomTraces(ctx context.Context, offset, limit uint } return transfers, nil } + +func (ap *WasmProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, chainHeight int64, clientId string, clientHeight int64) (exported.Height, error) { + param, err := types.NewPrevConsensusStateHeight(clientId, uint64(clientHeight)).Bytes() + res, err := ap.QueryIBCHandlerContract(ctx, param) + if err != nil { + return nil, err + } + + var heights []int64 + err = json.Unmarshal(res.Data.Bytes(), &heights) + + if err != nil { + return nil, err + } + + if len(heights) == 0 { + return nil, fmt.Errorf("consensus state of client %s before %d", clientId, clientHeight) + } + return clienttypes.Height{RevisionNumber: 0, RevisionHeight: uint64(heights[0])}, nil +} diff --git a/relayer/chains/wasm/types/types.go b/relayer/chains/wasm/types/types.go index b0826d463..f6085a42c 100644 --- a/relayer/chains/wasm/types/types.go +++ b/relayer/chains/wasm/types/types.go @@ -71,11 +71,13 @@ func NewClientState(clientId string) *GetClientState { } } +type ConsensusStateByHeight struct { + ClientId string "json:\"client_id\"" + Height uint64 "json:\"height\"" +} + type GetConsensusStateByHeight struct { - ConsensusStateByHeight struct { - ClientId string "json:\"client_id\"" - Height uint64 "json:\"height\"" - } `json:"get_consensus_state_by_height"` + ConsensusStateByHeight ConsensusStateByHeight `json:"get_consensus_state_by_height"` } func (x *GetConsensusStateByHeight) Bytes() ([]byte, error) { @@ -84,10 +86,7 @@ func (x *GetConsensusStateByHeight) Bytes() ([]byte, error) { func NewConsensusStateByHeight(clientId string, height uint64) *GetConsensusStateByHeight { return &GetConsensusStateByHeight{ - ConsensusStateByHeight: struct { - ClientId string "json:\"client_id\"" - Height uint64 "json:\"height\"" - }{ + ConsensusStateByHeight: ConsensusStateByHeight{ ClientId: clientId, Height: height, }, @@ -353,3 +352,20 @@ func NewCommitmentPrefix() *GetCommitmentPrefix { GetCommitment: struct{}{}, } } + +type GetPrevConsensusStateHeight struct { + ConsensusStateByHeight ConsensusStateByHeight `json:"get_previous_consensus_state_height"` +} + +func (x *GetPrevConsensusStateHeight) Bytes() ([]byte, error) { + return json.Marshal(x) +} + +func NewPrevConsensusStateHeight(clientId string, height uint64) *GetPrevConsensusStateHeight { + return &GetPrevConsensusStateHeight{ + ConsensusStateByHeight: ConsensusStateByHeight{ + ClientId: clientId, + Height: height, + }, + } +} diff --git a/relayer/processor/message_processor.go b/relayer/processor/message_processor.go index da2673ab6..44ff7a9ab 100644 --- a/relayer/processor/message_processor.go +++ b/relayer/processor/message_processor.go @@ -8,6 +8,7 @@ import ( "sync" "time" + "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" "github.com/cosmos/relayer/v2/relayer/provider" "go.uber.org/zap" @@ -229,7 +230,7 @@ func (mp *messageProcessor) assembleMessage( func (mp *messageProcessor) assembleMsgUpdateClient(ctx context.Context, src, dst *pathEndRuntime, shouldUpdate bool) error { if IsBTPLightClient(dst.clientState) { - err := mp.handleMsgUpdateClientForIcon(ctx, src, dst, shouldUpdate) + err := mp.handleMsgUpdateClientForBTPClient(ctx, src, dst, shouldUpdate) return err } @@ -302,7 +303,7 @@ func (mp *messageProcessor) assembleMsgUpdateClient(ctx context.Context, src, ds return nil } -func (mp *messageProcessor) handleMsgUpdateClientForIcon(ctx context.Context, src, dst *pathEndRuntime, shouldUpdate bool) error { +func (mp *messageProcessor) handleMsgUpdateClientForBTPClient(ctx context.Context, src, dst *pathEndRuntime, shouldUpdate bool) error { clientID := dst.info.ClientID latestConsensusHeight := dst.clientState.ConsensusHeight @@ -332,15 +333,23 @@ func (mp *messageProcessor) handleMsgUpdateClientForIcon(ctx context.Context, sr mp.log.Debug("Src latest header is less then latest client State", zap.String("chain-id", src.info.ChainID), zap.Int64("latest-header-height", int64(src.latestHeader.Height())), + zap.Int64("message processing btp-height", int64(src.latestHeader.Height())), zap.Int64("client-state-height", int64(latestConsensusHeight.RevisionHeight))) - return nil + height, err := dst.chainProvider.QueryClientPrevConsensusStateHeight(ctx, int64(dst.latestBlock.Height), dst.clientState.ClientID, int64(header.Height())) + if err != nil { + return fmt.Errorf("Failed to query prevClientConsensusState") + } + latestConsensusHeight = types.Height{ + RevisionNumber: height.GetRevisionNumber(), + RevisionHeight: height.GetRevisionHeight(), + } } msgUpdateClientHeader, err := src.chainProvider.MsgUpdateClientHeader( header, latestConsensusHeight, - dst.clientTrustedState.IBCHeader, + nil, ) if err != nil { return fmt.Errorf("error assembling new client header: %w", err) diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index 0a0ef7cb2..c134ab8bf 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -476,8 +476,8 @@ func (pathEnd *pathEndRuntime) shouldSendPacketMessage(message packetIBCMessage, ) return false } + if counterparty.BTPHeightQueue.ItemExist(int64(message.info.Height)) { - if counterparty.BTPHeightQueue.ItemExist(message.info.Height) { pathEnd.log.Debug("Waiting to relay packet message until clientState is in queue", zap.Inline(message), zap.String("event_type", eventType), diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index 5cc49a470..8dd0c7f2f 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1569,8 +1569,10 @@ func (pp *PathProcessor) UpdateBTPHeight(ctx context.Context, src *pathEndRuntim } size := src.BTPHeightQueue.Size() for i := 0; i < size; i++ { - btpHeightInfo := src.BTPHeightQueue.MustGetQueue() - + btpHeightInfo, err := src.BTPHeightQueue.GetQueue() + if err != nil { + continue + } if dst.clientState.ConsensusHeight.RevisionHeight < uint64(btpHeightInfo.Height) { break } diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index a548eae24..94eb8be35 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -445,7 +445,7 @@ type QueryProvider interface { QueryUpgradedConsState(ctx context.Context, height int64) (*clienttypes.QueryConsensusStateResponse, error) QueryConsensusState(ctx context.Context, height int64) (ibcexported.ConsensusState, int64, error) QueryClients(ctx context.Context) (clienttypes.IdentifiedClientStates, error) - + QueryClientPrevConsensusStateHeight(ctx context.Context, chainHeight int64, clinetId string, clientHeight int64) (ibcexported.Height, error) // ics 03 - connection QueryConnection(ctx context.Context, height int64, connectionid string) (*conntypes.QueryConnectionResponse, error) QueryConnections(ctx context.Context) (conns []*conntypes.IdentifiedConnection, err error) From 68f825711a25e8715d47f9ca5a485bc61b05a070 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 9 Aug 2023 15:53:05 +0545 Subject: [PATCH 15/61] fix: add method missing receipt methods --- relayer/chains/icon/methods.go | 4 ++- relayer/chains/icon/query.go | 33 +++++++++++++++++++++++ relayer/chains/wasm/query.go | 43 +++++++++++++++++++++++++++++- relayer/chains/wasm/types/types.go | 36 +++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/relayer/chains/icon/methods.go b/relayer/chains/icon/methods.go index 50a4d65ca..8c2012bf1 100644 --- a/relayer/chains/icon/methods.go +++ b/relayer/chains/icon/methods.go @@ -42,5 +42,7 @@ const ( MethodRequestTimeout = "requestTimeout" MethodTimeoutPacket = "timeoutPacket" - MethodGetAllPorts = "getAllPorts" + MethodGetAllPorts = "getAllPorts" + MethodGetMissingPacketReceipts = "getMissingPacketReceipts" + MethodGetPacketHeights = "getpacketHeights" ) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 6d1668a5e..5f2b8749d 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -792,6 +792,39 @@ func (icp *IconProvider) QueryPacketReceipt(ctx context.Context, height int64, c }, nil } +func (icp *IconProvider) QueryMissingPacketReceipts(ctx context.Context, height int64, channelId string, portId string, startSeq int64, endSeq int64) ([]types.HexInt, error) { + + callParam := icp.prepareCallParams(MethodHasPacketReceipt, map[string]interface{}{ + "portId": portId, + "channelId": channelId, + "startSeq": types.NewHexInt(int64(startSeq)), + "endSeq": types.NewHexInt(int64(endSeq)), + }, callParamsWithHeight(types.NewHexInt(height))) + + var missingReceipts []types.HexInt + if err := icp.client.Call(callParam, &missingReceipts); err != nil { + return nil, err + } + + return missingReceipts, nil +} + +func (icp *IconProvider) QueryPacketHeights(ctx context.Context, height int64, channelId string, portId string, startSeq int64, endSeq int64) (map[types.HexInt]types.HexInt, error) { + + callParam := icp.prepareCallParams(MethodHasPacketReceipt, map[string]interface{}{ + "portId": portId, + "channelId": channelId, + "startSeq": types.NewHexInt(int64(startSeq)), + "endSeq": types.NewHexInt(int64(endSeq)), + }, callParamsWithHeight(types.NewHexInt(height))) + + var missingReceipts map[types.HexInt]types.HexInt + if err := icp.client.Call(callParam, &missingReceipts); err != nil { + return nil, err + } + return missingReceipts, nil +} + // ics 20 - transfer // not required for icon func (icp *IconProvider) QueryDenomTrace(ctx context.Context, denom string) (*transfertypes.DenomTrace, error) { diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index e7d48d495..f1aec503c 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -17,6 +17,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/gogoproto/proto" + "github.com/cosmos/ibc-go/v7/modules/core/exported" tmclient "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" "github.com/icon-project/IBC-Integration/libraries/go/common/icon" @@ -27,7 +28,6 @@ import ( conntypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types" - "github.com/cosmos/ibc-go/v7/modules/core/exported" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" "github.com/cosmos/relayer/v2/relayer/chains/wasm/types" @@ -879,3 +879,44 @@ func (ap *WasmProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, } return clienttypes.Height{RevisionNumber: 0, RevisionHeight: uint64(heights[0])}, nil } + +func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, height int64, channelId string, portId string, startSeq int64, endSeq int64) ([]int64, error) { + + callParams := types.NewPacketMissingReceiptParams(channelId, portId, startSeq, endSeq) + callParamsByte, err := json.Marshal(callParams) + if err != nil { + return nil, err + } + + result, err := ap.QueryIBCHandlerContract(ctx, callParamsByte) + if err != nil { + return nil, err + } + + var receipts []int64 + if err := json.Unmarshal(result.Data.Bytes(), &receipts); err != nil { + return nil, err + } + + return receipts, nil +} + +func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, height int64, channelId string, portId string, startSeq int64, endSeq int64) (map[int64]int64, error) { + + callParams := types.NewPacketHeightParams(channelId, portId, startSeq, endSeq) + callParamsBytes, err := json.Marshal(callParams) + if err != nil { + return nil, err + } + result, err := ap.QueryIBCHandlerContract(ctx, callParamsBytes) + if err != nil { + return nil, err + } + + var packetHeights map[int64]int64 + if err := json.Unmarshal(result.Data.Bytes(), &packetHeights); err != nil { + return nil, err + } + + return packetHeights, nil +} diff --git a/relayer/chains/wasm/types/types.go b/relayer/chains/wasm/types/types.go index f6085a42c..cd44fe502 100644 --- a/relayer/chains/wasm/types/types.go +++ b/relayer/chains/wasm/types/types.go @@ -369,3 +369,39 @@ func NewPrevConsensusStateHeight(clientId string, height uint64) *GetPrevConsens }, } } + +type RangeParams struct { + ChannelId string `json:"channel_id"` + PortId string `json:"port_id"` + StartSequence int64 `json:"start_sequence"` + EndSequence int64 `json:"end_sequence"` +} + +func NewRangeParams(channelId, portId string, startSequence, endSequence int64) RangeParams { + return RangeParams{ + ChannelId: channelId, + PortId: portId, + StartSequence: startSequence, + EndSequence: endSequence, + } +} + +type PacketMissingReceiptsParams struct { + GetMissingPacketReceipts RangeParams `json:"get_missing_packet_receipts"` +} + +func NewPacketMissingReceiptParams(channelId, portId string, startSequence, endSequence int64) PacketMissingReceiptsParams { + return PacketMissingReceiptsParams{ + GetMissingPacketReceipts: NewRangeParams(channelId, portId, startSequence, endSequence), + } +} + +type PacketHeightsParams struct { + GetPacketHeights RangeParams `json:"get_packet_heights"` +} + +func NewPacketHeightParams(channelId, portId string, startSequence, endSequence int64) PacketHeightsParams { + return PacketHeightsParams{ + GetPacketHeights: NewRangeParams(channelId, portId, startSequence, endSequence), + } +} From 2b90d8b3c1e88645a1c4754a5ca5bbbe2f02d802 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 10:13:34 +0545 Subject: [PATCH 16/61] build fix --- relayer/chains/wasm/query.go | 1 - 1 file changed, 1 deletion(-) diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 1a2a2034a..e6eb87580 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -18,7 +18,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/gogoproto/proto" - "github.com/cosmos/ibc-go/v7/modules/core/exported" tmclient "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" "github.com/icon-project/IBC-Integration/libraries/go/common/icon" "go.uber.org/zap" From ed33f7492557816c6cc0ae0c11602a1fb57ddeb2 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 15:18:29 +0545 Subject: [PATCH 17/61] feat: flush logic for contract based chains --- relayer/processor/path_processor.go | 5 +- relayer/processor/path_processor_internal.go | 345 +++++++++++++++++++ 2 files changed, 348 insertions(+), 2 deletions(-) diff --git a/relayer/processor/path_processor.go b/relayer/processor/path_processor.go index 5289f5a23..0dab40f8d 100644 --- a/relayer/processor/path_processor.go +++ b/relayer/processor/path_processor.go @@ -276,7 +276,8 @@ func (pp *PathProcessor) HandleNewData(chainID string, cacheData ChainProcessorC func (pp *PathProcessor) handleFlush(ctx context.Context) { flushTimer := pp.flushInterval - if err := pp.flush(ctx); err != nil { + + if err := pp.flushByCase(ctx); err != nil { pp.log.Warn("Flush not complete", zap.Error(err)) flushTimer = flushFailureRetry } @@ -339,7 +340,7 @@ func (pp *PathProcessor) Run(ctx context.Context, cancel func()) { } if pp.shouldFlush() && !pp.initialFlushComplete { - // pp.handleFlush(ctx) + pp.handleFlush(ctx) pp.initialFlushComplete = true } else if pp.shouldTerminateForFlushComplete() { cancel() diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index 8dd0c7f2f..057d1077f 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1589,3 +1589,348 @@ func (pp *PathProcessor) UpdateBTPHeight(ctx context.Context, src *pathEndRuntim } } } + +func (pp *PathProcessor) flushByCase(ctx context.Context) error { + mod1 := pp.pathEnd1.chainProvider.Type() + mod2 := pp.pathEnd2.chainProvider.Type() + if mod1 == common.IconModule && mod2 == common.WasmModule || mod1 == common.WasmModule && mod2 == common.WasmModule { + return pp.ibcContractBasedFlush(ctx) + } + return pp.flush(ctx) + +} + +// both source and dst chain is ibc implemented contracts +func (pp *PathProcessor) ibcContractBasedFlush(ctx context.Context) error { + + var ( + channelPacketheights1 = make(map[ChannelKey]provider.PacketHeightsInfo) + channelPacketheights2 = make(map[ChannelKey]provider.PacketHeightsInfo) + channelPacketheights1Mu, channelPacketheights2Mu sync.Mutex + + pathEnd1Cache = NewIBCMessagesCache() + pathEnd2Cache = NewIBCMessagesCache() + pathEnd1CacheMu, pathEnd2CacheMu sync.Mutex + ) + + // Query remaining packet commitments on both chains + var eg errgroup.Group + for k, open := range pp.pathEnd1.channelStateCache { + if !open { + continue + } + if !pp.pathEnd1.info.ShouldRelayChannel(ChainChannelKey{ + ChainID: pp.pathEnd1.info.ChainID, + CounterpartyChainID: pp.pathEnd2.info.ChainID, + ChannelKey: k, + }) { + continue + } + eg.Go(QueryPacketHeights(ctx, pp.pathEnd1, pp.pathEnd2, k, channelPacketheights1, &channelPacketheights1Mu)) + } + for k, open := range pp.pathEnd2.channelStateCache { + if !open { + continue + } + if !pp.pathEnd2.info.ShouldRelayChannel(ChainChannelKey{ + ChainID: pp.pathEnd2.info.ChainID, + CounterpartyChainID: pp.pathEnd1.info.ChainID, + ChannelKey: k, + }) { + continue + } + eg.Go(QueryPacketHeights(ctx, pp.pathEnd2, pp.pathEnd1, k, channelPacketheights2, &channelPacketheights2Mu)) + } + + if err := eg.Wait(); err != nil { + return fmt.Errorf("failed to query packet commitments: %w", err) + } + + skipped := false + for k, seqs := range channelPacketheights1 { + k := k + seqs := seqs + eg.Go(func() error { + done, err := pp.queuePendingRecvAndAcksByHeights(ctx, pp.pathEnd1, pp.pathEnd2, k, seqs, pathEnd1Cache.PacketFlow, pathEnd2Cache.PacketFlow, &pathEnd1CacheMu, &pathEnd2CacheMu) + if err != nil { + return err + } + if !done { + skipped = true + } + return nil + }) + } + + for k, seqs := range channelPacketheights2 { + k := k + seqs := seqs + eg.Go(func() error { + done, err := pp.queuePendingRecvAndAcksByHeights(ctx, pp.pathEnd2, pp.pathEnd1, k, seqs, pathEnd2Cache.PacketFlow, pathEnd1Cache.PacketFlow, &pathEnd2CacheMu, &pathEnd1CacheMu) + if err != nil { + return err + } + if !done { + skipped = true + } + return nil + }) + } + + if err := eg.Wait(); err != nil { + return fmt.Errorf("failed to enqueue pending messages for flush: %w", err) + } + + pp.pathEnd1.mergeMessageCache(pathEnd1Cache, pp.pathEnd2.info.ChainID, pp.pathEnd2.inSync) + pp.pathEnd2.mergeMessageCache(pathEnd2Cache, pp.pathEnd1.info.ChainID, pp.pathEnd1.inSync) + + if skipped { + return fmt.Errorf("flush was successful, but more packet sequences are still pending") + } + + return nil +} + +func QueryPacketHeights( + ctx context.Context, + src *pathEndRuntime, + dst *pathEndRuntime, + k ChannelKey, + packetHeights map[ChannelKey]provider.PacketHeightsInfo, + mu sync.Locker, +) func() error { + return func() error { + src.log.Debug("Flushing", zap.String("channel", k.ChannelID), zap.String("port", k.PortID)) + + endSeq, err := src.chainProvider.QueryNextSeqSend(ctx, int64(src.latestBlock.Height), k.ChannelID, k.PortID) + if err != nil { + return err + } + + startSeq := uint64(0) + if dst.clientState.TrustingPeriodBlock > 0 { + startSeq, err = src.chainProvider.QueryNextSeqSend(ctx, int64(src.latestBlock.Height)-dst.clientState.TrustingPeriodBlock, k.ChannelID, k.PortID) + if err != nil { + return err + } + } + + c, err := src.chainProvider.QueryPacketHeights(ctx, int64(src.latestBlock.Height), k.ChannelID, k.PortID, startSeq, endSeq) + if err != nil { + return err + } + mu.Lock() + defer mu.Unlock() + packetHeights[k] = provider.PacketHeightsInfo{ + PacketHeights: c, + StartSeq: startSeq, + EndSeq: endSeq, + } + return nil + } +} + +// queuePendingRecvAndAcks returns whether flush can be considered complete (none skipped). +func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( + ctx context.Context, + src, dst *pathEndRuntime, + k ChannelKey, + packetHeights provider.PacketHeightsInfo, + srcCache ChannelPacketMessagesCache, + dstCache ChannelPacketMessagesCache, + srcMu sync.Locker, + dstMu sync.Locker, +) (bool, error) { + + if len(packetHeights.PacketHeights) == 0 { + src.log.Debug("Nothing to flush", zap.String("channel", k.ChannelID), zap.String("port", k.PortID)) + return true, nil + } + + dstChan, dstPort := k.CounterpartyChannelID, k.CounterpartyPortID + + unrecv, err := dst.chainProvider.QueryMissingPacketReceipts(ctx, int64(dst.latestBlock.Height), dstChan, dstPort, packetHeights.StartSeq, packetHeights.EndSeq) + if err != nil { + return false, err + } + + dstHeight := int64(dst.latestBlock.Height) + + if len(unrecv) > 0 { + channel, err := dst.chainProvider.QueryChannel(ctx, dstHeight, dstChan, dstPort) + if err != nil { + return false, err + } + + if channel.Channel.Ordering == chantypes.ORDERED { + nextSeqRecv, err := dst.chainProvider.QueryNextSeqRecv(ctx, dstHeight, dstChan, dstPort) + if err != nil { + return false, err + } + + var newUnrecv []uint64 + + for _, seq := range unrecv { + if seq >= nextSeqRecv.NextSequenceReceive { + newUnrecv = append(newUnrecv, seq) + } + } + + unrecv = newUnrecv + + sort.SliceStable(unrecv, func(i, j int) bool { + return unrecv[i] < unrecv[j] + }) + } + } + + var eg errgroup.Group + + skipped := false + + for i, seq := range unrecv { + srcMu.Lock() + if srcCache.IsCached(chantypes.EventTypeSendPacket, k, seq) { + continue // already cached + } + srcMu.Unlock() + + if i >= maxPacketsPerFlush { + skipped = true + break + } + + // incase of BTPBlock SeqHeight+1 will have matching BTPMessage + seqHeight, ok := packetHeights.PacketHeights[seq] + seqHeight = seqHeight + if !ok { + continue + } + + src.log.Debug("Querying send packet", + zap.String("channel", k.ChannelID), + zap.String("port", k.PortID), + zap.Uint64("sequence", seq), + ) + + seq := seq + + eg.Go(func() error { + sendPacket, err := src.chainProvider.QuerySendPacketByHeight(ctx, k.ChannelID, k.PortID, seq, seqHeight) + if err != nil { + return err + } + srcMu.Lock() + srcCache.Cache(chantypes.EventTypeSendPacket, k, seq, sendPacket) + srcMu.Unlock() + + src.log.Debug("Cached send packet", + zap.String("channel", k.ChannelID), + zap.String("port", k.PortID), + zap.String("ctrpty_channel", k.CounterpartyChannelID), + zap.String("ctrpty_port", k.CounterpartyPortID), + zap.Uint64("sequence", seq), + ) + + return nil + }) + if IsBTPLightClient(dst.clientState) { + // the btpMessage will be present in seqHeight +1 , if not present need to insert btpBlockHeight to the btpBlockDataStructure + _, err := dst.chainProvider.QueryClientConsensusState(ctx, int64(dst.latestBlock.Height), dst.clientState.ClientID, clienttypes.NewHeight(0, seqHeight+1)) + // if err !=nil header may not be there in light client + // if btpHeight already submitted then will be discarded before submitting update client + if err != nil { + src.BTPHeightQueue.Enqueue(BlockInfoHeight{Height: int64(seqHeight) + 1, IsProcessing: false, RetryCount: 0}) + } + } + } + + if err := eg.Wait(); err != nil { + return false, err + } + + if len(unrecv) > 0 { + src.log.Debug("Will flush MsgRecvPacket", + zap.String("channel", k.ChannelID), + zap.String("port", k.PortID), + zap.Uint64s("sequences", unrecv), + ) + } else { + src.log.Debug("No MsgRecvPacket to flush", + zap.String("channel", k.ChannelID), + zap.String("port", k.PortID), + ) + } + + // TODO: for ackedMessage + // var unacked []uint64 + + // SeqLoop: + // for _, seq := range seqs { + // for _, unrecvSeq := range unrecv { + // if seq == unrecvSeq { + // continue SeqLoop + // } + // } + // // does not exist in unrecv, so this is an ack that must be written + // unacked = append(unacked, seq) + // } + + // for i, seq := range unacked { + // dstMu.Lock() + // ck := k.Counterparty() + // if dstCache.IsCached(chantypes.EventTypeRecvPacket, ck, seq) && + // dstCache.IsCached(chantypes.EventTypeWriteAck, ck, seq) { + // continue // already cached + // } + // dstMu.Unlock() + + // if i >= maxPacketsPerFlush { + // skipped = true + // break + // } + + // seq := seq + + // dst.log.Debug("Querying recv packet", + // zap.String("channel", k.CounterpartyChannelID), + // zap.String("port", k.CounterpartyPortID), + // zap.Uint64("sequence", seq), + // ) + + // eg.Go(func() error { + // recvPacket, err := dst.chainProvider.QueryRecvPacket(ctx, k.CounterpartyChannelID, k.CounterpartyPortID, seq) + // if err != nil { + // return err + // } + + // ck := k.Counterparty() + // dstMu.Lock() + // dstCache.Cache(chantypes.EventTypeRecvPacket, ck, seq, recvPacket) + // dstCache.Cache(chantypes.EventTypeWriteAck, ck, seq, recvPacket) + // dstMu.Unlock() + + // return nil + // }) + // } + + // if err := eg.Wait(); err != nil { + // return false, err + // } + + // if len(unacked) > 0 { + // dst.log.Debug( + // "Will flush MsgAcknowledgement", + // zap.Object("channel", k), + // zap.Uint64s("sequences", unacked), + // ) + // } else { + // dst.log.Debug( + // "No MsgAcknowledgement to flush", + // zap.String("channel", k.CounterpartyChannelID), + // zap.String("port", k.CounterpartyPortID), + // ) + // } + + return !skipped, nil +} From aed90fe7089c1a21dc3329f3edd5b1dc9bc4ad1c Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 15:19:05 +0545 Subject: [PATCH 18/61] feat: add query method in chain provider for flush logic --- relayer/provider/provider.go | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 94eb8be35..0c31d9ce7 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -69,11 +69,12 @@ type IBCHeader interface { // ClientState holds the current state of a client from a single chain's perspective type ClientState struct { - ClientID string - ConsensusHeight clienttypes.Height - TrustingPeriod time.Duration // trustring period wont be there in ICON client state - ConsensusTime time.Time // consensus time wont be there in ICON light client State - Header []byte // + ClientID string + ConsensusHeight clienttypes.Height + TrustingPeriod time.Duration // trustring period wont be there in ICON client state + ConsensusTime time.Time // consensus time wont be there in ICON light client State + Header []byte // + TrustingPeriodBlock int64 } // ClientTrustedState holds the current state of a client from the perspective of both involved chains, @@ -217,6 +218,14 @@ func (r RelayerTxResponse) MarshalLogObject(enc zapcore.ObjectEncoder) error { return nil } +type PacketHeights map[uint64]uint64 + +type PacketHeightsInfo struct { + PacketHeights PacketHeights + StartSeq uint64 + EndSeq uint64 +} + type KeyProvider interface { CreateKeystore(path string) error KeystoreCreated(path string) bool @@ -429,6 +438,7 @@ type QueryProvider interface { // query packet info for sequence QuerySendPacket(ctx context.Context, srcChanID, srcPortID string, sequence uint64) (PacketInfo, error) QueryRecvPacket(ctx context.Context, dstChanID, dstPortID string, sequence uint64) (PacketInfo, error) + QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (PacketInfo, error) // bank QueryBalance(ctx context.Context, keyName string) (sdk.Coins, error) @@ -467,6 +477,9 @@ type QueryProvider interface { QueryPacketCommitment(ctx context.Context, height int64, channelid, portid string, seq uint64) (comRes *chantypes.QueryPacketCommitmentResponse, err error) QueryPacketAcknowledgement(ctx context.Context, height int64, channelid, portid string, seq uint64) (ackRes *chantypes.QueryPacketAcknowledgementResponse, err error) QueryPacketReceipt(ctx context.Context, height int64, channelid, portid string, seq uint64) (recRes *chantypes.QueryPacketReceiptResponse, err error) + QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights PacketHeights, err error) + QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) + QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) // ics 20 - transfer QueryDenomTrace(ctx context.Context, denom string) (*transfertypes.DenomTrace, error) From 544277ebe7e6c2b1cf2784d307f799b39fcd0c78 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 15:19:55 +0545 Subject: [PATCH 19/61] feat: implement additional query method in cosmos & penumber --- relayer/chains/cosmos/query.go | 12 ++++++++++++ relayer/chains/penumbra/query.go | 13 +++++++++++++ relayer/common/const.go | 1 - 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/relayer/chains/cosmos/query.go b/relayer/chains/cosmos/query.go index 5e03ed3c6..52c8795a6 100644 --- a/relayer/chains/cosmos/query.go +++ b/relayer/chains/cosmos/query.go @@ -1173,5 +1173,17 @@ func (cc *CosmosProvider) QueryConsensusStateABCI(ctx context.Context, clientID func (ap *CosmosProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, chainHeight int64, clientId string, clientHeight int64) (exported.Height, error) { panic("QueryClientPrevConsensusStateHeight not implemented") +} +func (ap *CosmosProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { + panic("QuerySendPacketByHeight not implemented") +} +func (ap *CosmosProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.PacketHeights, err error) { + panic("QueryPacketHeights not implemented") +} +func (ap *CosmosProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) { + panic("QueryMissingPacketReceipts not implemented") +} +func (ap *CosmosProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { + panic("QueryNextSeqSend not implemented") } diff --git a/relayer/chains/penumbra/query.go b/relayer/chains/penumbra/query.go index e20a64889..7281f29b4 100644 --- a/relayer/chains/penumbra/query.go +++ b/relayer/chains/penumbra/query.go @@ -988,3 +988,16 @@ func (cc *PenumbraProvider) QueryICQWithProof(ctx context.Context, msgType strin func (cc *PenumbraProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, chainHeight int64, clientId string, clientHeight int64) (exported.Height, error) { panic("QueryClientPrevConsensusStateHeight not implemented") } + +func (ap *PenumbraProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { + panic("QuerySendPacketByHeight not implemented") +} +func (ap *PenumbraProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.PacketHeights, err error) { + panic("QueryPacketHeights not implemented") +} +func (ap *PenumbraProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) { + panic("QueryMissingPacketReceipts not implemented") +} +func (ap *PenumbraProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { + panic("QueryNextSeqSend not implemented") +} diff --git a/relayer/common/const.go b/relayer/common/const.go index 55dee1afc..ab023cd1d 100644 --- a/relayer/common/const.go +++ b/relayer/common/const.go @@ -9,7 +9,6 @@ var ( EventTimeoutRequest = "TimeoutRequest(bytes)" IconModule = "icon" WasmModule = "wasm" - ArchwayModule = "archway" TendermintLightClient = "07-tendermint" IconLightClient = "iconclient" ConnectionKey = "connection" From 73613e6cb9b3e243c1b3252c7469b3c6c62b0ae1 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 15:20:29 +0545 Subject: [PATCH 20/61] feat: implement additional queries in icon & wasm chain --- relayer/chains/icon/query.go | 43 +++++++++++++++++++++++++----- relayer/chains/wasm/provider.go | 3 ++- relayer/chains/wasm/query.go | 16 ++++++++--- relayer/chains/wasm/types/types.go | 10 +++---- 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 5f2b8749d..f3312202f 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -792,37 +792,68 @@ func (icp *IconProvider) QueryPacketReceipt(ctx context.Context, height int64, c }, nil } -func (icp *IconProvider) QueryMissingPacketReceipts(ctx context.Context, height int64, channelId string, portId string, startSeq int64, endSeq int64) ([]types.HexInt, error) { +func (icp *IconProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) ([]uint64, error) { callParam := icp.prepareCallParams(MethodHasPacketReceipt, map[string]interface{}{ "portId": portId, "channelId": channelId, "startSeq": types.NewHexInt(int64(startSeq)), "endSeq": types.NewHexInt(int64(endSeq)), - }, callParamsWithHeight(types.NewHexInt(height))) + }, callParamsWithHeight(types.NewHexInt(latestHeight))) var missingReceipts []types.HexInt if err := icp.client.Call(callParam, &missingReceipts); err != nil { return nil, err } - return missingReceipts, nil + var receipts []uint64 + for _, h := range missingReceipts { + val, err := h.Value() + if err != nil { + return nil, err + } + receipts = append(receipts, uint64(val)) + } + + return receipts, nil } -func (icp *IconProvider) QueryPacketHeights(ctx context.Context, height int64, channelId string, portId string, startSeq int64, endSeq int64) (map[types.HexInt]types.HexInt, error) { +func (icp *IconProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.PacketHeights, error) { callParam := icp.prepareCallParams(MethodHasPacketReceipt, map[string]interface{}{ "portId": portId, "channelId": channelId, "startSeq": types.NewHexInt(int64(startSeq)), "endSeq": types.NewHexInt(int64(endSeq)), - }, callParamsWithHeight(types.NewHexInt(height))) + }, callParamsWithHeight(types.NewHexInt(latestHeight))) var missingReceipts map[types.HexInt]types.HexInt if err := icp.client.Call(callParam, &missingReceipts); err != nil { return nil, err } - return missingReceipts, nil + + var packetHeights provider.PacketHeights + for seq, h := range missingReceipts { + seqInt, err := seq.Value() + if err != nil { + return nil, err + } + heightInt, err := h.Value() + if err != nil { + return nil, err + } + + packetHeights[uint64(seqInt)] = uint64(heightInt) + } + return packetHeights, nil +} + +func (ap *IconProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { + panic("QuerySendPacketByHeight not implemented") +} + +func (ap *IconProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { + panic("QueryNextSeqSend not implemented") } // ics 20 - transfer diff --git a/relayer/chains/wasm/provider.go b/relayer/chains/wasm/provider.go index c3ad74207..96700c711 100644 --- a/relayer/chains/wasm/provider.go +++ b/relayer/chains/wasm/provider.go @@ -28,6 +28,7 @@ import ( commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" "github.com/cosmos/relayer/v2/relayer/codecs/ethermint" + "github.com/cosmos/relayer/v2/relayer/common" "github.com/cosmos/relayer/v2/relayer/processor" "github.com/cosmos/relayer/v2/relayer/provider" @@ -304,7 +305,7 @@ func (ap *WasmProvider) ChainName() string { } func (ap *WasmProvider) Type() string { - return "wasm" + return common.WasmModule } func (ap *WasmProvider) Key() string { diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index e6eb87580..ddeff3469 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -880,7 +880,7 @@ func (ap *WasmProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, return clienttypes.Height{RevisionNumber: 0, RevisionHeight: uint64(heights[0])}, nil } -func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, height int64, channelId string, portId string, startSeq int64, endSeq int64) ([]int64, error) { +func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) { callParams := types.NewPacketMissingReceiptParams(channelId, portId, startSeq, endSeq) callParamsByte, err := json.Marshal(callParams) @@ -893,7 +893,7 @@ func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, height i return nil, err } - var receipts []int64 + var receipts []uint64 if err := json.Unmarshal(result.Data.Bytes(), &receipts); err != nil { return nil, err } @@ -901,7 +901,7 @@ func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, height i return receipts, nil } -func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, height int64, channelId string, portId string, startSeq int64, endSeq int64) (map[int64]int64, error) { +func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.PacketHeights, error) { callParams := types.NewPacketHeightParams(channelId, portId, startSeq, endSeq) callParamsBytes, err := json.Marshal(callParams) @@ -913,10 +913,18 @@ func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, height int64, ch return nil, err } - var packetHeights map[int64]int64 + var packetHeights provider.PacketHeights if err := json.Unmarshal(result.Data.Bytes(), &packetHeights); err != nil { return nil, err } return packetHeights, nil } + +func (ap *WasmProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { + panic("QuerySendPacketByHeight not implemented") +} + +func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { + panic("QueryNextSeqSend not implemented") +} diff --git a/relayer/chains/wasm/types/types.go b/relayer/chains/wasm/types/types.go index cd44fe502..bbfd47baf 100644 --- a/relayer/chains/wasm/types/types.go +++ b/relayer/chains/wasm/types/types.go @@ -373,11 +373,11 @@ func NewPrevConsensusStateHeight(clientId string, height uint64) *GetPrevConsens type RangeParams struct { ChannelId string `json:"channel_id"` PortId string `json:"port_id"` - StartSequence int64 `json:"start_sequence"` - EndSequence int64 `json:"end_sequence"` + StartSequence uint64 `json:"start_sequence"` + EndSequence uint64 `json:"end_sequence"` } -func NewRangeParams(channelId, portId string, startSequence, endSequence int64) RangeParams { +func NewRangeParams(channelId, portId string, startSequence, endSequence uint64) RangeParams { return RangeParams{ ChannelId: channelId, PortId: portId, @@ -390,7 +390,7 @@ type PacketMissingReceiptsParams struct { GetMissingPacketReceipts RangeParams `json:"get_missing_packet_receipts"` } -func NewPacketMissingReceiptParams(channelId, portId string, startSequence, endSequence int64) PacketMissingReceiptsParams { +func NewPacketMissingReceiptParams(channelId, portId string, startSequence, endSequence uint64) PacketMissingReceiptsParams { return PacketMissingReceiptsParams{ GetMissingPacketReceipts: NewRangeParams(channelId, portId, startSequence, endSequence), } @@ -400,7 +400,7 @@ type PacketHeightsParams struct { GetPacketHeights RangeParams `json:"get_packet_heights"` } -func NewPacketHeightParams(channelId, portId string, startSequence, endSequence int64) PacketHeightsParams { +func NewPacketHeightParams(channelId, portId string, startSequence, endSequence uint64) PacketHeightsParams { return PacketHeightsParams{ GetPacketHeights: NewRangeParams(channelId, portId, startSequence, endSequence), } From c05f1c631e75c2abf606ea5cae537d308d53ef61 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 15:59:55 +0545 Subject: [PATCH 21/61] feat: getNextSequence Improvize logic --- relayer/chains/icon/query.go | 64 ++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index f3312202f..8001c84e7 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -44,7 +44,12 @@ const ( type CallParamOption func(*types.CallParam) +// if height is less than or zero don't set height func callParamsWithHeight(height types.HexInt) CallParamOption { + val, _ := height.Value() + if val <= 0 { + return func(*types.CallParam) {} + } return func(cp *types.CallParam) { cp.Height = height } @@ -306,7 +311,7 @@ func (icp *IconProvider) QueryConsensusState(ctx context.Context, height int64) // query all the clients of the chain func (icp *IconProvider) QueryClients(ctx context.Context) (clienttypes.IdentifiedClientStates, error) { - seq, err := icp.getNextSequence(ctx, MethodGetNextClientSequence) + seq, err := icp.getNextSequence(ctx, MethodGetNextClientSequence, 0, map[string]interface{}{}) if err != nil { return nil, err @@ -398,7 +403,8 @@ var emptyConnRes = conntypes.NewQueryConnectionResponse( // ics 03 - connection func (icp *IconProvider) QueryConnections(ctx context.Context) (conns []*conntypes.IdentifiedConnection, err error) { - nextSeq, err := icp.getNextSequence(ctx, MethodGetNextConnectionSequence) + // sending -1 for latest height + nextSeq, err := icp.getNextSequence(ctx, MethodGetNextConnectionSequence, -1, map[string]interface{}{}) if err != nil { return nil, err } @@ -440,27 +446,16 @@ func (icp *IconProvider) QueryConnections(ctx context.Context) (conns []*conntyp return conns, nil } -func (icp *IconProvider) getNextSequence(ctx context.Context, methodName string) (uint64, error) { - +func (icp *IconProvider) getNextSequence(ctx context.Context, methodName string, height int64, params map[string]interface{}) (uint64, error) { var seq types.HexInt - switch methodName { - case MethodGetNextClientSequence: - callParam := icp.prepareCallParams(MethodGetNextClientSequence, map[string]interface{}{}) - if err := icp.client.Call(callParam, &seq); err != nil { - return 0, err - } - case MethodGetNextChannelSequence: - callParam := icp.prepareCallParams(MethodGetNextChannelSequence, map[string]interface{}{}) - if err := icp.client.Call(callParam, &seq); err != nil { - return 0, err - } - case MethodGetNextConnectionSequence: - callParam := icp.prepareCallParams(MethodGetNextConnectionSequence, map[string]interface{}{}) - if err := icp.client.Call(callParam, &seq); err != nil { - return 0, err - } - default: - return 0, errors.New("Invalid method name") + options := make([]CallParamOption, 0) + if height > 0 { + options = append(options, callParamsWithHeight(types.NewHexInt(height))) + } + + callParam := icp.prepareCallParams(methodName, params, options...) + if err := icp.client.Call(callParam, &seq); err != nil { + return 0, err } val, _ := seq.Value() return uint64(val), nil @@ -592,7 +587,7 @@ func (icp *IconProvider) QueryConnectionChannels(ctx context.Context, height int } func (icp *IconProvider) QueryChannels(ctx context.Context) ([]*chantypes.IdentifiedChannel, error) { - nextSeq, err := icp.getNextSequence(ctx, MethodGetNextChannelSequence) + nextSeq, err := icp.getNextSequence(ctx, MethodGetNextChannelSequence, 0, map[string]interface{}{}) if err != nil { return nil, err } @@ -670,28 +665,22 @@ func (icp *IconProvider) QueryUnreceivedAcknowledgements(ctx context.Context, he } func (icp *IconProvider) QueryNextSeqRecv(ctx context.Context, height int64, channelid, portid string) (recvRes *chantypes.QueryNextSequenceReceiveResponse, err error) { - callParam := icp.prepareCallParams(MethodGetNextSequenceReceive, map[string]interface{}{ + + seq, err := icp.getNextSequence(ctx, MethodGetNextSequenceReceive, height, map[string]interface{}{ "portId": portid, "channelId": channelid, - }, callParamsWithHeight(types.NewHexInt(height))) - var nextSeqRecv types.HexInt - if err := icp.client.Call(callParam, &nextSeqRecv); err != nil { - return nil, err - } + }) + key := common.GetNextSequenceRecvCommitmentKey(portid, channelid) - keyHash := common.Sha3keccak256(key, []byte(nextSeqRecv)) + keyHash := common.Sha3keccak256(key, []byte(types.NewHexInt(int64(seq)))) proof, err := icp.QueryIconProof(ctx, height, keyHash) if err != nil { return nil, err } - nextSeq, err := nextSeqRecv.Value() - if err != nil { - return nil, err - } return &chantypes.QueryNextSequenceReceiveResponse{ - NextSequenceReceive: uint64(nextSeq), + NextSequenceReceive: seq, Proof: proof, ProofHeight: clienttypes.NewHeight(0, uint64(height)), }, nil @@ -853,7 +842,10 @@ func (ap *IconProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, } func (ap *IconProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { - panic("QueryNextSeqSend not implemented") + return ap.getNextSequence(ctx, MethodGetNextSequenceSend, height, map[string]interface{}{ + "channelId": channelid, + "portId": portid, + }) } // ics 20 - transfer From 7efd90203bdbfe7f7ddd7c592d455ad0d228bf2a Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 17:03:16 +0545 Subject: [PATCH 22/61] refract: wasm types code optimize --- relayer/chains/wasm/types/types.go | 161 +++++++++-------------------- 1 file changed, 47 insertions(+), 114 deletions(-) diff --git a/relayer/chains/wasm/types/types.go b/relayer/chains/wasm/types/types.go index bbfd47baf..805e8eb85 100644 --- a/relayer/chains/wasm/types/types.go +++ b/relayer/chains/wasm/types/types.go @@ -19,10 +19,6 @@ func NewHexBytes(b []byte) HexBytes { return HexBytes("0x" + hex.EncodeToString(b)) } -// / IBC Handler Contract Methods and Parameters - -// / EXTERNAL METHODS - type ContractCall struct { Msg HexBytes `json:"msg"` } @@ -50,30 +46,28 @@ func GenerateTxnParams(methodName string, value HexBytes) ([]byte, error) { return json.Marshal(m) } +type ClientState struct { + ClientId string `json:"client_id"` +} + // / READONLY METHODS type GetClientState struct { - ClientState struct { - ClientId string `json:"client_id"` - } `json:"get_client_state"` + ClientState `json:"get_client_state"` } func (x *GetClientState) Bytes() ([]byte, error) { return json.Marshal(x) } -func NewClientState(clientId string) *GetClientState { +func NewClientState(ClientId string) *GetClientState { return &GetClientState{ - struct { - ClientId string `json:"client_id"` - }{ - ClientId: clientId, - }, + ClientState{ClientId}, } } type ConsensusStateByHeight struct { - ClientId string "json:\"client_id\"" - Height uint64 "json:\"height\"" + ClientId string `json:"client_id"` + Height uint64 `json:"height"` } type GetConsensusStateByHeight struct { @@ -93,10 +87,12 @@ func NewConsensusStateByHeight(clientId string, height uint64) *GetConsensusStat } } +type Connection struct { + ConnectionId string `json:"connection_id"` +} + type GetConnection struct { - Connection struct { - ConnectionId string `json:"connection_id"` - } `json:"get_connection"` + Connection `json:"get_connection"` } func (x *GetConnection) Bytes() ([]byte, error) { @@ -105,181 +101,118 @@ func (x *GetConnection) Bytes() ([]byte, error) { func NewConnection(connId string) *GetConnection { return &GetConnection{ - Connection: struct { - ConnectionId string "json:\"connection_id\"" - }{ + Connection: Connection{ ConnectionId: connId, }, } } +type Capability struct { + PortId string `json:"port_id"` + ChannelId string `json:"channel_id"` +} + +type PacketIdentity struct { + PortId string `json:"port_id"` + ChannelId string `json:"channel_id"` + Sequence uint64 `json:"sequence"` +} + type GetChannel struct { - Channel struct { - PortId string `json:"port_id"` - ChannelId string `json:"channel_id"` - } `json:"get_channel"` + Channel Capability `json:"get_channel"` } func (x *GetChannel) Bytes() ([]byte, error) { return json.Marshal(x) } -func NewChannel(portId, channelId string) *GetChannel { +func NewChannel(PortId, ChannelId string) *GetChannel { return &GetChannel{ - Channel: struct { - PortId string "json:\"port_id\"" - ChannelId string "json:\"channel_id\"" - }{ - PortId: portId, - ChannelId: channelId, - }, + Channel: Capability{PortId, ChannelId}, } } type GetPacketCommitment struct { - PacketCommitment struct { - PortId string `json:"port_id"` - ChannelId string `json:"channel_id"` - Sequence uint64 `json:"sequence"` - } `json:"get_packet_commitment"` + PacketCommitment PacketIdentity `json:"get_packet_commitment"` } func (x *GetPacketCommitment) Bytes() ([]byte, error) { return json.Marshal(x) } -func NewPacketCommitment(portId, channelId string, sequence uint64) *GetPacketCommitment { +func NewPacketCommitment(PortId, ChannelId string, Sequence uint64) *GetPacketCommitment { return &GetPacketCommitment{ - PacketCommitment: struct { - PortId string "json:\"port_id\"" - ChannelId string "json:\"channel_id\"" - Sequence uint64 "json:\"sequence\"" - }{ - PortId: portId, - ChannelId: channelId, - Sequence: sequence, - }, + PacketCommitment: PacketIdentity{PortId, ChannelId, Sequence}, } } type GetPacketAcknowledgementCommitment struct { - PacketCommitment struct { - PortId string `json:"port_id"` - ChannelId string `json:"channel_id"` - Sequence uint64 `json:"sequence"` - } `json:"get_packet_acknowledgement_commitment"` + PacketCommitment PacketIdentity `json:"get_packet_acknowledgement_commitment"` } func (x *GetPacketAcknowledgementCommitment) Bytes() ([]byte, error) { return json.Marshal(x) } -func NewPacketAcknowledgementCommitment(portId, channelId string, sequence uint64) *GetPacketAcknowledgementCommitment { +func NewPacketAcknowledgementCommitment(PortId, ChannelId string, Sequence uint64) *GetPacketAcknowledgementCommitment { return &GetPacketAcknowledgementCommitment{ - PacketCommitment: struct { - PortId string "json:\"port_id\"" - ChannelId string "json:\"channel_id\"" - Sequence uint64 "json:\"sequence\"" - }{ - PortId: portId, - ChannelId: channelId, - Sequence: sequence, - }, + PacketCommitment: PacketIdentity{PortId, ChannelId, Sequence}, } } type GetNextSequenceSend struct { - NextSequenceSend struct { - PortId string `json:"port_id"` - ChannelId string `json:"channel_id"` - } `json:"get_next_sequence_send"` + NextSequenceSend Capability `json:"get_next_sequence_send"` } func (x *GetNextSequenceSend) Bytes() ([]byte, error) { return json.Marshal(x) } -func NewNextSequenceSend(portId, channelId string) *GetNextSequenceSend { +func NewNextSequenceSend(PortId, ChannelId string) *GetNextSequenceSend { return &GetNextSequenceSend{ - NextSequenceSend: struct { - PortId string "json:\"port_id\"" - ChannelId string "json:\"channel_id\"" - }{ - PortId: portId, - ChannelId: channelId, - }, + NextSequenceSend: Capability{PortId, ChannelId}, } } type GetNextSequenceReceive struct { - NextSequenceReceive struct { - PortId string `json:"port_id"` - ChannelId string `json:"channel_id"` - } `json:"get_next_sequence_receive"` + NextSequenceReceive Capability `json:"get_next_sequence_receive"` } func (x *GetNextSequenceReceive) Bytes() ([]byte, error) { return json.Marshal(x) } -func NewNextSequenceReceive(portId, channelId string) *GetNextSequenceReceive { +func NewNextSequenceReceive(PortId, ChannelId string) *GetNextSequenceReceive { return &GetNextSequenceReceive{ - NextSequenceReceive: struct { - PortId string "json:\"port_id\"" - ChannelId string "json:\"channel_id\"" - }{ - PortId: portId, - ChannelId: channelId, - }, + NextSequenceReceive: Capability{PortId, ChannelId}, } } type GetNextSequenceAcknowledgement struct { - NextSequenceAck struct { - PortId string `json:"port_id"` - ChannelId string `json:"channel_id"` - } `json:"get_next_sequence_acknowledgement"` + NextSequenceAck Capability `json:"get_next_sequence_acknowledgement"` } func (x *GetNextSequenceAcknowledgement) Bytes() ([]byte, error) { return json.Marshal(x) } -func NewNextSequenceAcknowledgement(portId, channelId string) *GetNextSequenceAcknowledgement { +func NewNextSequenceAcknowledgement(PortId, ChannelId string) *GetNextSequenceAcknowledgement { return &GetNextSequenceAcknowledgement{ - NextSequenceAck: struct { - PortId string "json:\"port_id\"" - ChannelId string "json:\"channel_id\"" - }{ - PortId: portId, - ChannelId: channelId, - }, + NextSequenceAck: Capability{PortId, ChannelId}, } } type GetPacketReceipt struct { - PacketReceipt struct { - PortId string `json:"port_id"` - ChannelId string `json:"channel_id"` - Sequence uint64 `json:"sequence"` - } `json:"get_packet_receipt"` + PacketReceipt PacketIdentity `json:"get_packet_receipt"` } func (x *GetPacketReceipt) Bytes() ([]byte, error) { return json.Marshal(x) } -func NewPacketReceipt(portId, channelId string, sequence uint64) *GetPacketReceipt { +func NewPacketReceipt(PortId, ChannelId string, Sequence uint64) *GetPacketReceipt { return &GetPacketReceipt{ - PacketReceipt: struct { - PortId string "json:\"port_id\"" - ChannelId string "json:\"channel_id\"" - Sequence uint64 "json:\"sequence\"" - }{ - PortId: portId, - ChannelId: channelId, - Sequence: sequence, - }, + PacketReceipt: PacketIdentity{PortId, ChannelId, Sequence}, } } From e08da36cb874c2074c1bfcf7ec4a796612c90f8d Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 17:03:40 +0545 Subject: [PATCH 23/61] feat: implement next sequence send method --- relayer/chains/wasm/query.go | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index ddeff3469..943f9031f 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -732,6 +732,10 @@ func (ap *WasmProvider) QueryNextSeqRecv(ctx context.Context, height int64, chan if err != nil { return nil, err } + var seq uint64 + if err := json.Unmarshal(nextSeqRecv.Data, &seq); err != nil { + return nil, err + } proof, err := ap.QueryWasmProof(ctx, common.MustHexStrToBytes(STORAGEKEY__NextSequenceReceive), height) if err != nil { @@ -739,7 +743,7 @@ func (ap *WasmProvider) QueryNextSeqRecv(ctx context.Context, height int64, chan } return &chantypes.QueryNextSequenceReceiveResponse{ - NextSequenceReceive: sdk.BigEndianToUint64(nextSeqRecv.Data.Bytes()), + NextSequenceReceive: seq, Proof: proof, ProofHeight: clienttypes.NewHeight(0, uint64(height)), }, nil @@ -925,6 +929,19 @@ func (ap *WasmProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, panic("QuerySendPacketByHeight not implemented") } -func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { - panic("QueryNextSeqSend not implemented") +func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (uint64, error) { + param, err := types.NewNextSequenceSend(portid, channelid).Bytes() + if err != nil { + return 0, err + } + res, err := ap.QueryIBCHandlerContract(ctx, param) + if err != nil { + return 0, err + } + + var seq uint64 + if err := json.Unmarshal(res.Data.Bytes(), &seq); err != nil { + return 0, err + } + return seq, nil } From 6776c85f2b147a2ba4b65a7f964f412ab4ecd884 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 17:23:59 +0545 Subject: [PATCH 24/61] refract: unmarshal of contract byte response --- relayer/chains/wasm/utils.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/relayer/chains/wasm/utils.go b/relayer/chains/wasm/utils.go index 6b49cc1aa..d842b7a64 100644 --- a/relayer/chains/wasm/utils.go +++ b/relayer/chains/wasm/utils.go @@ -3,9 +3,9 @@ package wasm import ( "encoding/binary" "encoding/hex" + "encoding/json" "fmt" "strconv" - "strings" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/cosmos/relayer/v2/relayer/common" @@ -30,9 +30,11 @@ func byteToInt(b []byte) (int, error) { } func ProcessContractResponse(p *wasmtypes.QuerySmartContractStateResponse) ([]byte, error) { - data := string(p.Data.Bytes()) - trimmedData := strings.ReplaceAll(data, `"`, "") - return hex.DecodeString(trimmedData) + var output string + if err := json.Unmarshal(p.Data.Bytes(), &output); err != nil { + return nil, err + } + return hex.DecodeString(output) } func getStorageKeyFromPath(path []byte) []byte { From c7e05343bb3b201004513d26d98a6830b856a0f3 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 18:30:29 +0545 Subject: [PATCH 25/61] feat: add querySendPacketByHeight wasm chain --- relayer/chains/cosmos/query.go | 2 +- relayer/chains/icon/query.go | 2 +- relayer/chains/penumbra/query.go | 2 +- relayer/chains/wasm/query.go | 30 ++++++++++++++++++++++++++++-- relayer/provider/provider.go | 2 +- 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/relayer/chains/cosmos/query.go b/relayer/chains/cosmos/query.go index 52c8795a6..445faa807 100644 --- a/relayer/chains/cosmos/query.go +++ b/relayer/chains/cosmos/query.go @@ -1175,7 +1175,7 @@ func (ap *CosmosProvider) QueryClientPrevConsensusStateHeight(ctx context.Contex panic("QueryClientPrevConsensusStateHeight not implemented") } -func (ap *CosmosProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { +func (ap *CosmosProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { panic("QuerySendPacketByHeight not implemented") } func (ap *CosmosProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.PacketHeights, err error) { diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 8001c84e7..72a997d85 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -837,7 +837,7 @@ func (icp *IconProvider) QueryPacketHeights(ctx context.Context, latestHeight in return packetHeights, nil } -func (ap *IconProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { +func (ap *IconProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { panic("QuerySendPacketByHeight not implemented") } diff --git a/relayer/chains/penumbra/query.go b/relayer/chains/penumbra/query.go index 7281f29b4..fa374cebc 100644 --- a/relayer/chains/penumbra/query.go +++ b/relayer/chains/penumbra/query.go @@ -989,7 +989,7 @@ func (cc *PenumbraProvider) QueryClientPrevConsensusStateHeight(ctx context.Cont panic("QueryClientPrevConsensusStateHeight not implemented") } -func (ap *PenumbraProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { +func (ap *PenumbraProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { panic("QuerySendPacketByHeight not implemented") } func (ap *PenumbraProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.PacketHeights, err error) { diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 943f9031f..303edfef9 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -925,8 +925,34 @@ func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, latestHeight int return packetHeights, nil } -func (ap *WasmProvider) QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { - panic("QuerySendPacketByHeight not implemented") +func (ap *WasmProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { + + h := int64(seqHeight) + blockRes, err := ap.RPCClient.BlockResults(ctx, &h) + if err != nil { + return provider.PacketInfo{}, err + } + + base64Encoded := true + for _, tx := range blockRes.TxsResults { + if tx.Code != 0 { + // tx was not successful + continue + } + messages := ibcMessagesFromEvents(ap.log, tx.Events, ap.ChainId(), seqHeight, ap.PCfg.IbcHandlerAddress, base64Encoded) + for _, m := range messages { + switch t := m.info.(type) { + case *packetInfo: + packet := provider.PacketInfo(*t) + if packet.Sequence == sequence && packet.SourceChannel == srcChanID && packet.SourcePort == srcPortID { + return packet, nil + } + default: + continue + } + } + } + return provider.PacketInfo{}, fmt.Errorf("Packet not found on height") } func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (uint64, error) { diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 0c31d9ce7..55c1ea13c 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -438,7 +438,7 @@ type QueryProvider interface { // query packet info for sequence QuerySendPacket(ctx context.Context, srcChanID, srcPortID string, sequence uint64) (PacketInfo, error) QueryRecvPacket(ctx context.Context, dstChanID, dstPortID string, sequence uint64) (PacketInfo, error) - QuerySendPacketByHeight(ctx context.Context, dstChanID, dstPortID string, sequence uint64, seqHeight uint64) (PacketInfo, error) + QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (PacketInfo, error) // bank QueryBalance(ctx context.Context, keyName string) (sdk.Coins, error) From cb5cd9b2e2e760bb5f31f859a7bc3ec1cbe7311f Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Wed, 6 Sep 2023 19:19:26 +0545 Subject: [PATCH 26/61] feat: query send packet by height query added --- relayer/chains/icon/methods.go | 2 +- relayer/chains/icon/query.go | 74 +++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/relayer/chains/icon/methods.go b/relayer/chains/icon/methods.go index 8c2012bf1..9972db139 100644 --- a/relayer/chains/icon/methods.go +++ b/relayer/chains/icon/methods.go @@ -44,5 +44,5 @@ const ( MethodGetAllPorts = "getAllPorts" MethodGetMissingPacketReceipts = "getMissingPacketReceipts" - MethodGetPacketHeights = "getpacketHeights" + MethodGetPacketHeights = "getPacketHeights" ) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 72a997d85..432acb6f1 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -809,20 +809,20 @@ func (icp *IconProvider) QueryMissingPacketReceipts(ctx context.Context, latestH func (icp *IconProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.PacketHeights, error) { - callParam := icp.prepareCallParams(MethodHasPacketReceipt, map[string]interface{}{ - "portId": portId, - "channelId": channelId, - "startSeq": types.NewHexInt(int64(startSeq)), - "endSeq": types.NewHexInt(int64(endSeq)), + callParam := icp.prepareCallParams(MethodGetPacketHeights, map[string]interface{}{ + "portId": portId, + "channelId": channelId, + "startSequence": types.NewHexInt(int64(startSeq)), + "endSequence": types.NewHexInt(int64(endSeq)), }, callParamsWithHeight(types.NewHexInt(latestHeight))) - var missingReceipts map[types.HexInt]types.HexInt - if err := icp.client.Call(callParam, &missingReceipts); err != nil { + var rawPacketHeights map[types.HexInt]types.HexInt + if err := icp.client.Call(callParam, &rawPacketHeights); err != nil { return nil, err } - var packetHeights provider.PacketHeights - for seq, h := range missingReceipts { + packetHeights := make(provider.PacketHeights, 0) + for seq, h := range rawPacketHeights { seqInt, err := seq.Value() if err != nil { return nil, err @@ -838,7 +838,61 @@ func (icp *IconProvider) QueryPacketHeights(ctx context.Context, latestHeight in } func (ap *IconProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { - panic("QuerySendPacketByHeight not implemented") + block, err := ap.client.GetBlockByHeight(&types.BlockHeightParam{ + Height: types.NewHexInt(int64(seqHeight)), + }) + if err != nil { + return provider.PacketInfo{}, err + } + + for _, res := range block.NormalTransactions { + + txResult, err := ap.client.GetTransactionResult(&types.TransactionHashParam{ + Hash: res.TxHash, + }) + if err != nil { + return provider.PacketInfo{}, err + } + for _, el := range txResult.EventLogs { + if el.Addr != types.Address(ap.PCfg.IbcHandlerAddress) && + // sendPacket will be of index length 2 + len(el.Indexed) != 2 && + el.Indexed[0] != EventTypeSendPacket { + continue + } + packetStr := el.Indexed[1] + packetByte, err := hex.DecodeString(strings.TrimPrefix(packetStr, "0x")) + if err != nil { + return provider.PacketInfo{}, err + } + var packet icon.Packet + if err := proto.Unmarshal(packetByte, &packet); err != nil { + return provider.PacketInfo{}, err + } + + if packet.Sequence != sequence && packet.SourceChannel != srcChanID && packet.SourcePort != srcPortID { + continue + } + return provider.PacketInfo{ + Height: seqHeight + 1, + Sequence: packet.Sequence, + SourcePort: packet.SourcePort, + SourceChannel: packet.SourceChannel, + DestPort: packet.DestinationPort, + DestChannel: packet.DestinationChannel, + Data: packet.Data, + TimeoutHeight: clienttypes.NewHeight(packet.TimeoutHeight.RevisionNumber, packet.TimeoutHeight.RevisionHeight), + TimeoutTimestamp: packet.TimeoutTimestamp, + }, nil + + } + + } + + return provider.PacketInfo{}, fmt.Errorf( + fmt.Sprintf("Packet of seq number : %d, srcchannel:%s, srcPort:%s not found at height %d", + sequence, srcChanID, srcPortID, seqHeight)) + } func (ap *IconProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { From 60ef21fd04549b7e1ce70615d623f8b9f982f47f Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Thu, 7 Sep 2023 18:00:41 +0545 Subject: [PATCH 27/61] fix: get next seq based on height --- relayer/chains/wasm/query.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 303edfef9..f29ec41ed 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -960,11 +960,19 @@ func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, chan if err != nil { return 0, err } - res, err := ap.QueryIBCHandlerContract(ctx, param) + clientCtx := ap.ClientCtx + if height > 0 { + clientCtx = clientCtx.WithHeight(height) + + } + qc := wasmtypes.NewQueryClient(clientCtx) + res, err := qc.SmartContractState(ctx, &wasmtypes.QuerySmartContractStateRequest{ + Address: ap.PCfg.IbcHandlerAddress, + QueryData: param, + }) if err != nil { return 0, err } - var seq uint64 if err := json.Unmarshal(res.Data.Bytes(), &seq); err != nil { return 0, err From 807283c584361ad4bb32a4576bab0b89409a5959 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 11:56:55 +0545 Subject: [PATCH 28/61] fix: remove comment --- relayer/chains/wasm/tx.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/relayer/chains/wasm/tx.go b/relayer/chains/wasm/tx.go index 64b34dfca..b7dc2ebf6 100644 --- a/relayer/chains/wasm/tx.go +++ b/relayer/chains/wasm/tx.go @@ -744,20 +744,6 @@ func (ap *WasmProvider) SendMessagesToMempool( return err } - // if msg.Type() == MethodUpdateClient { - // if err := retry.Do(func() error { - // if err := ap.BroadcastTx(cliCtx, txBytes, []provider.RelayerMessage{msg}, asyncCtx, defaultBroadcastWaitTimeout, asyncCallback, true); err != nil { - // if strings.Contains(err.Error(), sdkerrors.ErrWrongSequence.Error()) { - // ap.handleAccountSequenceMismatchError(err) - // } - // } - // return err - // }, retry.Context(ctx), rtyAtt, retry.Delay(time.Millisecond*time.Duration(ap.PCfg.BlockInterval)), rtyErr); err != nil { - // ap.log.Error("Failed to update client", zap.Any("Message", msg)) - // return err - // } - // continue - // } if err := ap.BroadcastTx(cliCtx, txBytes, []provider.RelayerMessage{msg}, asyncCtx, defaultBroadcastWaitTimeout, asyncCallback, false); err != nil { if strings.Contains(err.Error(), sdkerrors.ErrWrongSequence.Error()) { ap.handleAccountSequenceMismatchError(err) From 2e9818c99e2e660061d66b166e4dad2245f2c6ac Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 11:57:35 +0545 Subject: [PATCH 29/61] feat: new btp queue structure --- relayer/processor/types.go | 128 +++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 70 deletions(-) diff --git a/relayer/processor/types.go b/relayer/processor/types.go index f32a636d3..985caf1b9 100644 --- a/relayer/processor/types.go +++ b/relayer/processor/types.go @@ -598,105 +598,93 @@ func ConnectionInfoConnectionKey(info provider.ConnectionInfo) ConnectionKey { } } -type Queue[T any] interface { - Enqueue(item T) - Dequeue() (T, error) - MustGetQueue() T - GetQueue() (T, error) - ItemExist(interface{}) bool - ReplaceQueue(index int, item T) - Size() int -} - type ExistenceChecker interface { Exists(target interface{}) bool } type BlockInfoHeight struct { - Height int64 IsProcessing bool RetryCount int64 } -func (bi BlockInfoHeight) Exists(target interface{}) bool { - if height, ok := target.(int64); ok { - return bi.Height == height - } - return false +type BtpHeightMapQueue struct { + HeightMap map[uint64]BlockInfoHeight + HeightQueue []uint64 + mu *sync.Mutex } -type ArrayQueue[T ExistenceChecker] struct { - items []T - mu *sync.Mutex +func NewBtpHeightMapQueue() *BtpHeightMapQueue { + return &BtpHeightMapQueue{ + HeightMap: make(map[uint64]BlockInfoHeight, 0), + HeightQueue: make([]uint64, 0), + mu: &sync.Mutex{}, + } } -func (q *ArrayQueue[T]) Enqueue(item T) { - q.mu.Lock() - defer q.mu.Unlock() - q.items = append(q.items, item) -} +func (m *BtpHeightMapQueue) Enqueue(height uint64) { + m.mu.Lock() + defer m.mu.Unlock() + m.HeightQueue = append(m.HeightQueue, height) + m.HeightMap[height] = BlockInfoHeight{ + IsProcessing: false, + RetryCount: 0, + } -func (q *ArrayQueue[T]) MustGetQueue() T { +} +func (q *BtpHeightMapQueue) Dequeue() (BlockInfoHeight, error) { q.mu.Lock() defer q.mu.Unlock() if q.Size() == 0 { - panic("the size of queue is zero") + return BlockInfoHeight{}, fmt.Errorf("all element dequed") } + h := q.HeightQueue[0] - item := q.items[0] - return item -} + blockInfo := q.HeightMap[h] + delete(q.HeightMap, h) + q.HeightQueue = q.HeightQueue[1:] + return blockInfo, nil -func (q *ArrayQueue[T]) ItemExist(target interface{}) bool { - q.mu.Lock() - defer q.mu.Unlock() - for _, item := range q.items { - if item.Exists(target) { - return true - } - } - return false } - -func (q *ArrayQueue[T]) GetQueue() (T, error) { - q.mu.Lock() - defer q.mu.Unlock() - if q.Size() == 0 { - var element T - return element, fmt.Errorf("The queue is of empty length") +func (m *BtpHeightMapQueue) MustGetQueue() uint64 { + if m.Size() == 0 { + panic("the size of queue is zero") } - item := q.items[0] - return item, nil - + return m.HeightQueue[0] } - -func (q *ArrayQueue[T]) ReplaceQueue(index int, element T) { - q.mu.Lock() - defer q.mu.Unlock() - if index >= 0 && index < len(q.items) { - q.items[index] = element +func (m *BtpHeightMapQueue) GetQueue() (uint64, error) { + if m.Size() == 0 { + return 0, fmt.Errorf("The queue is of empty length") } + h := m.HeightQueue[0] + _, ok := m.HeightMap[h] + if !ok { + return 0, fmt.Errorf("Btp data of height %d missing from map", h) + } + return h, nil } -func (q *ArrayQueue[T]) Dequeue() (T, error) { - q.mu.Lock() - defer q.mu.Unlock() - if q.Size() == 0 { - var element T - return element, fmt.Errorf("all element dequed") +func (m *BtpHeightMapQueue) GetHeightInfo(h uint64) (BlockInfoHeight, error) { + b, ok := m.HeightMap[h] + if !ok { + return BlockInfoHeight{}, fmt.Errorf("Height Info not found %d", h) } - item := q.items[0] - q.items = q.items[1:] - return item, nil + return b, nil } -func (q *ArrayQueue[T]) Size() int { - return len(q.items) -} +func (m *BtpHeightMapQueue) ItemExist(height uint64) bool { + _, ok := m.HeightMap[height] + return ok -func NewBlockInfoHeightQueue[T ExistenceChecker]() *ArrayQueue[T] { - return &ArrayQueue[T]{ - items: make([]T, 0), - mu: &sync.Mutex{}, +} +func (m *BtpHeightMapQueue) ReplaceQueue(height uint64, b BlockInfoHeight) error { + m.mu.Lock() + defer m.mu.Unlock() + if _, ok := m.HeightMap[height]; !ok { + return fmt.Errorf("Height Info not found %d", height) } + m.HeightMap[height] = b + return nil +} +func (m *BtpHeightMapQueue) Size() int { + return len(m.HeightQueue) } From de85a36e26e6b6bf0db14818092a52b911ef0a92 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 11:59:21 +0545 Subject: [PATCH 30/61] feat: update client logic --- relayer/processor/message_processor.go | 67 +++++++++++++------- relayer/processor/path_end_runtime.go | 9 ++- relayer/processor/path_processor_internal.go | 21 ++---- 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/relayer/processor/message_processor.go b/relayer/processor/message_processor.go index 44ff7a9ab..ab71bb403 100644 --- a/relayer/processor/message_processor.go +++ b/relayer/processor/message_processor.go @@ -23,6 +23,7 @@ type messageProcessor struct { memo string msgUpdateClient provider.RelayerMessage + msgUpdateClientHeight uint64 clientUpdateThresholdTime time.Duration pktMsgs []packetMessageToTrack @@ -110,12 +111,17 @@ func (mp *messageProcessor) shouldUpdateClientNow(ctx context.Context, src, dst if src.BTPHeightQueue.Size() == 0 { return false, nil } - btpHeightInfo, err := src.BTPHeightQueue.GetQueue() + h, err := src.BTPHeightQueue.GetQueue() if err != nil { return false, nil } - if btpHeightInfo.IsProcessing { + blockHeightInfo, err := src.BTPHeightQueue.GetHeightInfo(h) + if err != nil { + return false, err + } + + if blockHeightInfo.IsProcessing { return false, nil } return true, nil @@ -299,6 +305,7 @@ func (mp *messageProcessor) assembleMsgUpdateClient(ctx context.Context, src, ds } mp.msgUpdateClient = msgUpdateClient + mp.msgUpdateClientHeight = src.latestHeader.Height() return nil } @@ -311,7 +318,7 @@ func (mp *messageProcessor) handleMsgUpdateClientForBTPClient(ctx context.Contex if src.BTPHeightQueue.Size() == 0 { return nil } - btpHeightInfo, err := src.BTPHeightQueue.GetQueue() + nextBtpHeight, err := src.BTPHeightQueue.GetQueue() if err != nil { return nil } @@ -320,9 +327,9 @@ func (mp *messageProcessor) handleMsgUpdateClientForBTPClient(ctx context.Contex return nil } - header, err := src.chainProvider.QueryIBCHeader(ctx, btpHeightInfo.Height) + header, err := src.chainProvider.QueryIBCHeader(ctx, int64(nextBtpHeight)) if err != nil { - return fmt.Errorf("Failed to query header for height %d", btpHeightInfo.Height) + return fmt.Errorf("Failed to query header for height %d", nextBtpHeight) } if !header.IsCompleteBlock() { @@ -361,6 +368,7 @@ func (mp *messageProcessor) handleMsgUpdateClientForBTPClient(ctx context.Contex } mp.msgUpdateClient = msgUpdateClient + mp.msgUpdateClientHeight = header.Height() return nil } @@ -416,18 +424,25 @@ func (mp *messageProcessor) sendClientUpdate( dst.log.Debug("Will relay client update") if IsBTPLightClient(dst.clientState) { - blockInfoHeight, err := src.BTPHeightQueue.GetQueue() + h, err := src.BTPHeightQueue.GetQueue() if err != nil { mp.log.Debug("No message in the queue", zap.Error(err)) return } + blockHeightInfo, err := src.BTPHeightQueue.GetHeightInfo(h) + if err != nil { + mp.log.Debug("No message in the queue", zap.Error(err)) + return + } + if blockHeightInfo.IsProcessing { + return + } dst.lastClientUpdateHeightMu.Lock() - dst.lastClientUpdateHeight = uint64(blockInfoHeight.Height) + dst.lastClientUpdateHeight = h dst.lastClientUpdateHeightMu.Unlock() - src.BTPHeightQueue.ReplaceQueue(zeroIndex, BlockInfoHeight{ - Height: int64(blockInfoHeight.Height), + src.BTPHeightQueue.ReplaceQueue(h, BlockInfoHeight{ IsProcessing: true, - RetryCount: blockInfoHeight.RetryCount + 1, + RetryCount: blockHeightInfo.RetryCount, }) } else { @@ -439,40 +454,44 @@ func (mp *messageProcessor) sendClientUpdate( msgs := []provider.RelayerMessage{mp.msgUpdateClient} callback := func(rtr *provider.RelayerTxResponse, err error) { - mp.log.Debug("Executing callback of sendClientUpdate ", zap.Any("Transaction Status", rtr.Code), zap.Any("Response", rtr), zap.Any("LastClientUpdateHeight", dst.lastClientUpdateHeight)) if IsBTPLightClient(dst.clientState) { - if src.BTPHeightQueue.Size() == 0 { - return - } - blockHeightInfo, err := src.BTPHeightQueue.GetQueue() + h, err := src.BTPHeightQueue.GetQueue() if err != nil { return } + if rtr.Code == 0 { - if blockHeightInfo.Height == int64(dst.lastClientUpdateHeight) { + if h == dst.lastClientUpdateHeight { src.BTPHeightQueue.Dequeue() } return } // this would represent a failure case in that case isProcessing should be false - if blockHeightInfo.Height == int64(dst.lastClientUpdateHeight) { - if blockHeightInfo.RetryCount >= 5 { - // removing btpBLock update - src.BTPHeightQueue.Dequeue() + // replacing the attempt only if the attempts fails + if h == dst.lastClientUpdateHeight { + heightInfo, err := src.BTPHeightQueue.GetHeightInfo(h) + if err != nil { + mp.log.Error("Error occured when getting Btp block height Info", zap.Error(err)) return } - - src.BTPHeightQueue.ReplaceQueue(zeroIndex, BlockInfoHeight{ - Height: int64(dst.lastClientUpdateHeight), + src.BTPHeightQueue.ReplaceQueue(h, BlockInfoHeight{ IsProcessing: false, - RetryCount: blockHeightInfo.RetryCount + 1, + RetryCount: heightInfo.RetryCount + 1, }) + if heightInfo.RetryCount >= 5 { + // throwing error if the Retry count is greater than 5 + // not processing forward until height x btp block is updated + mp.log.Error("Unable to update Btp Client even after attempt:", + zap.String("ClientId", dst.clientState.ClientID), zap.Error(err)) + return + } + } } } diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index c134ab8bf..bebd12eb4 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -55,7 +55,7 @@ type pathEndRuntime struct { lastClientUpdateHeightMu sync.Mutex metrics *PrometheusMetrics - BTPHeightQueue Queue[BlockInfoHeight] + BTPHeightQueue *BtpHeightMapQueue } func newPathEndRuntime(log *zap.Logger, pathEnd PathEnd, metrics *PrometheusMetrics) *pathEndRuntime { @@ -77,7 +77,7 @@ func newPathEndRuntime(log *zap.Logger, pathEnd PathEnd, metrics *PrometheusMetr clientICQProcessing: make(clientICQProcessingCache), connSubscribers: make(map[string][]func(provider.ConnectionInfo)), metrics: metrics, - BTPHeightQueue: NewBlockInfoHeightQueue[BlockInfoHeight](), + BTPHeightQueue: NewBtpHeightMapQueue(), } } @@ -392,7 +392,7 @@ func (pathEnd *pathEndRuntime) mergeCacheData(ctx context.Context, cancel func() pathEnd.clientState = d.ClientState if pathEnd.chainProvider.Type() == common.IconModule && d.LatestHeader.IsCompleteBlock() { - pathEnd.BTPHeightQueue.Enqueue(BlockInfoHeight{Height: int64(d.LatestHeader.Height()), IsProcessing: false}) + pathEnd.BTPHeightQueue.Enqueue(d.LatestHeader.Height()) } terminate, err := pathEnd.checkForMisbehaviour(ctx, pathEnd.clientState, counterParty) @@ -476,8 +476,7 @@ func (pathEnd *pathEndRuntime) shouldSendPacketMessage(message packetIBCMessage, ) return false } - if counterparty.BTPHeightQueue.ItemExist(int64(message.info.Height)) { - + if counterparty.BTPHeightQueue.ItemExist(message.info.Height) { pathEnd.log.Debug("Waiting to relay packet message until clientState is in queue", zap.Inline(message), zap.String("event_type", eventType), diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index 057d1077f..a91822687 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1569,19 +1569,19 @@ func (pp *PathProcessor) UpdateBTPHeight(ctx context.Context, src *pathEndRuntim } size := src.BTPHeightQueue.Size() for i := 0; i < size; i++ { - btpHeightInfo, err := src.BTPHeightQueue.GetQueue() + btpHeight, err := src.BTPHeightQueue.GetQueue() if err != nil { continue } - if dst.clientState.ConsensusHeight.RevisionHeight < uint64(btpHeightInfo.Height) { + if dst.clientState.ConsensusHeight.RevisionHeight < btpHeight { break } - if dst.clientState.ConsensusHeight.RevisionHeight == uint64(btpHeightInfo.Height) { + if dst.clientState.ConsensusHeight.RevisionHeight == btpHeight { src.BTPHeightQueue.Dequeue() continue } - if dst.clientState.ConsensusHeight.RevisionHeight > uint64(btpHeightInfo.Height) { - cs, err := dst.chainProvider.QueryClientConsensusState(ctx, int64(dst.latestBlock.Height), dst.clientState.ClientID, clienttypes.NewHeight(0, uint64(btpHeightInfo.Height))) + if dst.clientState.ConsensusHeight.RevisionHeight > btpHeight { + cs, err := dst.chainProvider.QueryClientConsensusState(ctx, int64(dst.latestBlock.Height), dst.clientState.ClientID, clienttypes.NewHeight(0, uint64(btpHeight))) if err == nil && cs != nil { // removing latest height element src.BTPHeightQueue.Dequeue() @@ -1802,7 +1802,6 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( // incase of BTPBlock SeqHeight+1 will have matching BTPMessage seqHeight, ok := packetHeights.PacketHeights[seq] - seqHeight = seqHeight if !ok { continue } @@ -1834,15 +1833,7 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( return nil }) - if IsBTPLightClient(dst.clientState) { - // the btpMessage will be present in seqHeight +1 , if not present need to insert btpBlockHeight to the btpBlockDataStructure - _, err := dst.chainProvider.QueryClientConsensusState(ctx, int64(dst.latestBlock.Height), dst.clientState.ClientID, clienttypes.NewHeight(0, seqHeight+1)) - // if err !=nil header may not be there in light client - // if btpHeight already submitted then will be discarded before submitting update client - if err != nil { - src.BTPHeightQueue.Enqueue(BlockInfoHeight{Height: int64(seqHeight) + 1, IsProcessing: false, RetryCount: 0}) - } - } + // not trying to enqueue btpBlock height if height is missing } if err := eg.Wait(); err != nil { From 4f233d7b32bd2edcfabcc6a3218cc3c2d2092677 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 11:59:46 +0545 Subject: [PATCH 31/61] feat: add test btp queue --- relayer/processor/types_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/relayer/processor/types_test.go b/relayer/processor/types_test.go index 5edb510fb..b716db3e5 100644 --- a/relayer/processor/types_test.go +++ b/relayer/processor/types_test.go @@ -5,6 +5,7 @@ import ( ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" "github.com/cosmos/relayer/v2/relayer/processor" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -43,3 +44,30 @@ func TestIBCHeaderCachePrune(t *testing.T) { require.Len(t, cache, 5) require.NotNil(t, cache[uint64(15)], cache[uint64(16)], cache[uint64(17)], cache[uint64(18)], cache[uint64(19)]) } + +func TestBtpQueue(t *testing.T) { + + q := processor.NewBtpHeightMapQueue() + + q.Enqueue(20) + q.Enqueue(30) + q.Enqueue(40) + + assert.Equal(t, q.Size(), 3) + + q.Dequeue() + assert.Equal(t, q.Size(), 2) + + // testing getQueue + h := uint64(40) + hInfo, err := q.GetHeightInfo(h) + assert.NoError(t, err) + assert.Equal(t, processor.BlockInfoHeight{IsProcessing: false, RetryCount: 0}, hInfo) + + replace := processor.BlockInfoHeight{IsProcessing: true, RetryCount: 2} + q.ReplaceQueue(h, replace) + hInfo, err = q.GetHeightInfo(h) + assert.NoError(t, err) + assert.Equal(t, replace, hInfo) + +} From b07f90e24705aae8086d0bb54d2bc9c79aeeeb6b Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 14:04:20 +0545 Subject: [PATCH 32/61] fix: queryMissingPacketReceipts method icon provider --- relayer/chains/icon/query.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 432acb6f1..2531a59b7 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -783,11 +783,11 @@ func (icp *IconProvider) QueryPacketReceipt(ctx context.Context, height int64, c func (icp *IconProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) ([]uint64, error) { - callParam := icp.prepareCallParams(MethodHasPacketReceipt, map[string]interface{}{ - "portId": portId, - "channelId": channelId, - "startSeq": types.NewHexInt(int64(startSeq)), - "endSeq": types.NewHexInt(int64(endSeq)), + callParam := icp.prepareCallParams(MethodGetMissingPacketReceipts, map[string]interface{}{ + "portId": portId, + "channelId": channelId, + "startSequence": types.NewHexInt(int64(startSeq)), + "endSequence": types.NewHexInt(int64(endSeq)), }, callParamsWithHeight(types.NewHexInt(latestHeight))) var missingReceipts []types.HexInt From 64cf31d9e58427b3935bedfae86f2ae9364a9d2b Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 14:18:46 +0545 Subject: [PATCH 33/61] fix: filter packetHeights before --- relayer/processor/path_processor_internal.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index a91822687..777245a61 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1789,6 +1789,12 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( skipped := false for i, seq := range unrecv { + // seq could be only queried if in packetheights + seqHeight, ok := packetHeights.PacketHeights[seq] + if !ok { + continue + } + srcMu.Lock() if srcCache.IsCached(chantypes.EventTypeSendPacket, k, seq) { continue // already cached @@ -1800,16 +1806,10 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( break } - // incase of BTPBlock SeqHeight+1 will have matching BTPMessage - seqHeight, ok := packetHeights.PacketHeights[seq] - if !ok { - continue - } - src.log.Debug("Querying send packet", zap.String("channel", k.ChannelID), zap.String("port", k.PortID), - zap.Uint64("sequence", seq), + zap.Any("Seq", seq), ) seq := seq @@ -1844,7 +1844,7 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( src.log.Debug("Will flush MsgRecvPacket", zap.String("channel", k.ChannelID), zap.String("port", k.PortID), - zap.Uint64s("sequences", unrecv), + zap.Any("PacketHeights", packetHeights), ) } else { src.log.Debug("No MsgRecvPacket to flush", From a2f663ab5e36bfb706c825ec0e075185b942c949 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 15:43:24 +0545 Subject: [PATCH 34/61] chore: rename packetHeights to message heights --- relayer/chains/cosmos/query.go | 2 +- relayer/chains/icon/query.go | 4 ++-- relayer/chains/penumbra/query.go | 2 +- relayer/chains/wasm/query.go | 4 ++-- relayer/processor/path_processor_internal.go | 20 ++++++++++---------- relayer/provider/provider.go | 13 +++++++------ 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/relayer/chains/cosmos/query.go b/relayer/chains/cosmos/query.go index 445faa807..d2418fa6f 100644 --- a/relayer/chains/cosmos/query.go +++ b/relayer/chains/cosmos/query.go @@ -1178,7 +1178,7 @@ func (ap *CosmosProvider) QueryClientPrevConsensusStateHeight(ctx context.Contex func (ap *CosmosProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { panic("QuerySendPacketByHeight not implemented") } -func (ap *CosmosProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.PacketHeights, err error) { +func (ap *CosmosProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.MessageHeights, err error) { panic("QueryPacketHeights not implemented") } func (ap *CosmosProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) { diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 96c416e18..7dbbd9bde 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -807,7 +807,7 @@ func (icp *IconProvider) QueryMissingPacketReceipts(ctx context.Context, latestH return receipts, nil } -func (icp *IconProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.PacketHeights, error) { +func (icp *IconProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { callParam := icp.prepareCallParams(MethodGetPacketHeights, map[string]interface{}{ "portId": portId, @@ -821,7 +821,7 @@ func (icp *IconProvider) QueryPacketHeights(ctx context.Context, latestHeight in return nil, err } - packetHeights := make(provider.PacketHeights, 0) + packetHeights := make(provider.MessageHeights, 0) for seq, h := range rawPacketHeights { seqInt, err := seq.Value() if err != nil { diff --git a/relayer/chains/penumbra/query.go b/relayer/chains/penumbra/query.go index fa374cebc..b06044c57 100644 --- a/relayer/chains/penumbra/query.go +++ b/relayer/chains/penumbra/query.go @@ -992,7 +992,7 @@ func (cc *PenumbraProvider) QueryClientPrevConsensusStateHeight(ctx context.Cont func (ap *PenumbraProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { panic("QuerySendPacketByHeight not implemented") } -func (ap *PenumbraProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.PacketHeights, err error) { +func (ap *PenumbraProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.MessageHeights, err error) { panic("QueryPacketHeights not implemented") } func (ap *PenumbraProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) { diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index f90c6ac5e..b2369d470 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -932,7 +932,7 @@ func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, latestHe return receipts, nil } -func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.PacketHeights, error) { +func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { callParams := types.NewPacketHeightParams(channelId, portId, startSeq, endSeq) callParamsBytes, err := json.Marshal(callParams) @@ -944,7 +944,7 @@ func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, latestHeight int return nil, err } - var packetHeights provider.PacketHeights + var packetHeights provider.MessageHeights if err := json.Unmarshal(result.Data.Bytes(), &packetHeights); err != nil { return nil, err } diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index 777245a61..33d16117b 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1604,8 +1604,8 @@ func (pp *PathProcessor) flushByCase(ctx context.Context) error { func (pp *PathProcessor) ibcContractBasedFlush(ctx context.Context) error { var ( - channelPacketheights1 = make(map[ChannelKey]provider.PacketHeightsInfo) - channelPacketheights2 = make(map[ChannelKey]provider.PacketHeightsInfo) + channelPacketheights1 = make(map[ChannelKey]provider.MessageHeightsInfo) + channelPacketheights2 = make(map[ChannelKey]provider.MessageHeightsInfo) channelPacketheights1Mu, channelPacketheights2Mu sync.Mutex pathEnd1Cache = NewIBCMessagesCache() @@ -1696,7 +1696,7 @@ func QueryPacketHeights( src *pathEndRuntime, dst *pathEndRuntime, k ChannelKey, - packetHeights map[ChannelKey]provider.PacketHeightsInfo, + packetHeights map[ChannelKey]provider.MessageHeightsInfo, mu sync.Locker, ) func() error { return func() error { @@ -1721,10 +1721,10 @@ func QueryPacketHeights( } mu.Lock() defer mu.Unlock() - packetHeights[k] = provider.PacketHeightsInfo{ - PacketHeights: c, - StartSeq: startSeq, - EndSeq: endSeq, + packetHeights[k] = provider.MessageHeightsInfo{ + MessageHeights: c, + StartSeq: startSeq, + EndSeq: endSeq, } return nil } @@ -1735,14 +1735,14 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( ctx context.Context, src, dst *pathEndRuntime, k ChannelKey, - packetHeights provider.PacketHeightsInfo, + packetHeights provider.MessageHeightsInfo, srcCache ChannelPacketMessagesCache, dstCache ChannelPacketMessagesCache, srcMu sync.Locker, dstMu sync.Locker, ) (bool, error) { - if len(packetHeights.PacketHeights) == 0 { + if len(packetHeights.MessageHeights) == 0 { src.log.Debug("Nothing to flush", zap.String("channel", k.ChannelID), zap.String("port", k.PortID)) return true, nil } @@ -1790,7 +1790,7 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( for i, seq := range unrecv { // seq could be only queried if in packetheights - seqHeight, ok := packetHeights.PacketHeights[seq] + seqHeight, ok := packetHeights.MessageHeights[seq] if !ok { continue } diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 55c1ea13c..ffb139787 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -218,12 +218,12 @@ func (r RelayerTxResponse) MarshalLogObject(enc zapcore.ObjectEncoder) error { return nil } -type PacketHeights map[uint64]uint64 +type MessageHeights map[uint64]uint64 -type PacketHeightsInfo struct { - PacketHeights PacketHeights - StartSeq uint64 - EndSeq uint64 +type MessageHeightsInfo struct { + MessageHeights MessageHeights + StartSeq uint64 + EndSeq uint64 } type KeyProvider interface { @@ -477,7 +477,8 @@ type QueryProvider interface { QueryPacketCommitment(ctx context.Context, height int64, channelid, portid string, seq uint64) (comRes *chantypes.QueryPacketCommitmentResponse, err error) QueryPacketAcknowledgement(ctx context.Context, height int64, channelid, portid string, seq uint64) (ackRes *chantypes.QueryPacketAcknowledgementResponse, err error) QueryPacketReceipt(ctx context.Context, height int64, channelid, portid string, seq uint64) (recRes *chantypes.QueryPacketReceiptResponse, err error) - QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights PacketHeights, err error) + QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights MessageHeights, err error) + // QueryAckHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights MessageHeights, err error) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) From bf19a0a99c041039f5b6fc2cd8420b61f6388384 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 16:05:03 +0545 Subject: [PATCH 35/61] feat: add query ackHeights methods --- relayer/chains/cosmos/query.go | 3 +++ relayer/chains/icon/methods.go | 1 + relayer/chains/icon/query.go | 15 ++++++++++++++- relayer/chains/penumbra/query.go | 3 +++ relayer/chains/wasm/query.go | 20 +++++++++++++++++++- relayer/chains/wasm/types/types.go | 10 ++++++++++ relayer/provider/provider.go | 2 +- 7 files changed, 51 insertions(+), 3 deletions(-) diff --git a/relayer/chains/cosmos/query.go b/relayer/chains/cosmos/query.go index d2418fa6f..14780b0cb 100644 --- a/relayer/chains/cosmos/query.go +++ b/relayer/chains/cosmos/query.go @@ -1181,6 +1181,9 @@ func (ap *CosmosProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID func (ap *CosmosProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.MessageHeights, err error) { panic("QueryPacketHeights not implemented") } +func (ap *CosmosProvider) QueryAckHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.MessageHeights, err error) { + panic("QueryAckHeights not implemented") +} func (ap *CosmosProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) { panic("QueryMissingPacketReceipts not implemented") } diff --git a/relayer/chains/icon/methods.go b/relayer/chains/icon/methods.go index 6324023a7..894fae8aa 100644 --- a/relayer/chains/icon/methods.go +++ b/relayer/chains/icon/methods.go @@ -44,4 +44,5 @@ const ( MethodGetAllPorts = "getAllPorts" MethodGetMissingPacketReceipts = "getMissingPacketReceipts" MethodGetPacketHeights = "getPacketHeights" + MethodGetAckHeights = "getAckHeights" ) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 7dbbd9bde..33e5fdf5b 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -808,8 +808,21 @@ func (icp *IconProvider) QueryMissingPacketReceipts(ctx context.Context, latestH } func (icp *IconProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { + return icp.QueryMessageHeights(ctx, MethodGetPacketHeights, latestHeight, channelId, portId, startSeq, endSeq) +} + +func (icp *IconProvider) QueryAckHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { + return icp.QueryMessageHeights(ctx, MethodGetAckHeights, latestHeight, channelId, portId, startSeq, endSeq) +} + +func (icp *IconProvider) QueryMessageHeights(ctx context.Context, methodName string, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { + + if methodName != MethodGetPacketHeights && + methodName != MethodGetAckHeights { + return provider.MessageHeights{}, fmt.Errorf("invalid methodName: %s", methodName) + } - callParam := icp.prepareCallParams(MethodGetPacketHeights, map[string]interface{}{ + callParam := icp.prepareCallParams(methodName, map[string]interface{}{ "portId": portId, "channelId": channelId, "startSequence": types.NewHexInt(int64(startSeq)), diff --git a/relayer/chains/penumbra/query.go b/relayer/chains/penumbra/query.go index b06044c57..e214af5f1 100644 --- a/relayer/chains/penumbra/query.go +++ b/relayer/chains/penumbra/query.go @@ -995,6 +995,9 @@ func (ap *PenumbraProvider) QuerySendPacketByHeight(ctx context.Context, srcChan func (ap *PenumbraProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.MessageHeights, err error) { panic("QueryPacketHeights not implemented") } +func (ap *PenumbraProvider) QueryAckHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.MessageHeights, err error) { + panic("QueryAckHeights not implemented") +} func (ap *PenumbraProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) { panic("QueryMissingPacketReceipts not implemented") } diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index b2369d470..3b08f1da8 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -933,7 +933,6 @@ func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, latestHe } func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { - callParams := types.NewPacketHeightParams(channelId, portId, startSeq, endSeq) callParamsBytes, err := json.Marshal(callParams) if err != nil { @@ -951,6 +950,25 @@ func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, latestHeight int return packetHeights, nil } +func (ap *WasmProvider) QueryAckHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { + + callParams := types.NewAckHeightParams(channelId, portId, startSeq, endSeq) + callParamsBytes, err := json.Marshal(callParams) + if err != nil { + return nil, err + } + result, err := ap.QueryIBCHandlerContract(ctx, callParamsBytes) + if err != nil { + return nil, err + } + + var packetHeights provider.MessageHeights + if err := json.Unmarshal(result.Data.Bytes(), &packetHeights); err != nil { + return nil, err + } + + return packetHeights, nil +} func (ap *WasmProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { diff --git a/relayer/chains/wasm/types/types.go b/relayer/chains/wasm/types/types.go index 805e8eb85..0433c9bdf 100644 --- a/relayer/chains/wasm/types/types.go +++ b/relayer/chains/wasm/types/types.go @@ -338,3 +338,13 @@ func NewPacketHeightParams(channelId, portId string, startSequence, endSequence GetPacketHeights: NewRangeParams(channelId, portId, startSequence, endSequence), } } + +type AckHeightsParams struct { + GetPacketHeights RangeParams `json:"get_ack_heights"` +} + +func NewAckHeightParams(channelId, portId string, startSequence, endSequence uint64) AckHeightsParams { + return AckHeightsParams{ + GetPacketHeights: NewRangeParams(channelId, portId, startSequence, endSequence), + } +} diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index ffb139787..5cec51b09 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -478,7 +478,7 @@ type QueryProvider interface { QueryPacketAcknowledgement(ctx context.Context, height int64, channelid, portid string, seq uint64) (ackRes *chantypes.QueryPacketAcknowledgementResponse, err error) QueryPacketReceipt(ctx context.Context, height int64, channelid, portid string, seq uint64) (recRes *chantypes.QueryPacketReceiptResponse, err error) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights MessageHeights, err error) - // QueryAckHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights MessageHeights, err error) + QueryAckHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights MessageHeights, err error) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) From 7fff47336f3399b0857675d9626cf4489fb8a298 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 17:45:53 +0545 Subject: [PATCH 36/61] refract: refractor query method wasm --- relayer/chains/wasm/consts.go | 22 +++ relayer/chains/wasm/query.go | 186 +++++++++--------- relayer/chains/wasm/types/types.go | 294 +++-------------------------- relayer/chains/wasm/utils.go | 6 - 4 files changed, 140 insertions(+), 368 deletions(-) diff --git a/relayer/chains/wasm/consts.go b/relayer/chains/wasm/consts.go index e68b1bd1e..039430032 100644 --- a/relayer/chains/wasm/consts.go +++ b/relayer/chains/wasm/consts.go @@ -20,9 +20,31 @@ const ( MethodAcknowledgePacket = "acknowledgement_packet" MethodTimeoutPacket = "timeout_packet" + // queryMethods MethodGetNextClientSequence = "get_next_client_sequence" MethodGetNextChannelSequence = "get_next_channel_sequence" MethodGetNextConnectionSequence = "get_next_connection_sequence" + + MethodGetNextSequenceSend = "get_next_sequence_send" + MethodGetNextSequenceReceive = "get_next_sequence_receive" + MethodGetNextSequenceAcknowledgement = "get_next_sequence_acknowledgement" + + MethodGetClientState = "get_client_state" + MethodGetChannel = "get_channel" + MethodGetConnection = "get_connection" + MethodGetConsensusStateByHeight = "get_consensus_state_by_height" + + MethodGetPacketCommitment = "get_packet_commitment" + MethodGetPacketAcknowledgementCommitment = "get_packet_acknowledgement_commitment" + MethodGetPacketReceipt = "get_packet_receipt" + + MethodGetAllPorts = "get_all_ports" + MethodGetCommitmentPrefix = "get_commitment_prefix" + + MethodGetMissingPacketReceipts = "get_missing_packet_receipts" + MethodGetPacketHeights = "get_packet_heights" + MethodGetAckHeights = "get_ack_heights" + MethodGetPreviousConsensusStateHeight = "get_previous_consensus_state_height" ) const ( diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 3b08f1da8..cbd70b3f4 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -253,7 +253,9 @@ func (ap *WasmProvider) QueryClientStateResponse(ctx context.Context, height int } func (ap *WasmProvider) QueryClientStateContract(ctx context.Context, clientId string) (*icon.ClientState, error) { - clientStateParam, err := types.NewClientState(clientId).Bytes() + clientStateParam, err := types.GenerateQueryParams(MethodGetClientState, types.ClientState{ + ClientId: clientId, + }) if err != nil { return nil, err } @@ -279,7 +281,9 @@ func (ap *WasmProvider) QueryClientStateContract(ctx context.Context, clientId s } func (ap *WasmProvider) QueryConnectionContract(ctx context.Context, connId string) (*conntypes.ConnectionEnd, error) { - connStateParam, err := types.NewConnection(connId).Bytes() + connStateParam, err := types.GenerateQueryParams(MethodGetConnection, types.Connection{ + ConnectionId: connId, + }) if err != nil { return nil, err } @@ -298,12 +302,14 @@ func (ap *WasmProvider) QueryConnectionContract(ctx context.Context, connId stri } func (ap *WasmProvider) QueryChannelContractNoRetry(ctx context.Context, portId, channelId string) (*chantypes.Channel, error) { - channelStateParam, err := types.NewChannel(portId, channelId).Bytes() + param, err := types.GenerateQueryParams(MethodGetChannel, + types.NewCapability(channelId, portId), + ) if err != nil { return nil, err } - channelState, err := ap.QueryIBCHandlerContractNoRetry(ctx, channelStateParam) + channelState, err := ap.QueryIBCHandlerContractNoRetry(ctx, param) if err != nil { return nil, err } @@ -317,11 +323,14 @@ func (ap *WasmProvider) QueryChannelContractNoRetry(ctx context.Context, portId, func (ap *WasmProvider) QueryClientConsensusState(ctx context.Context, chainHeight int64, clientid string, clientHeight ibcexported.Height) (*clienttypes.QueryConsensusStateResponse, error) { - consensusStateParam, err := types.NewConsensusStateByHeight(clientid, uint64(clientHeight.GetRevisionHeight())).Bytes() + param, err := types.GenerateQueryParams(MethodGetConsensusStateByHeight, types.ConsensusStateByHeight{ + ClientId: clientid, + Height: clientHeight.GetRevisionHeight(), + }) if err != nil { return nil, err } - consensusState, err := ap.QueryIBCHandlerContractProcessed(ctx, consensusStateParam) + consensusState, err := ap.QueryIBCHandlerContractProcessed(ctx, param) if err != nil { return nil, err } @@ -419,7 +428,7 @@ func (ap *WasmProvider) QueryConsensusState(ctx context.Context, height int64) ( } func (ap *WasmProvider) getAllPorts(ctx context.Context) ([]string, error) { - param, err := types.NewGetAllPorts().Bytes() + param, err := types.GenerateQueryParams(MethodGetAllPorts, struct{}{}) if err != nil { return make([]string, 0), err } @@ -437,41 +446,24 @@ func (ap *WasmProvider) getAllPorts(ctx context.Context) ([]string, error) { } func (ap *WasmProvider) getNextSequence(ctx context.Context, methodName string) (int, error) { - switch methodName { - case MethodGetNextClientSequence: - param, err := types.NewNextClientSequence().Bytes() - if err != nil { - return 0, err - } - op, err := ap.QueryIBCHandlerContract(ctx, param) + switch methodName { + case MethodGetNextClientSequence, MethodGetNextChannelSequence, MethodGetNextConnectionSequence: + param, err := types.GenerateQueryParams(methodName, struct{}{}) if err != nil { return 0, err } - return byteToInt(op.Data.Bytes()) - - case MethodGetNextChannelSequence: - param, err := types.NewNextChannelSequence().Bytes() - if err != nil { - return 0, err - } - op, err := ap.QueryIBCHandlerContract(ctx, param) + res, err := ap.QueryIBCHandlerContract(ctx, param) if err != nil { return 0, err } - return byteToInt(op.Data.Bytes()) - case MethodGetNextConnectionSequence: - param, err := types.NewNextConnectionSequence().Bytes() - if err != nil { - return 0, err - } - op, err := ap.QueryIBCHandlerContract(ctx, param) - if err != nil { + var op int + if err := json.Unmarshal(res.Data.Bytes(), &op); err != nil { return 0, err } - return byteToInt(op.Data.Bytes()) + return op, nil default: return 0, errors.New("Invalid method name") @@ -504,12 +496,14 @@ func (ap *WasmProvider) QueryClients(ctx context.Context) (clienttypes.Identifie // ics 03 - connection func (ap *WasmProvider) QueryConnection(ctx context.Context, height int64, connectionid string) (*conntypes.QueryConnectionResponse, error) { - connectionStateParams, err := types.NewConnection(connectionid).Bytes() + param, err := types.GenerateQueryParams(MethodGetConnection, types.Connection{ + ConnectionId: connectionid, + }) if err != nil { return nil, err } - connState, err := ap.QueryIBCHandlerContractProcessed(ctx, connectionStateParams) + connState, err := ap.QueryIBCHandlerContractProcessed(ctx, param) if err != nil { return nil, err } @@ -645,13 +639,15 @@ func (ap *WasmProvider) GenerateConnHandshakeProof(ctx context.Context, height i } // ics 04 - channel -func (ap *WasmProvider) QueryChannel(ctx context.Context, height int64, channelid, portid string) (chanRes *chantypes.QueryChannelResponse, err error) { - channelParams, err := types.NewChannel(portid, channelid).Bytes() +func (ap *WasmProvider) QueryChannel(ctx context.Context, height int64, channelId, portId string) (chanRes *chantypes.QueryChannelResponse, err error) { + param, err := types.GenerateQueryParams(MethodGetChannel, + types.NewCapability(channelId, portId), + ) if err != nil { return nil, err } - channelState, err := ap.QueryIBCHandlerContractProcessed(ctx, channelParams) + channelState, err := ap.QueryIBCHandlerContractProcessed(ctx, param) if err != nil { return nil, err } @@ -665,7 +661,7 @@ func (ap *WasmProvider) QueryChannel(ctx context.Context, height int64, channeli return nil, err } - storageKey := getStorageKeyFromPath(common.GetChannelCommitmentKey(portid, channelid)) + storageKey := getStorageKeyFromPath(common.GetChannelCommitmentKey(portId, channelId)) proof, err := ap.QueryWasmProof(ctx, storageKey, height) if err != nil { return nil, err @@ -674,7 +670,7 @@ func (ap *WasmProvider) QueryChannel(ctx context.Context, height int64, channeli return chantypes.NewQueryChannelResponse(channelS, proof, clienttypes.NewHeight(0, uint64(height))), nil } -func (ap *WasmProvider) QueryChannelClient(ctx context.Context, height int64, channelid, portid string) (*clienttypes.IdentifiedClientState, error) { +func (ap *WasmProvider) QueryChannelClient(ctx context.Context, height int64, channelId, portId string) (*clienttypes.IdentifiedClientState, error) { panic(fmt.Sprintf("%s%s", ap.ChainName(), NOT_IMPLEMENTED)) } @@ -734,28 +730,30 @@ func (ap *WasmProvider) QueryChannels(ctx context.Context) ([]*chantypes.Identif return channels, nil } -func (ap *WasmProvider) QueryPacketCommitments(ctx context.Context, height uint64, channelid, portid string) (commitments *chantypes.QueryPacketCommitmentsResponse, err error) { +func (ap *WasmProvider) QueryPacketCommitments(ctx context.Context, height uint64, channelId, portId string) (commitments *chantypes.QueryPacketCommitmentsResponse, err error) { panic(fmt.Sprintf("%s%s", ap.ChainName(), NOT_IMPLEMENTED)) } -func (ap *WasmProvider) QueryPacketAcknowledgements(ctx context.Context, height uint64, channelid, portid string) (acknowledgements []*chantypes.PacketState, err error) { +func (ap *WasmProvider) QueryPacketAcknowledgements(ctx context.Context, height uint64, channelId, portId string) (acknowledgements []*chantypes.PacketState, err error) { panic(fmt.Sprintf("%s%s", ap.ChainName(), NOT_IMPLEMENTED)) } -func (ap *WasmProvider) QueryUnreceivedPackets(ctx context.Context, height uint64, channelid, portid string, seqs []uint64) ([]uint64, error) { +func (ap *WasmProvider) QueryUnreceivedPackets(ctx context.Context, height uint64, channelId, portId string, seqs []uint64) ([]uint64, error) { panic(fmt.Sprintf("%s%s", ap.ChainName(), NOT_IMPLEMENTED)) } -func (ap *WasmProvider) QueryUnreceivedAcknowledgements(ctx context.Context, height uint64, channelid, portid string, seqs []uint64) ([]uint64, error) { +func (ap *WasmProvider) QueryUnreceivedAcknowledgements(ctx context.Context, height uint64, channelId, portId string, seqs []uint64) ([]uint64, error) { panic(fmt.Sprintf("%s%s", ap.ChainName(), NOT_IMPLEMENTED)) } -func (ap *WasmProvider) QueryNextSeqRecv(ctx context.Context, height int64, channelid, portid string) (recvRes *chantypes.QueryNextSequenceReceiveResponse, err error) { - nextSeqRecvParams, err := types.NewNextSequenceReceive(portid, channelid).Bytes() +func (ap *WasmProvider) QueryNextSeqRecv(ctx context.Context, height int64, channelId, portId string) (recvRes *chantypes.QueryNextSequenceReceiveResponse, err error) { + param, err := types.GenerateQueryParams(MethodGetNextSequenceReceive, + types.NewCapability(channelId, portId), + ) if err != nil { return nil, err } - nextSeqRecv, err := ap.QueryIBCHandlerContract(ctx, nextSeqRecvParams) + nextSeqRecv, err := ap.QueryIBCHandlerContract(ctx, param) if err != nil { return nil, err } @@ -776,16 +774,18 @@ func (ap *WasmProvider) QueryNextSeqRecv(ctx context.Context, height int64, chan }, nil } -func (ap *WasmProvider) QueryPacketCommitment(ctx context.Context, height int64, channelid, portid string, seq uint64) (comRes *chantypes.QueryPacketCommitmentResponse, err error) { - pktCommitmentParams, err := types.NewPacketCommitment(portid, channelid, seq).Bytes() +func (ap *WasmProvider) QueryPacketCommitment(ctx context.Context, height int64, channelId, portId string, seq uint64) (comRes *chantypes.QueryPacketCommitmentResponse, err error) { + param, err := types.GenerateQueryParams(MethodGetPacketCommitment, + types.NewPacketIdentity(channelId, portId, seq), + ) if err != nil { return nil, err } - pktCommitment, err := ap.QueryIBCHandlerContract(ctx, pktCommitmentParams) + pktCommitment, err := ap.QueryIBCHandlerContract(ctx, param) if err != nil { return nil, err } - storageKey := getStorageKeyFromPath(common.GetPacketCommitmentKey(portid, channelid, big.NewInt(int64(seq)))) + storageKey := getStorageKeyFromPath(common.GetPacketCommitmentKey(portId, channelId, big.NewInt(int64(seq)))) proof, err := ap.QueryWasmProof(ctx, storageKey, height) if err != nil { @@ -799,16 +799,19 @@ func (ap *WasmProvider) QueryPacketCommitment(ctx context.Context, height int64, } -func (ap *WasmProvider) QueryPacketAcknowledgement(ctx context.Context, height int64, channelid, portid string, seq uint64) (ackRes *chantypes.QueryPacketAcknowledgementResponse, err error) { - pktAcknowledgementParams, err := types.NewPacketAcknowledgementCommitment(portid, channelid, seq).Bytes() +func (ap *WasmProvider) QueryPacketAcknowledgement(ctx context.Context, height int64, channelId, portId string, seq uint64) (ackRes *chantypes.QueryPacketAcknowledgementResponse, err error) { + param, err := types.GenerateQueryParams( + MethodGetPacketAcknowledgementCommitment, + types.NewPacketIdentity(channelId, portId, seq), + ) if err != nil { return nil, err } - pktAcknowledgement, err := ap.QueryIBCHandlerContract(ctx, pktAcknowledgementParams) + pktAcknowledgement, err := ap.QueryIBCHandlerContract(ctx, param) if err != nil { return nil, err } - storageKey := getStorageKeyFromPath(common.GetPacketAcknowledgementCommitmentKey(portid, channelid, big.NewInt(int64(seq)))) + storageKey := getStorageKeyFromPath(common.GetPacketAcknowledgementCommitmentKey(portId, channelId, big.NewInt(int64(seq)))) proof, err := ap.QueryWasmProof(ctx, storageKey, height) return &chantypes.QueryPacketAcknowledgementResponse{ @@ -818,27 +821,27 @@ func (ap *WasmProvider) QueryPacketAcknowledgement(ctx context.Context, height i }, nil } -func (ap *WasmProvider) QueryPacketReceipt(ctx context.Context, height int64, channelid, portid string, seq uint64) (recRes *chantypes.QueryPacketReceiptResponse, err error) { +func (ap *WasmProvider) QueryPacketReceipt(ctx context.Context, height int64, channelId, portId string, seq uint64) (recRes *chantypes.QueryPacketReceiptResponse, err error) { - // getting proof from commitment map in contract - storageKey := getStorageKeyFromPath(common.GetPacketReceiptCommitmentKey(portid, channelid, big.NewInt(int64(seq)))) - proof, err := ap.QueryWasmProof(ctx, storageKey, height) + param, err := types.GenerateQueryParams( + MethodGetPacketReceipt, types.NewPacketIdentity(channelId, portId, seq)) if err != nil { return nil, err } - pktReceiptParams, err := types.NewPacketReceipt(portid, channelid, seq).Bytes() - if err != nil { + pktReceipt, err := ap.QueryIBCHandlerContract(ctx, param) + if err != nil && !strings.Contains(err.Error(), "PacketReceiptNotFound") { return nil, err } - pktReceipt, err := ap.QueryIBCHandlerContract(ctx, pktReceiptParams) - if err != nil && !strings.Contains(err.Error(), "PacketReceiptNotFound") { + storageKey := getStorageKeyFromPath(common.GetPacketReceiptCommitmentKey(portId, channelId, big.NewInt(int64(seq)))) + proof, err := ap.QueryWasmProof(ctx, storageKey, height) + if err != nil { return nil, err } return &chantypes.QueryPacketReceiptResponse{ - Received: pktReceipt != nil, // TODO: Bytes to boolean + Received: pktReceipt != nil, Proof: proof, ProofHeight: clienttypes.NewHeight(0, uint64(height)), }, nil @@ -846,11 +849,11 @@ func (ap *WasmProvider) QueryPacketReceipt(ctx context.Context, height int64, ch func (ap *WasmProvider) GetCommitmentPrefixFromContract(ctx context.Context) ([]byte, error) { - pktCommitmentParams, err := types.NewCommitmentPrefix().Bytes() + param, err := types.GenerateQueryParams(MethodGetAllPorts, struct{}{}) if err != nil { return nil, err } - return ap.QueryIBCHandlerContractProcessed(ctx, pktCommitmentParams) + return ap.QueryIBCHandlerContractProcessed(ctx, param) } @@ -892,7 +895,12 @@ func (ap *WasmProvider) QueryDenomTraces(ctx context.Context, offset, limit uint } func (ap *WasmProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, chainHeight int64, clientId string, clientHeight int64) (exported.Height, error) { - param, err := types.NewPrevConsensusStateHeight(clientId, uint64(clientHeight)).Bytes() + param, err := types.GenerateQueryParams(MethodGetPreviousConsensusStateHeight, + types.NewConsensusStateByHeight(clientId, uint64(clientHeight)), + ) + if err != nil { + return nil, err + } res, err := ap.QueryIBCHandlerContract(ctx, param) if err != nil { return nil, err @@ -913,13 +921,13 @@ func (ap *WasmProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (missingReceipts []uint64, err error) { - callParams := types.NewPacketMissingReceiptParams(channelId, portId, startSeq, endSeq) - callParamsByte, err := json.Marshal(callParams) + param, err := types.GenerateQueryParams(MethodGetMissingPacketReceipts, + types.NewRangeParams(channelId, portId, startSeq, endSeq)) if err != nil { return nil, err } - result, err := ap.QueryIBCHandlerContract(ctx, callParamsByte) + result, err := ap.QueryIBCHandlerContract(ctx, param) if err != nil { return nil, err } @@ -932,32 +940,20 @@ func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, latestHe return receipts, nil } -func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { - callParams := types.NewPacketHeightParams(channelId, portId, startSeq, endSeq) - callParamsBytes, err := json.Marshal(callParams) - if err != nil { - return nil, err - } - result, err := ap.QueryIBCHandlerContract(ctx, callParamsBytes) - if err != nil { - return nil, err - } +func (ap *WasmProvider) QueryMessageHeights(ctx context.Context, methodName string, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { - var packetHeights provider.MessageHeights - if err := json.Unmarshal(result.Data.Bytes(), &packetHeights); err != nil { - return nil, err + if methodName != MethodGetAckHeights && + methodName != MethodGetPacketHeights { + return provider.MessageHeights{}, fmt.Errorf("incorrect method name: %s", methodName) } - return packetHeights, nil -} -func (ap *WasmProvider) QueryAckHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { - - callParams := types.NewAckHeightParams(channelId, portId, startSeq, endSeq) - callParamsBytes, err := json.Marshal(callParams) + param, err := types.GenerateQueryParams(methodName, + types.NewRangeParams(channelId, portId, startSeq, endSeq)) if err != nil { return nil, err } - result, err := ap.QueryIBCHandlerContract(ctx, callParamsBytes) + + result, err := ap.QueryIBCHandlerContract(ctx, param) if err != nil { return nil, err } @@ -970,6 +966,14 @@ func (ap *WasmProvider) QueryAckHeights(ctx context.Context, latestHeight int64, return packetHeights, nil } +func (ap *WasmProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { + return ap.QueryMessageHeights(ctx, MethodGetPacketHeights, latestHeight, channelId, portId, startSeq, endSeq) +} + +func (ap *WasmProvider) QueryAckHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { + return ap.QueryMessageHeights(ctx, MethodGetAckHeights, latestHeight, channelId, portId, startSeq, endSeq) +} + func (ap *WasmProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { h := int64(seqHeight) @@ -1000,8 +1004,10 @@ func (ap *WasmProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, return provider.PacketInfo{}, fmt.Errorf("Packet not found on height") } -func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (uint64, error) { - param, err := types.NewNextSequenceSend(portid, channelid).Bytes() +func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, channelId, portId string) (uint64, error) { + param, err := types.GenerateQueryParams(MethodGetNextSequenceSend, + types.NewCapability(channelId, portId), + ) if err != nil { return 0, err } diff --git a/relayer/chains/wasm/types/types.go b/relayer/chains/wasm/types/types.go index 0433c9bdf..b68c785c7 100644 --- a/relayer/chains/wasm/types/types.go +++ b/relayer/chains/wasm/types/types.go @@ -23,14 +23,6 @@ type ContractCall struct { Msg HexBytes `json:"msg"` } -type CreateClientMsg struct { - CreateClient ContractCall `json:"create_client"` -} - -func (c *CreateClientMsg) Bytes() ([]byte, error) { - return json.Marshal(c) -} - func GenerateTxnParams(methodName string, value HexBytes) ([]byte, error) { if len(methodName) <= 0 { return nil, fmt.Errorf("Empty Method Name") @@ -46,23 +38,18 @@ func GenerateTxnParams(methodName string, value HexBytes) ([]byte, error) { return json.Marshal(m) } -type ClientState struct { - ClientId string `json:"client_id"` -} - -// / READONLY METHODS -type GetClientState struct { - ClientState `json:"get_client_state"` +func GenerateQueryParams(methodName string, params interface{}) ([]byte, error) { + queryObj := make(map[string]interface{}, 0) + queryObj[methodName] = params + return json.Marshal(queryObj) } -func (x *GetClientState) Bytes() ([]byte, error) { - return json.Marshal(x) +type ClientState struct { + ClientId string `json:"client_id"` } -func NewClientState(ClientId string) *GetClientState { - return &GetClientState{ - ClientState{ClientId}, - } +func NewClientState(ClientId string) ClientState { + return ClientState{ClientId} } type ConsensusStateByHeight struct { @@ -70,237 +57,35 @@ type ConsensusStateByHeight struct { Height uint64 `json:"height"` } -type GetConsensusStateByHeight struct { - ConsensusStateByHeight ConsensusStateByHeight `json:"get_consensus_state_by_height"` -} - -func (x *GetConsensusStateByHeight) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewConsensusStateByHeight(clientId string, height uint64) *GetConsensusStateByHeight { - return &GetConsensusStateByHeight{ - ConsensusStateByHeight: ConsensusStateByHeight{ - ClientId: clientId, - Height: height, - }, - } +func NewConsensusStateByHeight(ClientId string, Height uint64) ConsensusStateByHeight { + return ConsensusStateByHeight{ClientId, Height} } type Connection struct { ConnectionId string `json:"connection_id"` } -type GetConnection struct { - Connection `json:"get_connection"` -} - -func (x *GetConnection) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewConnection(connId string) *GetConnection { - return &GetConnection{ - Connection: Connection{ - ConnectionId: connId, - }, - } +func NewConnection(ConnectionId string) Connection { + return Connection{ConnectionId} } type Capability struct { - PortId string `json:"port_id"` ChannelId string `json:"channel_id"` -} - -type PacketIdentity struct { PortId string `json:"port_id"` - ChannelId string `json:"channel_id"` - Sequence uint64 `json:"sequence"` -} - -type GetChannel struct { - Channel Capability `json:"get_channel"` -} - -func (x *GetChannel) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewChannel(PortId, ChannelId string) *GetChannel { - return &GetChannel{ - Channel: Capability{PortId, ChannelId}, - } -} - -type GetPacketCommitment struct { - PacketCommitment PacketIdentity `json:"get_packet_commitment"` -} - -func (x *GetPacketCommitment) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewPacketCommitment(PortId, ChannelId string, Sequence uint64) *GetPacketCommitment { - return &GetPacketCommitment{ - PacketCommitment: PacketIdentity{PortId, ChannelId, Sequence}, - } -} - -type GetPacketAcknowledgementCommitment struct { - PacketCommitment PacketIdentity `json:"get_packet_acknowledgement_commitment"` -} - -func (x *GetPacketAcknowledgementCommitment) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewPacketAcknowledgementCommitment(PortId, ChannelId string, Sequence uint64) *GetPacketAcknowledgementCommitment { - return &GetPacketAcknowledgementCommitment{ - PacketCommitment: PacketIdentity{PortId, ChannelId, Sequence}, - } -} - -type GetNextSequenceSend struct { - NextSequenceSend Capability `json:"get_next_sequence_send"` } -func (x *GetNextSequenceSend) Bytes() ([]byte, error) { - return json.Marshal(x) +func NewCapability(ChannelId, PortId string) Capability { + return Capability{ChannelId, PortId} } -func NewNextSequenceSend(PortId, ChannelId string) *GetNextSequenceSend { - return &GetNextSequenceSend{ - NextSequenceSend: Capability{PortId, ChannelId}, - } -} - -type GetNextSequenceReceive struct { - NextSequenceReceive Capability `json:"get_next_sequence_receive"` -} - -func (x *GetNextSequenceReceive) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewNextSequenceReceive(PortId, ChannelId string) *GetNextSequenceReceive { - return &GetNextSequenceReceive{ - NextSequenceReceive: Capability{PortId, ChannelId}, - } -} - -type GetNextSequenceAcknowledgement struct { - NextSequenceAck Capability `json:"get_next_sequence_acknowledgement"` -} - -func (x *GetNextSequenceAcknowledgement) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewNextSequenceAcknowledgement(PortId, ChannelId string) *GetNextSequenceAcknowledgement { - return &GetNextSequenceAcknowledgement{ - NextSequenceAck: Capability{PortId, ChannelId}, - } -} - -type GetPacketReceipt struct { - PacketReceipt PacketIdentity `json:"get_packet_receipt"` -} - -func (x *GetPacketReceipt) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewPacketReceipt(PortId, ChannelId string, Sequence uint64) *GetPacketReceipt { - return &GetPacketReceipt{ - PacketReceipt: PacketIdentity{PortId, ChannelId, Sequence}, - } -} - -type GetNextClientSequence struct { - Sequence struct{} `json:"get_next_client_sequence"` -} - -func (x *GetNextClientSequence) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewNextClientSequence() *GetNextClientSequence { - return &GetNextClientSequence{ - Sequence: struct{}{}, - } -} - -type GetNextConnectionSequence struct { - Sequence struct{} `json:"get_next_connection_sequence"` -} - -func (x *GetNextConnectionSequence) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewNextConnectionSequence() *GetNextConnectionSequence { - return &GetNextConnectionSequence{ - Sequence: struct{}{}, - } -} - -type GetNextChannelSequence struct { - Sequence struct{} `json:"get_next_channel_sequence"` -} - -func (x *GetNextChannelSequence) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewNextChannelSequence() *GetNextChannelSequence { - return &GetNextChannelSequence{ - Sequence: struct{}{}, - } -} - -type GetAllPorts struct { - AllPorts struct{} `json:"get_all_ports"` -} - -func (x *GetAllPorts) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewGetAllPorts() *GetAllPorts { - return &GetAllPorts{ - AllPorts: struct{}{}, - } -} - -type GetCommitmentPrefix struct { - GetCommitment struct{} `json:"get_commitment_prefix"` -} - -func (x *GetCommitmentPrefix) Bytes() ([]byte, error) { - return json.Marshal(x) -} - -func NewCommitmentPrefix() *GetCommitmentPrefix { - return &GetCommitmentPrefix{ - GetCommitment: struct{}{}, - } -} - -type GetPrevConsensusStateHeight struct { - ConsensusStateByHeight ConsensusStateByHeight `json:"get_previous_consensus_state_height"` -} - -func (x *GetPrevConsensusStateHeight) Bytes() ([]byte, error) { - return json.Marshal(x) +type PacketIdentity struct { + ChannelId string `json:"channel_id"` + PortId string `json:"port_id"` + Sequence uint64 `json:"sequence"` } -func NewPrevConsensusStateHeight(clientId string, height uint64) *GetPrevConsensusStateHeight { - return &GetPrevConsensusStateHeight{ - ConsensusStateByHeight: ConsensusStateByHeight{ - ClientId: clientId, - Height: height, - }, - } +func NewPacketIdentity(ChannelId, PortId string, Sequence uint64) PacketIdentity { + return PacketIdentity{ChannelId, PortId, Sequence} } type RangeParams struct { @@ -310,41 +95,6 @@ type RangeParams struct { EndSequence uint64 `json:"end_sequence"` } -func NewRangeParams(channelId, portId string, startSequence, endSequence uint64) RangeParams { - return RangeParams{ - ChannelId: channelId, - PortId: portId, - StartSequence: startSequence, - EndSequence: endSequence, - } -} - -type PacketMissingReceiptsParams struct { - GetMissingPacketReceipts RangeParams `json:"get_missing_packet_receipts"` -} - -func NewPacketMissingReceiptParams(channelId, portId string, startSequence, endSequence uint64) PacketMissingReceiptsParams { - return PacketMissingReceiptsParams{ - GetMissingPacketReceipts: NewRangeParams(channelId, portId, startSequence, endSequence), - } -} - -type PacketHeightsParams struct { - GetPacketHeights RangeParams `json:"get_packet_heights"` -} - -func NewPacketHeightParams(channelId, portId string, startSequence, endSequence uint64) PacketHeightsParams { - return PacketHeightsParams{ - GetPacketHeights: NewRangeParams(channelId, portId, startSequence, endSequence), - } -} - -type AckHeightsParams struct { - GetPacketHeights RangeParams `json:"get_ack_heights"` -} - -func NewAckHeightParams(channelId, portId string, startSequence, endSequence uint64) AckHeightsParams { - return AckHeightsParams{ - GetPacketHeights: NewRangeParams(channelId, portId, startSequence, endSequence), - } +func NewRangeParams(ChannelId, PortId string, StartSequence, EndSequence uint64) RangeParams { + return RangeParams{ChannelId, PortId, StartSequence, EndSequence} } diff --git a/relayer/chains/wasm/utils.go b/relayer/chains/wasm/utils.go index d842b7a64..fe5bbd35d 100644 --- a/relayer/chains/wasm/utils.go +++ b/relayer/chains/wasm/utils.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "encoding/json" "fmt" - "strconv" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/cosmos/relayer/v2/relayer/common" @@ -24,11 +23,6 @@ func getKeyLength(data string) string { return fmt.Sprintf("%x", buf) } -func byteToInt(b []byte) (int, error) { - return strconv.Atoi(string(b)) - -} - func ProcessContractResponse(p *wasmtypes.QuerySmartContractStateResponse) ([]byte, error) { var output string if err := json.Unmarshal(p.Data.Bytes(), &output); err != nil { From 7e10932090ad21919f203247fa487e4b1a2b8d97 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Sep 2023 19:04:35 +0545 Subject: [PATCH 37/61] feat: add flush unreceived ack logic --- relayer/chains/cosmos/query.go | 3 +- relayer/chains/icon/query.go | 12 +- relayer/chains/penumbra/query.go | 3 +- relayer/chains/wasm/query.go | 6 +- relayer/processor/path_processor_internal.go | 141 ++++++++++--------- relayer/provider/provider.go | 3 +- 6 files changed, 91 insertions(+), 77 deletions(-) diff --git a/relayer/chains/cosmos/query.go b/relayer/chains/cosmos/query.go index 14780b0cb..687deca48 100644 --- a/relayer/chains/cosmos/query.go +++ b/relayer/chains/cosmos/query.go @@ -1175,9 +1175,10 @@ func (ap *CosmosProvider) QueryClientPrevConsensusStateHeight(ctx context.Contex panic("QueryClientPrevConsensusStateHeight not implemented") } -func (ap *CosmosProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { +func (ap *CosmosProvider) QueryPacketMessageByEventHeight(ctx context.Context, eventType, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { panic("QuerySendPacketByHeight not implemented") } + func (ap *CosmosProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.MessageHeights, err error) { panic("QueryPacketHeights not implemented") } diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 33e5fdf5b..3c481a6d3 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -850,7 +850,15 @@ func (icp *IconProvider) QueryMessageHeights(ctx context.Context, methodName str return packetHeights, nil } -func (ap *IconProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { +func (ap *IconProvider) QueryPacketMessageByEventHeight(ctx context.Context, eventType string, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { + var eventName = "" + switch eventType { + case chantypes.EventTypeSendPacket: + eventName = EventTypeSendPacket + case chantypes.EventTypeWriteAck: + eventName = EventTypeWriteAcknowledgement + } + block, err := ap.client.GetBlockByHeight(&types.BlockHeightParam{ Height: types.NewHexInt(int64(seqHeight)), }) @@ -870,7 +878,7 @@ func (ap *IconProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, if el.Addr != types.Address(ap.PCfg.IbcHandlerAddress) && // sendPacket will be of index length 2 len(el.Indexed) != 2 && - el.Indexed[0] != EventTypeSendPacket { + el.Indexed[0] != eventName { continue } packetStr := el.Indexed[1] diff --git a/relayer/chains/penumbra/query.go b/relayer/chains/penumbra/query.go index e214af5f1..0ed2ecbb8 100644 --- a/relayer/chains/penumbra/query.go +++ b/relayer/chains/penumbra/query.go @@ -989,9 +989,10 @@ func (cc *PenumbraProvider) QueryClientPrevConsensusStateHeight(ctx context.Cont panic("QueryClientPrevConsensusStateHeight not implemented") } -func (ap *PenumbraProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { +func (ap *PenumbraProvider) QueryPacketMessageByEventHeight(ctx context.Context, eventType, srcChanID, srcPortID string, sequence uint64, height uint64) (provider.PacketInfo, error) { panic("QuerySendPacketByHeight not implemented") } + func (ap *PenumbraProvider) QueryPacketHeights(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (packetHeights provider.MessageHeights, err error) { panic("QueryPacketHeights not implemented") } diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index cbd70b3f4..301923ff1 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -974,7 +974,7 @@ func (ap *WasmProvider) QueryAckHeights(ctx context.Context, latestHeight int64, return ap.QueryMessageHeights(ctx, MethodGetAckHeights, latestHeight, channelId, portId, startSeq, endSeq) } -func (ap *WasmProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { +func (ap *WasmProvider) QueryPacketMessageByEventHeight(ctx context.Context, eventType, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (provider.PacketInfo, error) { h := int64(seqHeight) blockRes, err := ap.RPCClient.BlockResults(ctx, &h) @@ -990,6 +990,10 @@ func (ap *WasmProvider) QuerySendPacketByHeight(ctx context.Context, srcChanID, } messages := ibcMessagesFromEvents(ap.log, tx.Events, ap.ChainId(), seqHeight, ap.PCfg.IbcHandlerAddress, base64Encoded) for _, m := range messages { + // in case eventtype donot match + if m.eventType != eventType { + continue + } switch t := m.info.(type) { case *packetInfo: packet := provider.PacketInfo(*t) diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index 33d16117b..22d1d470f 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1815,7 +1815,7 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( seq := seq eg.Go(func() error { - sendPacket, err := src.chainProvider.QuerySendPacketByHeight(ctx, k.ChannelID, k.PortID, seq, seqHeight) + sendPacket, err := src.chainProvider.QueryPacketMessageByEventHeight(ctx, chantypes.EventTypeSendPacket, k.ChannelID, k.PortID, seq, seqHeight) if err != nil { return err } @@ -1853,75 +1853,76 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( ) } - // TODO: for ackedMessage - // var unacked []uint64 - - // SeqLoop: - // for _, seq := range seqs { - // for _, unrecvSeq := range unrecv { - // if seq == unrecvSeq { - // continue SeqLoop - // } - // } - // // does not exist in unrecv, so this is an ack that must be written - // unacked = append(unacked, seq) - // } - - // for i, seq := range unacked { - // dstMu.Lock() - // ck := k.Counterparty() - // if dstCache.IsCached(chantypes.EventTypeRecvPacket, ck, seq) && - // dstCache.IsCached(chantypes.EventTypeWriteAck, ck, seq) { - // continue // already cached - // } - // dstMu.Unlock() - - // if i >= maxPacketsPerFlush { - // skipped = true - // break - // } - - // seq := seq - - // dst.log.Debug("Querying recv packet", - // zap.String("channel", k.CounterpartyChannelID), - // zap.String("port", k.CounterpartyPortID), - // zap.Uint64("sequence", seq), - // ) - - // eg.Go(func() error { - // recvPacket, err := dst.chainProvider.QueryRecvPacket(ctx, k.CounterpartyChannelID, k.CounterpartyPortID, seq) - // if err != nil { - // return err - // } - - // ck := k.Counterparty() - // dstMu.Lock() - // dstCache.Cache(chantypes.EventTypeRecvPacket, ck, seq, recvPacket) - // dstCache.Cache(chantypes.EventTypeWriteAck, ck, seq, recvPacket) - // dstMu.Unlock() - - // return nil - // }) - // } - - // if err := eg.Wait(); err != nil { - // return false, err - // } - - // if len(unacked) > 0 { - // dst.log.Debug( - // "Will flush MsgAcknowledgement", - // zap.Object("channel", k), - // zap.Uint64s("sequences", unacked), - // ) - // } else { - // dst.log.Debug( - // "No MsgAcknowledgement to flush", - // zap.String("channel", k.CounterpartyChannelID), - // zap.String("port", k.CounterpartyPortID), - // ) - // } + var unacked []uint64 + + ackHeights, err := dst.chainProvider.QueryAckHeights(ctx, int64(dst.latestBlock.Height), dstChan, dstPort, packetHeights.StartSeq, packetHeights.EndSeq) + if err != nil { + return false, err + } + + counter := 0 + for seq, height := range ackHeights { + + // Is packetHeights is present then Ack not received + // not present means ack already received + _, ok := packetHeights.MessageHeights[seq] + if !ok { + continue + } + + dstMu.Lock() + ck := k.Counterparty() + if dstCache.IsCached(chantypes.EventTypeWriteAck, ck, seq) { + continue // already cached + } + dstMu.Unlock() + + if counter >= maxPacketsPerFlush { + skipped = true + break + } + + seq := seq + + dst.log.Debug("Querying write Ack", + zap.String("channel", k.CounterpartyChannelID), + zap.String("port", k.CounterpartyPortID), + zap.Uint64("sequence", seq), + ) + + eg.Go(func() error { + AckPacket, err := dst.chainProvider.QueryPacketMessageByEventHeight(ctx, chantypes.EventTypeWriteAck, k.CounterpartyChannelID, k.CounterpartyPortID, seq, height) + if err != nil { + return err + } + + ck := k.Counterparty() + dstMu.Lock() + dstCache.Cache(chantypes.EventTypeWriteAck, ck, seq, AckPacket) + dstMu.Unlock() + + return nil + }) + counter++ + } + + if err := eg.Wait(); err != nil { + return false, err + } + + if len(unacked) > 0 { + dst.log.Debug( + "Will flush MsgAcknowledgement", + zap.Object("channel", k), + zap.Uint64s("sequences", unacked), + ) + } else { + dst.log.Debug( + "No MsgAcknowledgement to flush", + zap.String("channel", k.CounterpartyChannelID), + zap.String("port", k.CounterpartyPortID), + ) + } return !skipped, nil } diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 5cec51b09..c7c0c4354 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -438,8 +438,7 @@ type QueryProvider interface { // query packet info for sequence QuerySendPacket(ctx context.Context, srcChanID, srcPortID string, sequence uint64) (PacketInfo, error) QueryRecvPacket(ctx context.Context, dstChanID, dstPortID string, sequence uint64) (PacketInfo, error) - QuerySendPacketByHeight(ctx context.Context, srcChanID, srcPortID string, sequence uint64, seqHeight uint64) (PacketInfo, error) - + QueryPacketMessageByEventHeight(ctx context.Context, eventType string, srcChanID, srcPortID string, sequence uint64, height uint64) (PacketInfo, error) // bank QueryBalance(ctx context.Context, keyName string) (sdk.Coins, error) QueryBalanceWithAddress(ctx context.Context, addr string) (sdk.Coins, error) From fc991ede0e86f12bd369c577199128c55ca8fe84 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 12 Sep 2023 10:08:49 +0545 Subject: [PATCH 38/61] fix: handle wasm query search based on latest height --- relayer/chains/icon/provider.go | 18 ++------- relayer/chains/wasm/provider.go | 1 - relayer/chains/wasm/query.go | 69 ++++++++++++++++----------------- relayer/common/const.go | 1 - 4 files changed, 36 insertions(+), 53 deletions(-) diff --git a/relayer/chains/icon/provider.go b/relayer/chains/icon/provider.go index 45500d536..76dec947e 100644 --- a/relayer/chains/icon/provider.go +++ b/relayer/chains/icon/provider.go @@ -76,6 +76,7 @@ func (pp *IconProviderConfig) Validate() error { return fmt.Errorf("Ibc handler Address cannot be empty") } + // BlockInterval should be in milliseconds if pp.BlockInterval == 0 { return fmt.Errorf("Block interval cannot be zero") } @@ -191,20 +192,6 @@ func (h IconIBCHeader) ShouldUpdateWithZeroMessage() bool { //ChainProvider Methods func (icp *IconProvider) Init(ctx context.Context) error { - // if _, err := os.Stat(icp.PCfg.Keystore); err != nil { - // return err - // } - - // ksByte, err := os.ReadFile(icp.PCfg.Keystore) - // if err != nil { - // return err - // } - - // wallet, err := wallet.NewFromKeyStore(ksByte, []byte(icp.PCfg.Password)) - // if err != nil { - // return err - // } - // icp.AddWallet(wallet) return nil } @@ -225,7 +212,8 @@ func (icp *IconProvider) NewClientState( return nil, fmt.Errorf("Blockinterval cannot be empty in Icon config") } - trustingBlockPeriod := uint64(dstTrustingPeriod) / (icp.PCfg.BlockInterval * uint64(common.NanoToMilliRatio)) + // BlockInterval should be in milliseconds + trustingBlockPeriod := uint64(dstTrustingPeriod) / (icp.PCfg.BlockInterval * uint64(time.Millisecond)) return &icon.ClientState{ // In case of Icon: Trusting Period is block Difference // see: light.proto in ibc-integration diff --git a/relayer/chains/wasm/provider.go b/relayer/chains/wasm/provider.go index 96700c711..3962cf1d7 100644 --- a/relayer/chains/wasm/provider.go +++ b/relayer/chains/wasm/provider.go @@ -361,7 +361,6 @@ func (ap *WasmProvider) Init(ctx context.Context) error { if addr != nil { clientCtx = clientCtx. WithFromAddress(addr) - } ap.QueryClient = wasmtypes.NewQueryClient(clientCtx) diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 301923ff1..9015a1d9d 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -386,6 +386,33 @@ func (ap *WasmProvider) QueryIBCHandlerContractNoRetry(ctx context.Context, para return ProcessContractResponse(resp) } +func (ap *WasmProvider) QueryIBCHandlerContractWithHeight(ctx context.Context, param wasmtypes.RawContractMessage, height int64, response interface{}) error { + + clientCtx := ap.ClientCtx + if height > 0 { + clientCtx = clientCtx.WithHeight(height) + + } + qc := wasmtypes.NewQueryClient(clientCtx) + // holding sdk just before and after + done := ap.SetSDKContext() + r, err := qc.SmartContractState(ctx, &wasmtypes.QuerySmartContractStateRequest{ + Address: ap.PCfg.IbcHandlerAddress, + QueryData: param, + }) + defer done() + if err != nil { + ap.log.Error( + "Failed to query", + zap.Any("Param", param), + zap.Error(err), + ) + return err + } + + return json.Unmarshal(r.Data.Bytes(), &response) +} + func (ap *WasmProvider) QueryIBCHandlerContractProcessed(ctx context.Context, param wasmtypes.RawContractMessage) ([]byte, error) { res, err := ap.QueryIBCHandlerContract(ctx, param) if err != nil { @@ -901,15 +928,8 @@ func (ap *WasmProvider) QueryClientPrevConsensusStateHeight(ctx context.Context, if err != nil { return nil, err } - res, err := ap.QueryIBCHandlerContract(ctx, param) - if err != nil { - return nil, err - } - var heights []int64 - err = json.Unmarshal(res.Data.Bytes(), &heights) - - if err != nil { + if err := ap.QueryIBCHandlerContractWithHeight(ctx, param, chainHeight, &heights); err != nil { return nil, err } @@ -927,13 +947,8 @@ func (ap *WasmProvider) QueryMissingPacketReceipts(ctx context.Context, latestHe return nil, err } - result, err := ap.QueryIBCHandlerContract(ctx, param) - if err != nil { - return nil, err - } - var receipts []uint64 - if err := json.Unmarshal(result.Data.Bytes(), &receipts); err != nil { + if err := ap.QueryIBCHandlerContractWithHeight(ctx, param, latestHeight, &receipts); err != nil { return nil, err } @@ -953,13 +968,8 @@ func (ap *WasmProvider) QueryMessageHeights(ctx context.Context, methodName stri return nil, err } - result, err := ap.QueryIBCHandlerContract(ctx, param) - if err != nil { - return nil, err - } - var packetHeights provider.MessageHeights - if err := json.Unmarshal(result.Data.Bytes(), &packetHeights); err != nil { + if err := ap.QueryIBCHandlerContractWithHeight(ctx, param, latestHeight, &packetHeights); err != nil { return nil, err } @@ -1015,22 +1025,9 @@ func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, chan if err != nil { return 0, err } - clientCtx := ap.ClientCtx - if height > 0 { - clientCtx = clientCtx.WithHeight(height) - - } - qc := wasmtypes.NewQueryClient(clientCtx) - res, err := qc.SmartContractState(ctx, &wasmtypes.QuerySmartContractStateRequest{ - Address: ap.PCfg.IbcHandlerAddress, - QueryData: param, - }) - if err != nil { - return 0, err - } - var seq uint64 - if err := json.Unmarshal(res.Data.Bytes(), &seq); err != nil { + var response uint64 + if err := ap.QueryIBCHandlerContractWithHeight(ctx, param, height, &response); err != nil { return 0, err } - return seq, nil + return response, nil } diff --git a/relayer/common/const.go b/relayer/common/const.go index ab023cd1d..70d638bf7 100644 --- a/relayer/common/const.go +++ b/relayer/common/const.go @@ -14,7 +14,6 @@ var ( ConnectionKey = "connection" ChannelKey = "channel" ONE_HOUR = 60 * 60 * 1000 - NanoToMilliRatio = 1000_000 ) var ( From 2cf0a6c1f9d83cc9739edc3dff81672a4584063a Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 12 Sep 2023 10:09:38 +0545 Subject: [PATCH 39/61] fix: query packet height based on fixed duration --- relayer/processor/path_processor.go | 3 +++ relayer/processor/path_processor_internal.go | 16 ++++++++++++---- relayer/provider/provider.go | 11 +++++------ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/relayer/processor/path_processor.go b/relayer/processor/path_processor.go index 8af8a5358..d5e22a0db 100644 --- a/relayer/processor/path_processor.go +++ b/relayer/processor/path_processor.go @@ -49,6 +49,9 @@ const ( // made to retrieve the client consensus state in order to assemble a // MsgUpdateClient message. clientConsensusHeightUpdateThresholdBlocks = 2 + + // Needed for finding trusting block one week + defaultTrustingPeriod = 7 * 24 * time.Hour ) // PathProcessor is a process that handles incoming IBC messages from a pair of chains. diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index 22d1d470f..e3cbc7aed 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -7,6 +7,7 @@ import ( "fmt" "sort" "sync" + "time" clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" conntypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" @@ -1708,11 +1709,18 @@ func QueryPacketHeights( } startSeq := uint64(0) - if dst.clientState.TrustingPeriodBlock > 0 { - startSeq, err = src.chainProvider.QueryNextSeqSend(ctx, int64(src.latestBlock.Height)-dst.clientState.TrustingPeriodBlock, k.ChannelID, k.PortID) - if err != nil { - return err + if src.chainProvider.ProviderConfig().GetBlockInterval() > 0 { + // blockInterval from provider config will be in milliseconds + blockInterval := int64(src.chainProvider.ProviderConfig().GetBlockInterval()) * int64(time.Millisecond) + startBlock := int64(src.latestBlock.Height) - defaultTrustingPeriod.Nanoseconds()/blockInterval + if startBlock > 0 { + startSeq, err = src.chainProvider.QueryNextSeqSend(ctx, startBlock, k.ChannelID, k.PortID) + if err != nil { + // don't care about error here, + // if error start from startSeq 0 + } } + } c, err := src.chainProvider.QueryPacketHeights(ctx, int64(src.latestBlock.Height), k.ChannelID, k.PortID, startSeq, endSeq) diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index c7c0c4354..a3a0a0fbd 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -69,12 +69,11 @@ type IBCHeader interface { // ClientState holds the current state of a client from a single chain's perspective type ClientState struct { - ClientID string - ConsensusHeight clienttypes.Height - TrustingPeriod time.Duration // trustring period wont be there in ICON client state - ConsensusTime time.Time // consensus time wont be there in ICON light client State - Header []byte // - TrustingPeriodBlock int64 + ClientID string + ConsensusHeight clienttypes.Height + TrustingPeriod time.Duration // trustring period wont be there in ICON client state + ConsensusTime time.Time // consensus time wont be there in ICON light client State + Header []byte // } // ClientTrustedState holds the current state of a client from the perspective of both involved chains, From 2098511d4ae02539d57b274af923e7f5c36ddc7e Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 12 Sep 2023 12:09:49 +0545 Subject: [PATCH 40/61] fix: implement pagination --- relayer/chains/icon/query.go | 86 +++++++++++++++++++++++------------- relayer/common/paginate.go | 41 +++++++++++++++++ 2 files changed, 96 insertions(+), 31 deletions(-) create mode 100644 relayer/common/paginate.go diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 3c481a6d3..cc247649c 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -39,7 +39,8 @@ import ( var _ provider.QueryProvider = &IconProvider{} const ( - epoch = 24 * 3600 * 1000 + epoch = 24 * 3600 * 1000 + sequenceLimit = 2 ) type CallParamOption func(*types.CallParam) @@ -782,26 +783,39 @@ func (icp *IconProvider) QueryPacketReceipt(ctx context.Context, height int64, c } func (icp *IconProvider) QueryMissingPacketReceipts(ctx context.Context, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) ([]uint64, error) { + receipts := make([]uint64, 0) - callParam := icp.prepareCallParams(MethodGetMissingPacketReceipts, map[string]interface{}{ - "portId": portId, - "channelId": channelId, - "startSequence": types.NewHexInt(int64(startSeq)), - "endSequence": types.NewHexInt(int64(endSeq)), - }, callParamsWithHeight(types.NewHexInt(latestHeight))) - - var missingReceipts []types.HexInt - if err := icp.client.Call(callParam, &missingReceipts); err != nil { - return nil, err + if endSeq <= startSeq { + return receipts, fmt.Errorf("start sequence %d is greater than end sequence: %d ", startSeq, endSeq) } - var receipts []uint64 - for _, h := range missingReceipts { - val, err := h.Value() + paginate := common.NewPaginate(startSeq, endSeq, sequenceLimit) + + for paginate.HasNext() { + start, end, err := paginate.Next() if err != nil { return nil, err } - receipts = append(receipts, uint64(val)) + callParam := icp.prepareCallParams(MethodGetMissingPacketReceipts, map[string]interface{}{ + "portId": portId, + "channelId": channelId, + "startSequence": types.NewHexInt(int64(start)), + "endSequence": types.NewHexInt(int64(end)), + }, callParamsWithHeight(types.NewHexInt(latestHeight))) + + var missingReceipts []types.HexInt + if err := icp.client.Call(callParam, &missingReceipts); err != nil { + return nil, err + } + + for _, h := range missingReceipts { + val, err := h.Value() + if err != nil { + return nil, err + } + receipts = append(receipts, uint64(val)) + } + } return receipts, nil @@ -817,36 +831,46 @@ func (icp *IconProvider) QueryAckHeights(ctx context.Context, latestHeight int64 func (icp *IconProvider) QueryMessageHeights(ctx context.Context, methodName string, latestHeight int64, channelId, portId string, startSeq, endSeq uint64) (provider.MessageHeights, error) { + packetHeights := make(provider.MessageHeights, 0) + if methodName != MethodGetPacketHeights && methodName != MethodGetAckHeights { return provider.MessageHeights{}, fmt.Errorf("invalid methodName: %s", methodName) } - callParam := icp.prepareCallParams(methodName, map[string]interface{}{ - "portId": portId, - "channelId": channelId, - "startSequence": types.NewHexInt(int64(startSeq)), - "endSequence": types.NewHexInt(int64(endSeq)), - }, callParamsWithHeight(types.NewHexInt(latestHeight))) - - var rawPacketHeights map[types.HexInt]types.HexInt - if err := icp.client.Call(callParam, &rawPacketHeights); err != nil { - return nil, err + if endSeq <= startSeq { + return provider.MessageHeights{}, fmt.Errorf("start sequence %d is greater than end sequence: %d ", startSeq, endSeq) } - packetHeights := make(provider.MessageHeights, 0) - for seq, h := range rawPacketHeights { - seqInt, err := seq.Value() + paginate := common.NewPaginate(startSeq, endSeq, sequenceLimit) + for paginate.HasNext() { + start, end, err := paginate.Next() if err != nil { return nil, err } - heightInt, err := h.Value() - if err != nil { + + callParam := icp.prepareCallParams(methodName, map[string]interface{}{ + "portId": portId, + "channelId": channelId, + "startSequence": types.NewHexInt(int64(start)), + "endSequence": types.NewHexInt(int64(end)), + }, callParamsWithHeight(types.NewHexInt(latestHeight))) + + var rawPacketHeights map[int64]types.HexInt + if err := icp.client.Call(callParam, &rawPacketHeights); err != nil { return nil, err } - packetHeights[uint64(seqInt)] = uint64(heightInt) + for seq, h := range rawPacketHeights { + heightInt, err := h.Value() + if err != nil { + return nil, err + } + + packetHeights[uint64(seq)] = uint64(heightInt) + } } + return packetHeights, nil } diff --git a/relayer/common/paginate.go b/relayer/common/paginate.go new file mode 100644 index 000000000..6b99d7058 --- /dev/null +++ b/relayer/common/paginate.go @@ -0,0 +1,41 @@ +package common + +import "fmt" + +type Paginate struct { + startSeq uint64 + endSeq uint64 + limit uint64 + page uint64 +} + +func NewPaginate(startSeq, endSeq, limit uint64) *Paginate { + return &Paginate{ + startSeq: startSeq, + endSeq: endSeq, + limit: limit, + page: 0, + } +} + +func (p *Paginate) HasNext() bool { + return p.startSeq <= p.endSeq +} + +func (p *Paginate) Next() (uint64, uint64, error) { + if !p.HasNext() { + return 0, 0, fmt.Errorf("no more pages available") + } + + start := p.startSeq + end := p.startSeq + p.limit - 1 + + if end > p.endSeq { + end = p.endSeq + } + + p.startSeq = end + 1 + p.page++ + + return start, end, nil +} From c310e7984f3e5a14415d1461f9b6e3e2ac663c71 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 18 Sep 2023 17:27:10 +0545 Subject: [PATCH 41/61] fix: find proofContext change heights from last client state to latest block --- relayer/chains/cosmos/query.go | 4 ++ relayer/chains/icon/client.go | 20 +++++++++ relayer/chains/icon/methods.go | 3 ++ relayer/chains/icon/provider.go | 5 +-- relayer/chains/icon/query.go | 64 ++++++++++++++++++++++++++- relayer/chains/icon/types/types.go | 20 +++++++++ relayer/chains/penumbra/query.go | 3 ++ relayer/chains/wasm/query.go | 4 ++ relayer/processor/path_end_runtime.go | 14 ++++++ relayer/provider/provider.go | 3 ++ 10 files changed, 135 insertions(+), 5 deletions(-) diff --git a/relayer/chains/cosmos/query.go b/relayer/chains/cosmos/query.go index 687deca48..ebd98d40e 100644 --- a/relayer/chains/cosmos/query.go +++ b/relayer/chains/cosmos/query.go @@ -1191,3 +1191,7 @@ func (ap *CosmosProvider) QueryMissingPacketReceipts(ctx context.Context, latest func (ap *CosmosProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { panic("QueryNextSeqSend not implemented") } + +func (ap *CosmosProvider) QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, height uint64) ([]uint64, error) { + panic("QueryProofContextChangeHeights not implemented") +} diff --git a/relayer/chains/icon/client.go b/relayer/chains/icon/client.go index 034865743..8b2024c50 100644 --- a/relayer/chains/icon/client.go +++ b/relayer/chains/icon/client.go @@ -64,6 +64,7 @@ type IClient interface { GetLastBlock() (*types.Block, error) GetBlockHeaderByHeight(height int64) (*types.BlockHeader, error) GetValidatorsByHash(hash common.HexHash) ([]common.Address, error) + GetPrepTerm() (*types.PrepTerm, error) } type Client struct { @@ -622,6 +623,25 @@ func (c *Client) EstimateStep(param *types.TransactionParamForEstimate) (*types. return &result, nil } +func (c *Client) GetPrepTerm() (*types.PrepTerm, error) { + + param := types.CallParam{ + FromAddress: types.Address(fmt.Sprintf("hx%s", strings.Repeat("0", 40))), + ToAddress: types.Address(genesisContract), + DataType: "call", + Data: &types.CallData{ + Method: MethodGetPrepTerm, + Params: map[string]string{}, + }, + } + + var op types.PrepTerm + if err := c.Call(¶m, &op); err != nil { + return nil, err + } + return &op, nil +} + func NewClient(uri string, l *zap.Logger) *Client { //TODO options {MaxRetrySendTx, MaxRetryGetResult, MaxIdleConnsPerHost, Debug, Dump} tr := &http.Transport{MaxIdleConnsPerHost: 1000} diff --git a/relayer/chains/icon/methods.go b/relayer/chains/icon/methods.go index 894fae8aa..1c33e4738 100644 --- a/relayer/chains/icon/methods.go +++ b/relayer/chains/icon/methods.go @@ -45,4 +45,7 @@ const ( MethodGetMissingPacketReceipts = "getMissingPacketReceipts" MethodGetPacketHeights = "getPacketHeights" MethodGetAckHeights = "getAckHeights" + + // + MethodGetPrepTerm = "getPRepTerm" ) diff --git a/relayer/chains/icon/provider.go b/relayer/chains/icon/provider.go index 76dec947e..8a975f2a9 100644 --- a/relayer/chains/icon/provider.go +++ b/relayer/chains/icon/provider.go @@ -104,15 +104,14 @@ func (pp *IconProviderConfig) NewProvider(log *zap.Logger, homepath string, debu return nil, err } - codec := MakeCodec(ModuleBasics, []string{}) - return &IconProvider{ log: log.With(zap.String("chain_id", pp.ChainID)), client: NewClient(pp.getRPCAddr(), log), PCfg: pp, StartHeight: uint64(pp.StartHeight), - codec: codec, + codec: MakeCodec(ModuleBasics, []string{}), }, nil + } func (pp IconProviderConfig) getRPCAddr() string { diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index cc247649c..b2536fbc2 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -39,8 +39,9 @@ import ( var _ provider.QueryProvider = &IconProvider{} const ( - epoch = 24 * 3600 * 1000 - sequenceLimit = 2 + epoch = 24 * 3600 * 1000 + sequenceLimit = 2 + genesisContract = "cx0000000000000000000000000000000000000000" ) type CallParamOption func(*types.CallParam) @@ -1015,3 +1016,62 @@ func (icp *IconProvider) HexStringToProtoUnmarshal(encoded string, v proto.Messa return inputBytes, nil } + +func (ip *IconProvider) GetProofContextChangePeriod() (uint64, error) { + // assigning termPeriod + prep, err := ip.client.GetPrepTerm() + if err != nil { + return 0, fmt.Errorf("fail to get prepterm: %v", err) + } + + decentralized, err := prep.IsDecentralized.Value() + if err != nil { + return 0, err + } + + // storing prep-term term only if decentralized + if decentralized == 1 { + period, err := prep.Period.Value() + if err != nil { + return 0, err + } + return uint64(period), nil + + } + return 0, nil +} + +func (ip *IconProvider) QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, latestHeight uint64) ([]uint64, error) { + heights := make([]uint64, 0) + // querying prepterm + + period, err := ip.GetProofContextChangePeriod() + if err != nil { + return heights, err + } + + // 0 suggest that proof context period is not set + if period == 0 { + return heights, nil + } + + // hasn't reached until the latest block + if counterpartyClientHeight+period > latestHeight { + return heights, nil + } + + lastPeriodChangeHeight := counterpartyClientHeight - counterpartyClientHeight%period + + for lastPeriodChangeHeight < latestHeight { + lastPeriodChangeHeight += period + btpblock, err := ip.GetBtpHeader(int64(lastPeriodChangeHeight + 1)) + if err != nil { + continue + } + if btpblock != nil { + heights = append(heights, btpblock.MainHeight) + } + } + + return heights, nil +} diff --git a/relayer/chains/icon/types/types.go b/relayer/chains/icon/types/types.go index 7026f4a54..721a9e851 100644 --- a/relayer/chains/icon/types/types.go +++ b/relayer/chains/icon/types/types.go @@ -666,3 +666,23 @@ func (h *NetworkTypeSection) Encode() []byte { func (h *NetworkTypeSection) Hash() []byte { return relayer_common.Sha3keccak256(h.Encode()) } + +type PrepTerm struct { + BlockHeight HexInt + bondRequirement HexInt + EndBlockHeight HexInt + IissVersion HexInt + Irep HexInt + IsDecentralized HexInt + MainPRepCount HexInt + Period HexInt + Preps interface{} //dont need right now + Revision HexInt + RewardFund interface{} //dont need right now + Rrep HexInt + Sequence HexInt + StartBlockHeight HexInt + TotalDelegated HexInt + TotalPower HexInt + TotalSupply HexInt +} diff --git a/relayer/chains/penumbra/query.go b/relayer/chains/penumbra/query.go index 0ed2ecbb8..76ccdb4e0 100644 --- a/relayer/chains/penumbra/query.go +++ b/relayer/chains/penumbra/query.go @@ -1005,3 +1005,6 @@ func (ap *PenumbraProvider) QueryMissingPacketReceipts(ctx context.Context, late func (ap *PenumbraProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { panic("QueryNextSeqSend not implemented") } +func (ap *PenumbraProvider) QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, height uint64) ([]uint64, error) { + panic("QueryProofContextChangeHeights not implemented") +} diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 9015a1d9d..592f06bce 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -1031,3 +1031,7 @@ func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, chan } return response, nil } + +func (ap *WasmProvider) QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, height uint64) ([]uint64, error) { + panic("QueryProofContextChangeHeights not implemented") +} diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index bebd12eb4..bbb964454 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -391,6 +391,20 @@ func (pathEnd *pathEndRuntime) mergeCacheData(ctx context.Context, cancel func() pathEnd.latestHeader = d.LatestHeader pathEnd.clientState = d.ClientState + // from the last clientState update to latest header + // add all the proof context change height in btp + if d.IsGenesis && pathEnd.chainProvider.Type() == common.IconModule { + + heights, _ := pathEnd.chainProvider.QueryProofContextChangeHeights(ctx, + counterParty.clientState.ConsensusHeight.RevisionHeight, + d.LatestHeader.Height()) + + for _, h := range heights { + pathEnd.BTPHeightQueue.Enqueue(h) + + } + } + if pathEnd.chainProvider.Type() == common.IconModule && d.LatestHeader.IsCompleteBlock() { pathEnd.BTPHeightQueue.Enqueue(d.LatestHeader.Height()) } diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index a3a0a0fbd..c01d90b27 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -483,6 +483,9 @@ type QueryProvider interface { // ics 20 - transfer QueryDenomTrace(ctx context.Context, denom string) (*transfertypes.DenomTrace, error) QueryDenomTraces(ctx context.Context, offset, limit uint64, height int64) ([]transfertypes.DenomTrace, error) + + // For BTP + QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, height uint64) ([]uint64, error) } type RelayPacket interface { From 89b740618f9dfc9852ccfc2953867417fc7065a2 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Fri, 22 Sep 2023 15:55:22 +0545 Subject: [PATCH 42/61] fix: add btp block for all the missing packet if consensus state not present --- relayer/chains/icon/query.go | 2 + relayer/chains/wasm/query.go | 2 +- relayer/chains/wasm/tx.go | 14 +++++++ relayer/processor/path_end_runtime.go | 6 ++- relayer/processor/path_processor_internal.go | 43 ++++++++++++++++++-- 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index b2536fbc2..63f5864e2 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -920,6 +920,8 @@ func (ap *IconProvider) QueryPacketMessageByEventHeight(ctx context.Context, eve continue } return provider.PacketInfo{ + // in case of icon we need to consider btp block because of which if a message is send at height h + // btp header will be in h + 1 Height: seqHeight + 1, Sequence: packet.Sequence, SourcePort: packet.SourcePort, diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 592f06bce..ac46d107b 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -330,7 +330,7 @@ func (ap *WasmProvider) QueryClientConsensusState(ctx context.Context, chainHeig if err != nil { return nil, err } - consensusState, err := ap.QueryIBCHandlerContractProcessed(ctx, param) + consensusState, err := ap.QueryIBCHandlerContractNoRetry(ctx, param) if err != nil { return nil, err } diff --git a/relayer/chains/wasm/tx.go b/relayer/chains/wasm/tx.go index a5ae2406f..455407bec 100644 --- a/relayer/chains/wasm/tx.go +++ b/relayer/chains/wasm/tx.go @@ -744,6 +744,20 @@ func (ap *WasmProvider) SendMessagesToMempool( return err } + if msg.Type() == MethodUpdateClient { + if err := retry.Do(func() error { + if err := ap.BroadcastTx(cliCtx, txBytes, []provider.RelayerMessage{msg}, asyncCtx, defaultBroadcastWaitTimeout, asyncCallback, true); err != nil { + if strings.Contains(err.Error(), sdkerrors.ErrWrongSequence.Error()) { + ap.handleAccountSequenceMismatchError(err) + } + } + return err + }, retry.Context(ctx), rtyAtt, retry.Delay(time.Millisecond*time.Duration(ap.PCfg.BlockInterval)), rtyErr); err != nil { + ap.log.Error("Failed to update client", zap.Any("Message", msg)) + return err + } + continue + } if err := ap.BroadcastTx(cliCtx, txBytes, []provider.RelayerMessage{msg}, asyncCtx, defaultBroadcastWaitTimeout, asyncCallback, false); err != nil { if strings.Contains(err.Error(), sdkerrors.ErrWrongSequence.Error()) { ap.handleAccountSequenceMismatchError(err) diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index bbb964454..c685e3d83 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -393,8 +393,8 @@ func (pathEnd *pathEndRuntime) mergeCacheData(ctx context.Context, cancel func() // from the last clientState update to latest header // add all the proof context change height in btp + // Genesis denotes first time if d.IsGenesis && pathEnd.chainProvider.Type() == common.IconModule { - heights, _ := pathEnd.chainProvider.QueryProofContextChangeHeights(ctx, counterParty.clientState.ConsensusHeight.RevisionHeight, d.LatestHeader.Height()) @@ -487,6 +487,8 @@ func (pathEnd *pathEndRuntime) shouldSendPacketMessage(message packetIBCMessage, pathEnd.log.Debug("Waiting to relay packet message until clientState is updated", zap.Inline(message), zap.String("event_type", eventType), + zap.String("client id", pathEnd.clientState.ClientID), + zap.Uint64("client height", pathEnd.clientState.ConsensusHeight.RevisionHeight), ) return false } @@ -494,6 +496,8 @@ func (pathEnd *pathEndRuntime) shouldSendPacketMessage(message packetIBCMessage, pathEnd.log.Debug("Waiting to relay packet message until clientState is in queue", zap.Inline(message), zap.String("event_type", eventType), + zap.String("client id", pathEnd.clientState.ClientID), + zap.Uint64("client height", pathEnd.clientState.ConsensusHeight.RevisionHeight), ) return false } diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index e3cbc7aed..49893ee4e 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1827,6 +1827,25 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( if err != nil { return err } + + // save btp block if height is Icon + // height+1 + if src.chainProvider.Type() == common.IconModule { + _, err := dst.chainProvider.QueryClientConsensusState(ctx, int64(dst.latestBlock.Height), dst.clientState.ClientID, clienttypes.NewHeight(0, sendPacket.Height)) + if err != nil { + // could mean update client for the message is not present + header, err := src.chainProvider.QueryIBCHeader(ctx, int64(sendPacket.Height)) + if err != nil { + return err + } + if !header.IsCompleteBlock() { + return fmt.Errorf("icon module should have complete block at height: %d because of send packet message: %v", sendPacket.Height, sendPacket) + } + // enqueuing this height + src.BTPHeightQueue.Enqueue(sendPacket.Height) + } + } + srcMu.Lock() srcCache.Cache(chantypes.EventTypeSendPacket, k, seq, sendPacket) srcMu.Unlock() @@ -1838,7 +1857,6 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( zap.String("ctrpty_port", k.CounterpartyPortID), zap.Uint64("sequence", seq), ) - return nil }) // not trying to enqueue btpBlock height if height is missing @@ -1899,14 +1917,33 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( ) eg.Go(func() error { - AckPacket, err := dst.chainProvider.QueryPacketMessageByEventHeight(ctx, chantypes.EventTypeWriteAck, k.CounterpartyChannelID, k.CounterpartyPortID, seq, height) + ackPacket, err := dst.chainProvider.QueryPacketMessageByEventHeight(ctx, chantypes.EventTypeWriteAck, k.CounterpartyChannelID, k.CounterpartyPortID, seq, height) if err != nil { return err } + // save btp block if height is Icon + // height+1 + if src.chainProvider.Type() == common.IconModule { + _, err := dst.chainProvider.QueryClientConsensusState(ctx, int64(dst.latestBlock.Height), dst.clientState.ClientID, clienttypes.NewHeight(0, ackPacket.Height)) + if err != nil { + // could mean update client for the message is not present + header, err := src.chainProvider.QueryIBCHeader(ctx, int64(ackPacket.Height)) + if err != nil { + return err + } + if !header.IsCompleteBlock() { + return fmt.Errorf("icon module should have complete block at height:%d because of send packet message: %v", + ackPacket.Height, ackPacket) + } + // enqueuing this height + src.BTPHeightQueue.Enqueue(ackPacket.Height) + } + } + ck := k.Counterparty() dstMu.Lock() - dstCache.Cache(chantypes.EventTypeWriteAck, ck, seq, AckPacket) + dstCache.Cache(chantypes.EventTypeWriteAck, ck, seq, ackPacket) dstMu.Unlock() return nil From aa4ea1ad8fcb601f34587efc7964ddebc9c39f2d Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Tue, 26 Sep 2023 17:56:17 +0545 Subject: [PATCH 43/61] fix: add btp queue for missing block --- relayer/chains/wasm/query.go | 2 +- relayer/processor/path_end_runtime.go | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index ac46d107b..fcd40bd91 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -876,7 +876,7 @@ func (ap *WasmProvider) QueryPacketReceipt(ctx context.Context, height int64, ch func (ap *WasmProvider) GetCommitmentPrefixFromContract(ctx context.Context) ([]byte, error) { - param, err := types.GenerateQueryParams(MethodGetAllPorts, struct{}{}) + param, err := types.GenerateQueryParams(MethodGetCommitmentPrefix, struct{}{}) if err != nil { return nil, err } diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index c685e3d83..edb3938f2 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -395,13 +395,19 @@ func (pathEnd *pathEndRuntime) mergeCacheData(ctx context.Context, cancel func() // add all the proof context change height in btp // Genesis denotes first time if d.IsGenesis && pathEnd.chainProvider.Type() == common.IconModule { + // need to fetch clientstate height + clientHeight := counterParty.clientState.ConsensusHeight.RevisionHeight + if clientHeight == 0 { + cs, _ := counterParty.chainProvider.QueryClientState(ctx, 0, counterParty.info.ClientID) + clientHeight = cs.GetLatestHeight().GetRevisionHeight() + } + heights, _ := pathEnd.chainProvider.QueryProofContextChangeHeights(ctx, - counterParty.clientState.ConsensusHeight.RevisionHeight, + clientHeight, d.LatestHeader.Height()) for _, h := range heights { pathEnd.BTPHeightQueue.Enqueue(h) - } } From 1ed32296b0486890c7c779277853d2dc2ab82f79 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Thu, 5 Oct 2023 09:25:37 +0545 Subject: [PATCH 44/61] fix: flush ack not handled properly on icon side --- relayer/chains/icon/query.go | 44 +++++++++++++------- relayer/processor/path_processor_internal.go | 16 ++++--- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 63f5864e2..65884d619 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -906,6 +906,13 @@ func (ap *IconProvider) QueryPacketMessageByEventHeight(ctx context.Context, eve el.Indexed[0] != eventName { continue } + // for ack + if eventName == EventTypeWriteAcknowledgement { + if len(el.Data) == 0 || el.Data[0] == "" { + continue + } + } + packetStr := el.Indexed[1] packetByte, err := hex.DecodeString(strings.TrimPrefix(packetStr, "0x")) if err != nil { @@ -916,22 +923,29 @@ func (ap *IconProvider) QueryPacketMessageByEventHeight(ctx context.Context, eve return provider.PacketInfo{}, err } - if packet.Sequence != sequence && packet.SourceChannel != srcChanID && packet.SourcePort != srcPortID { - continue + if packet.Sequence == sequence && packet.SourceChannel == srcChanID && packet.SourcePort == srcPortID { + packet := provider.PacketInfo{ + // in case of icon we need to consider btp block because of which if a message is send at height h + // btp header will be in h + 1 + Height: seqHeight + 1, + Sequence: packet.Sequence, + SourcePort: packet.SourcePort, + SourceChannel: packet.SourceChannel, + DestPort: packet.DestinationPort, + DestChannel: packet.DestinationChannel, + Data: packet.Data, + TimeoutHeight: clienttypes.NewHeight(packet.TimeoutHeight.RevisionNumber, packet.TimeoutHeight.RevisionHeight), + TimeoutTimestamp: packet.TimeoutTimestamp, + } + // adding ack bytes + if eventName == EventTypeWriteAcknowledgement { + packet.Ack, err = hex.DecodeString(strings.TrimPrefix(el.Data[0], "0x")) + if err != nil { + return provider.PacketInfo{}, err + } + } + return packet, nil } - return provider.PacketInfo{ - // in case of icon we need to consider btp block because of which if a message is send at height h - // btp header will be in h + 1 - Height: seqHeight + 1, - Sequence: packet.Sequence, - SourcePort: packet.SourcePort, - SourceChannel: packet.SourceChannel, - DestPort: packet.DestinationPort, - DestChannel: packet.DestinationChannel, - Data: packet.Data, - TimeoutHeight: clienttypes.NewHeight(packet.TimeoutHeight.RevisionNumber, packet.TimeoutHeight.RevisionHeight), - TimeoutTimestamp: packet.TimeoutTimestamp, - }, nil } diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index 49893ee4e..76235e2be 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1908,14 +1908,15 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( break } - seq := seq - dst.log.Debug("Querying write Ack", zap.String("channel", k.CounterpartyChannelID), zap.String("port", k.CounterpartyPortID), zap.Uint64("sequence", seq), + zap.Uint64("height", height), ) + seq := seq + height := height eg.Go(func() error { ackPacket, err := dst.chainProvider.QueryPacketMessageByEventHeight(ctx, chantypes.EventTypeWriteAck, k.CounterpartyChannelID, k.CounterpartyPortID, seq, height) if err != nil { @@ -1924,11 +1925,11 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( // save btp block if height is Icon // height+1 - if src.chainProvider.Type() == common.IconModule { - _, err := dst.chainProvider.QueryClientConsensusState(ctx, int64(dst.latestBlock.Height), dst.clientState.ClientID, clienttypes.NewHeight(0, ackPacket.Height)) + if dst.chainProvider.Type() == common.IconModule { + _, err := src.chainProvider.QueryClientConsensusState(ctx, int64(dst.latestBlock.Height), src.clientState.ClientID, clienttypes.NewHeight(0, ackPacket.Height)) if err != nil { // could mean update client for the message is not present - header, err := src.chainProvider.QueryIBCHeader(ctx, int64(ackPacket.Height)) + header, err := dst.chainProvider.QueryIBCHeader(ctx, int64(ackPacket.Height)) if err != nil { return err } @@ -1936,8 +1937,11 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( return fmt.Errorf("icon module should have complete block at height:%d because of send packet message: %v", ackPacket.Height, ackPacket) } + // enqueuing this height - src.BTPHeightQueue.Enqueue(ackPacket.Height) + if !dst.BTPHeightQueue.ItemExist(ackPacket.Height) { + dst.BTPHeightQueue.Enqueue(ackPacket.Height) + } } } From d262d5d5b1bbe61bb9aa6070b86abeb444c7ea4d Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Thu, 5 Oct 2023 09:26:10 +0545 Subject: [PATCH 45/61] fix: ack on wasm not handled properly --- relayer/chains/wasm/query.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index fcd40bd91..98b7541cf 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -376,11 +376,6 @@ func (ap *WasmProvider) QueryIBCHandlerContractNoRetry(ctx context.Context, para QueryData: param, }) if err != nil { - ap.log.Error( - "Failed to query", - zap.Any("Param", param), - zap.Error(err), - ) return nil, err } return ProcessContractResponse(resp) @@ -1008,6 +1003,11 @@ func (ap *WasmProvider) QueryPacketMessageByEventHeight(ctx context.Context, eve case *packetInfo: packet := provider.PacketInfo(*t) if packet.Sequence == sequence && packet.SourceChannel == srcChanID && packet.SourcePort == srcPortID { + // for ack byte length cannot be empty + if eventType == chantypes.EventTypeAcknowledgePacket && len(packet.Ack) == 0 { + continue + } + return packet, nil } default: From 0150ed7108af4a4333087ca48d95619806c93767 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Thu, 5 Oct 2023 09:26:29 +0545 Subject: [PATCH 46/61] fix: active flush timer --- relayer/processor/path_processor.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relayer/processor/path_processor.go b/relayer/processor/path_processor.go index d5e22a0db..768418c89 100644 --- a/relayer/processor/path_processor.go +++ b/relayer/processor/path_processor.go @@ -314,7 +314,7 @@ func (pp *PathProcessor) processAvailableSignals(ctx context.Context, cancel fun // No new data to merge in, just retry handling. case <-pp.flushTimer.C: // Periodic flush to clear out any old packets - // pp.handleFlush(ctx) + pp.handleFlush(ctx) } return false } @@ -323,7 +323,7 @@ func (pp *PathProcessor) processAvailableSignals(ctx context.Context, cancel fun func (pp *PathProcessor) Run(ctx context.Context, cancel func()) { var retryTimer *time.Timer - pp.flushTimer = time.NewTimer(time.Hour) + pp.flushTimer = time.NewTimer(pp.flushInterval) for { // block until we have any signals to process From f92cede12d2022a4fffe5bfc63acf6fa2d3f0696 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Fri, 1 Dec 2023 15:13:23 +0800 Subject: [PATCH 47/61] feat: add btp proof context change flag --- cmd/flags.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmd/flags.go b/cmd/flags.go index 1f8396899..a5d190902 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -55,6 +55,7 @@ const ( flagSrcConnID = "src-connection-id" flagDstConnID = "dst-connection-id" flagBtpBlockHeight = "btp-block-height" + flagBtpUpdateProofContext = "btp-update-proof-context" ) const ( @@ -390,3 +391,11 @@ func OverwriteConfigFlag(v *viper.Viper, cmd *cobra.Command) *cobra.Command { } return cmd } + +func BtpUpdateProofContextFlag(v *viper.Viper, cmd *cobra.Command) *cobra.Command { + cmd.Flags().BoolP(flagBtpUpdateProofContext, "u", false, "update all proof context change") + if err := v.BindPFlag(flagFlushInterval, cmd.Flags().Lookup(flagFlushInterval)); err != nil { + panic(err) + } + return cmd +} From 3daee450df15e77218529048e329caae312260b5 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Fri, 1 Dec 2023 15:14:28 +0800 Subject: [PATCH 48/61] chore: remove unwanted --- relayer/chains/cosmos/query.go | 4 ---- relayer/chains/penumbra/query.go | 3 --- relayer/chains/wasm/query.go | 4 ---- relayer/provider/provider.go | 3 --- 4 files changed, 14 deletions(-) diff --git a/relayer/chains/cosmos/query.go b/relayer/chains/cosmos/query.go index ebd98d40e..687deca48 100644 --- a/relayer/chains/cosmos/query.go +++ b/relayer/chains/cosmos/query.go @@ -1191,7 +1191,3 @@ func (ap *CosmosProvider) QueryMissingPacketReceipts(ctx context.Context, latest func (ap *CosmosProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { panic("QueryNextSeqSend not implemented") } - -func (ap *CosmosProvider) QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, height uint64) ([]uint64, error) { - panic("QueryProofContextChangeHeights not implemented") -} diff --git a/relayer/chains/penumbra/query.go b/relayer/chains/penumbra/query.go index 76ccdb4e0..0ed2ecbb8 100644 --- a/relayer/chains/penumbra/query.go +++ b/relayer/chains/penumbra/query.go @@ -1005,6 +1005,3 @@ func (ap *PenumbraProvider) QueryMissingPacketReceipts(ctx context.Context, late func (ap *PenumbraProvider) QueryNextSeqSend(ctx context.Context, height int64, channelid, portid string) (seq uint64, err error) { panic("QueryNextSeqSend not implemented") } -func (ap *PenumbraProvider) QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, height uint64) ([]uint64, error) { - panic("QueryProofContextChangeHeights not implemented") -} diff --git a/relayer/chains/wasm/query.go b/relayer/chains/wasm/query.go index 98b7541cf..cd2f2d3d9 100644 --- a/relayer/chains/wasm/query.go +++ b/relayer/chains/wasm/query.go @@ -1031,7 +1031,3 @@ func (ap *WasmProvider) QueryNextSeqSend(ctx context.Context, height int64, chan } return response, nil } - -func (ap *WasmProvider) QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, height uint64) ([]uint64, error) { - panic("QueryProofContextChangeHeights not implemented") -} diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 6cac9eb9c..3bbd3eccb 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -483,9 +483,6 @@ type QueryProvider interface { // ics 20 - transfer QueryDenomTrace(ctx context.Context, denom string) (*transfertypes.DenomTrace, error) QueryDenomTraces(ctx context.Context, offset, limit uint64, height int64) ([]transfertypes.DenomTrace, error) - - // For BTP - QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, height uint64) ([]uint64, error) } type RelayPacket interface { From 539c43572fb298b992901e2b4b372c99d3c3930b Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:44:14 +0800 Subject: [PATCH 49/61] chore: add flag for proof context from height --- cmd/flags.go | 99 ++++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/cmd/flags.go b/cmd/flags.go index a5d190902..a2b6ff07f 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -11,51 +11,52 @@ import ( ) const ( - flagHome = "home" - flagURL = "url" - flagSkip = "skip" - flagTimeout = "timeout" - flagJSON = "json" - flagYAML = "yaml" - flagFile = "file" - flagPath = "path" - flagMaxTxSize = "max-tx-size" - flagMaxMsgLength = "max-msgs" - flagIBCDenoms = "ibc-denoms" - flagTimeoutHeightOffset = "timeout-height-offset" - flagTimeoutTimeOffset = "timeout-time-offset" - flagMaxRetries = "max-retries" - flagThresholdTime = "time-threshold" - flagUpdateAfterExpiry = "update-after-expiry" - flagUpdateAfterMisbehaviour = "update-after-misbehaviour" - flagClientTrustingPeriod = "client-tp" - flagOverride = "override" - flagSrcPort = "src-port" - flagDstPort = "dst-port" - flagOrder = "order" - flagVersion = "version" - flagDebugAddr = "debug-addr" - flagOverwriteConfig = "overwrite" - flagLimit = "limit" - flagHeight = "height" - flagPage = "page" - flagPageKey = "page-key" - flagCountTotal = "count-total" - flagReverse = "reverse" - flagProcessor = "processor" - flagInitialBlockHistory = "block-history" - flagFlushInterval = "flush-interval" - flagMemo = "memo" - flagFilterRule = "filter-rule" - flagFilterChannels = "filter-channels" - flagSrcChainID = "src-chain-id" - flagDstChainID = "dst-chain-id" - flagSrcClientID = "src-client-id" - flagDstClientID = "dst-client-id" - flagSrcConnID = "src-connection-id" - flagDstConnID = "dst-connection-id" - flagBtpBlockHeight = "btp-block-height" - flagBtpUpdateProofContext = "btp-update-proof-context" + flagHome = "home" + flagURL = "url" + flagSkip = "skip" + flagTimeout = "timeout" + flagJSON = "json" + flagYAML = "yaml" + flagFile = "file" + flagPath = "path" + flagMaxTxSize = "max-tx-size" + flagMaxMsgLength = "max-msgs" + flagIBCDenoms = "ibc-denoms" + flagTimeoutHeightOffset = "timeout-height-offset" + flagTimeoutTimeOffset = "timeout-time-offset" + flagMaxRetries = "max-retries" + flagThresholdTime = "time-threshold" + flagUpdateAfterExpiry = "update-after-expiry" + flagUpdateAfterMisbehaviour = "update-after-misbehaviour" + flagClientTrustingPeriod = "client-tp" + flagOverride = "override" + flagSrcPort = "src-port" + flagDstPort = "dst-port" + flagOrder = "order" + flagVersion = "version" + flagDebugAddr = "debug-addr" + flagOverwriteConfig = "overwrite" + flagLimit = "limit" + flagHeight = "height" + flagPage = "page" + flagPageKey = "page-key" + flagCountTotal = "count-total" + flagReverse = "reverse" + flagProcessor = "processor" + flagInitialBlockHistory = "block-history" + flagFlushInterval = "flush-interval" + flagMemo = "memo" + flagFilterRule = "filter-rule" + flagFilterChannels = "filter-channels" + flagSrcChainID = "src-chain-id" + flagDstChainID = "dst-chain-id" + flagSrcClientID = "src-client-id" + flagDstClientID = "dst-client-id" + flagSrcConnID = "src-connection-id" + flagDstConnID = "dst-connection-id" + flagBtpBlockHeight = "btp-block-height" + flagBtpUpdateProofContext = "btp-update-proof-context" + flagBTPUpdateProofContextFromHeight = "btp-update-proof-context-from-height" ) const ( @@ -399,3 +400,11 @@ func BtpUpdateProofContextFlag(v *viper.Viper, cmd *cobra.Command) *cobra.Comman } return cmd } + +func BtpUpdateProofContextFromHeightFlag(v *viper.Viper, cmd *cobra.Command) *cobra.Command { + cmd.Flags().Int64(flagBTPUpdateProofContextFromHeight, 0, "btp update proof context from height") + if err := v.BindPFlag(flagFlushInterval, cmd.Flags().Lookup(flagFlushInterval)); err != nil { + panic(err) + } + return cmd +} From 5d06c2d432b2848ce229d0103c7fd8664eadc79d Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:45:47 +0800 Subject: [PATCH 50/61] feat: update proof context change logic and remove timer to save height --- relayer/channel.go | 12 +-- relayer/connection.go | 4 +- relayer/strategies.go | 241 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 219 insertions(+), 38 deletions(-) diff --git a/relayer/channel.go b/relayer/channel.go index 184ed599c..2f3f32b64 100644 --- a/relayer/channel.go +++ b/relayer/channel.go @@ -71,8 +71,8 @@ func (c *Chain) CreateOpenChannels( return processor.NewEventProcessor(). WithChainProcessors( - c.chainProcessor(c.log, nil, nil), - dst.chainProcessor(c.log, nil, nil), + c.chainProcessor(c.log, nil), + dst.chainProcessor(c.log, nil), ). WithPathProcessors(pp). WithInitialBlockHistory(0). @@ -121,8 +121,8 @@ func (c *Chain) CloseChannel( flushProcessor := processor.NewEventProcessor(). WithChainProcessors( - c.chainProcessor(c.log, nil, nil), - dst.chainProcessor(c.log, nil, nil), + c.chainProcessor(c.log, nil), + dst.chainProcessor(c.log, nil), ). WithPathProcessors(processor.NewPathProcessor( c.log, @@ -159,8 +159,8 @@ func (c *Chain) CloseChannel( return processor.NewEventProcessor(). WithChainProcessors( - c.chainProcessor(c.log, nil, nil), - dst.chainProcessor(c.log, nil, nil), + c.chainProcessor(c.log, nil), + dst.chainProcessor(c.log, nil), ). WithPathProcessors(processor.NewPathProcessor( c.log, diff --git a/relayer/connection.go b/relayer/connection.go index 9c64619cc..df784d504 100644 --- a/relayer/connection.go +++ b/relayer/connection.go @@ -61,8 +61,8 @@ func (c *Chain) CreateOpenConnections( return connectionSrc, connectionDst, processor.NewEventProcessor(). WithChainProcessors( - c.chainProcessor(c.log, nil, nil), - dst.chainProcessor(c.log, nil, nil), + c.chainProcessor(c.log, nil), + dst.chainProcessor(c.log, nil), ). WithPathProcessors(pp). WithInitialBlockHistory(initialBlockHistory). diff --git a/relayer/strategies.go b/relayer/strategies.go index 710589605..b22e88c09 100644 --- a/relayer/strategies.go +++ b/relayer/strategies.go @@ -9,12 +9,16 @@ import ( "time" "github.com/avast/retry-go/v4" + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v7/modules/core/exported" "github.com/cosmos/relayer/v2/relayer/chains/cosmos" "github.com/cosmos/relayer/v2/relayer/chains/icon" penumbraprocessor "github.com/cosmos/relayer/v2/relayer/chains/penumbra" "github.com/cosmos/relayer/v2/relayer/chains/wasm" + "github.com/cosmos/relayer/v2/relayer/common" "github.com/cosmos/relayer/v2/relayer/processor" + "github.com/cosmos/relayer/v2/relayer/provider" "go.uber.org/zap" ) @@ -33,26 +37,26 @@ const ( TwoMB = 2 * 1024 * 1024 ) -func timerChannel(ctx context.Context, log *zap.Logger, timerChan map[string]chan struct{}, chains map[string]*Chain) { - ticker := time.NewTicker(time.Hour) - defer ticker.Stop() - for { - NamedLoop: - select { - case <-ticker.C: - for _, c := range chains { - _, err := c.ChainProvider.QueryLatestHeight(ctx) - if err != nil { - log.Warn("Failed getting status of chain", zap.String("chain_id", c.ChainID()), zap.Error(err)) - break NamedLoop - } - } - for _, c := range timerChan { - c <- struct{}{} - } - } - } -} +// func timerChannel(ctx context.Context, log *zap.Logger, timerChan map[string]chan struct{}, chains map[string]*Chain) { +// ticker := time.NewTicker(time.Hour) +// defer ticker.Stop() +// for { +// NamedLoop: +// select { +// case <-ticker.C: +// for _, c := range chains { +// _, err := c.ChainProvider.QueryLatestHeight(ctx) +// if err != nil { +// log.Warn("Failed getting status of chain", zap.String("chain_id", c.ChainID()), zap.Error(err)) +// break NamedLoop +// } +// } +// for _, c := range timerChan { +// c <- struct{}{} +// } +// } +// } +// } // StartRelayer starts the main relaying loop and returns a channel that will contain any control-flow related errors. func StartRelayer( @@ -70,20 +74,20 @@ func StartRelayer( metrics *processor.PrometheusMetrics, ) chan error { errorChan := make(chan error, 1) - chans := make(map[string]chan struct{}) + // chans := make(map[string]chan struct{}) - for k := range chains { - chans[k] = make(chan struct{}) - } + // for k := range chains { + // chans[k] = make(chan struct{}) + // } - go timerChannel(ctx, log, chans, chains) + // go timerChannel(ctx, log, chans, chains) switch processorType { case ProcessorEvents: chainProcessors := make([]processor.ChainProcessor, 0, len(chains)) - for name, chain := range chains { - chainProcessors = append(chainProcessors, chain.chainProcessor(log, metrics, chans[name])) + for _, chain := range chains { + chainProcessors = append(chainProcessors, chain.chainProcessor(log, metrics)) } ePaths := make([]path, len(paths)) @@ -144,7 +148,7 @@ type path struct { } // chainProcessor returns the corresponding ChainProcessor implementation instance for a pathChain. -func (chain *Chain) chainProcessor(log *zap.Logger, metrics *processor.PrometheusMetrics, timerChan chan struct{}) processor.ChainProcessor { +func (chain *Chain) chainProcessor(log *zap.Logger, metrics *processor.PrometheusMetrics) processor.ChainProcessor { // Handle new ChainProcessor implementations as cases here switch p := chain.ChainProvider.(type) { case *penumbraprocessor.PenumbraProvider: @@ -152,9 +156,9 @@ func (chain *Chain) chainProcessor(log *zap.Logger, metrics *processor.Prometheu case *cosmos.CosmosProvider: return cosmos.NewCosmosChainProcessor(log, p, metrics) case *icon.IconProvider: - return icon.NewIconChainProcessor(log, p, metrics, timerChan) + return icon.NewIconChainProcessor(log, p, metrics) case *wasm.WasmProvider: - return wasm.NewWasmChainProcessor(log, p, metrics, timerChan) + return wasm.NewWasmChainProcessor(log, p, metrics) default: panic(fmt.Errorf("unsupported chain provider type: %T", chain.ChainProvider)) } @@ -552,3 +556,180 @@ func relayUnrelayedAcks(ctx context.Context, log *zap.Logger, src, dst *Chain, m return true } + +type SrcProviderClientState struct { + SrcChainProvider provider.ChainProvider + ClientState exported.ClientState + ClientId string +} + +func RunProofContextUpdate(ctx context.Context, log *zap.Logger, chains map[string]*Chain, paths []NamedPath, fromHeight int64) (uint64, error) { + + log.Info("runProofContextUpdate: started") + + // finding the height to start from + srcProviderClientStates := make([]SrcProviderClientState, 0) + +pathloop: + for _, p := range paths { + + if strings.Contains(p.Path.Src.ClientID, common.IconLightClient) { + // src should be iconchain + chainId := p.Path.Src.ChainID + clientId := p.Path.Src.ClientID + for _, chain := range chains { + if chain.ChainID() == chainId { + // getting clientState + cs, err := chain.ChainProvider.QueryClientState(ctx, 0, clientId) + if err != nil { + log.Debug("error occured when fetching client state", + zap.String("chainid ", chainId), + zap.String("clientid", clientId)) + continue + } + srcProviderClientStates = append(srcProviderClientStates, SrcProviderClientState{ + SrcChainProvider: chain.ChainProvider, + ClientState: cs, + ClientId: clientId, + }) + continue pathloop + } + } + } + + if strings.Contains(p.Path.Dst.ClientID, common.IconLightClient) { + // src should be iconchain + chainId := p.Path.Dst.ChainID + clientId := p.Path.Dst.ClientID + for _, chain := range chains { + if chain.ChainID() == chainId { + // getting clientState + // all the chain 0 should return current height clientState + cs, err := chain.ChainProvider.QueryClientState(ctx, 0, clientId) + if err != nil { + log.Debug("error occured when fetching client state", + zap.String("chainid ", chainId), + zap.String("clientid", clientId)) + continue pathloop + } + srcProviderClientStates = append(srcProviderClientStates, SrcProviderClientState{ + SrcChainProvider: chain.ChainProvider, + ClientState: cs, + ClientId: clientId, + }) + continue pathloop + } + } + } + } + + startQueryHeight := uint64(0) + + if fromHeight > 0 { + startQueryHeight = uint64(fromHeight) + } else { + // find height to query From + for _, chainStruct := range srcProviderClientStates { + if chainStruct.ClientState == nil && chainStruct.ClientState.GetLatestHeight() == nil { + continue + } + h := chainStruct.ClientState.GetLatestHeight().GetRevisionHeight() + if startQueryHeight == 0 { + startQueryHeight = h + } + if h > 0 && startQueryHeight > h { + startQueryHeight = h + } + } + } + + if startQueryHeight == 0 { + return 0, nil + } + + // query all the height until the latest height + var chain provider.ChainProvider + for _, c := range chains { + // assumption: there will be only one icon module config in config.yaml + if strings.Contains(c.ChainProvider.Type(), common.IconModule) { + chain = c.ChainProvider + } + } + + iconChainProvider, ok := chain.(*icon.IconProvider) + if !ok { + return 0, fmt.Errorf("iconChainProvider not found in chain list") + } + + // this will move upto the latest height + btpBlockHeaders, uptoHeight, err := iconChainProvider.GetProofContextChangeHeaders(ctx, startQueryHeight) + if err != nil { + return 0, fmt.Errorf("failed to get proofContextChangeHeight %v", err) + } + + if len(btpBlockHeaders) == 0 { + log.Info("No btpHeight to update: clientContextdidn't changed") + } + + // updateClientMessage and create tx + for _, c := range srcProviderClientStates { + trustedHeight := clienttypes.Height{ + RevisionNumber: c.ClientState.GetLatestHeight().GetRevisionNumber(), + RevisionHeight: c.ClientState.GetLatestHeight().GetRevisionHeight(), + } + for _, blockHeader := range btpBlockHeaders { + + _, err := c.SrcChainProvider.QueryClientConsensusState(ctx, 0, c.ClientId, clienttypes.NewHeight(0, blockHeader.Height())) + if err == nil { + log.Info("clientHeight is already updated", + zap.String("chain id", c.SrcChainProvider.ChainId()), + zap.String("client id ", c.ClientId), + zap.Int64("client height", int64(blockHeader.Height()))) + continue + } + + trustedHeader, err := iconChainProvider.QueryIBCHeader(ctx, int64(trustedHeight.GetRevisionHeight())) + if err != nil { + return 0, fmt.Errorf(" query and update for chain %v", err) + } + + clientMessage, err := iconChainProvider.MsgUpdateClientHeader(blockHeader, trustedHeight, trustedHeader) + if err != nil { + return 0, fmt.Errorf("error occured: %v", err) + } + msg, err := c.SrcChainProvider.MsgUpdateClient(c.ClientId, clientMessage) + if err != nil { + return 0, fmt.Errorf("error occured: %v ", err) + } + + res, sucess, err := c.SrcChainProvider.SendMessage(ctx, msg, "") + if err != nil { + return 0, fmt.Errorf("tx not successfull %v", err) + } + + if !sucess { + return 0, fmt.Errorf("tx not successful, chainId: %s , clientId: %s ", + c.SrcChainProvider.ChainId(), + c.ClientId) + } + + log.Debug("update client successful", + zap.String("chain id ", c.SrcChainProvider.ChainId()), + zap.String("client id ", c.ClientId), + zap.String("txhash", res.TxHash)) + + // updating trustedHeight + cs, err := c.SrcChainProvider.QueryClientState(ctx, 0, c.ClientId) + if err != nil { + return 0, fmt.Errorf("error fetching clientState %v", err) + } + csLatestHeight := cs.GetLatestHeight() + trustedHeight = + clienttypes.Height{ + RevisionNumber: csLatestHeight.GetRevisionNumber(), + RevisionHeight: csLatestHeight.GetRevisionHeight(), + } + } + } + return uptoHeight, nil +} From 71838839aa4e242c58927fd41fa1cb7368f09215 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:46:21 +0800 Subject: [PATCH 51/61] feat: add proof context update logic in start only --- cmd/start.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/cmd/start.go b/cmd/start.go index c2cdf9406..a03c92915 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -26,6 +26,7 @@ import ( "github.com/cosmos/relayer/v2/internal/relaydebug" "github.com/cosmos/relayer/v2/relayer" "github.com/cosmos/relayer/v2/relayer/chains/cosmos" + "github.com/cosmos/relayer/v2/relayer/common" "github.com/cosmos/relayer/v2/relayer/processor" "github.com/spf13/cobra" "go.uber.org/zap" @@ -143,8 +144,24 @@ $ %s start demo-path2 --max-tx-size 10`, appName, appName, appName, appName)), return err } + btpProofContextUpdateFrom, err := cmd.Flags().GetInt64(flagBTPUpdateProofContextFromHeight) + if err != nil { + return err + } + + ctx := cmd.Context() + shouldUpdateProofContext, err := cmd.Flags().GetBool(flagBtpUpdateProofContext) + // runUsing the flag + if shouldUpdateProofContext { + iconStartHeight, err := relayer.RunProofContextUpdate(cmd.Context(), a.log, chains, paths, btpProofContextUpdateFrom) + if err != nil { + return fmt.Errorf("unable to complete proofContextUpdate error: %v", err) + } + ctx = context.WithValue(ctx, common.IconStartHeightFromPreRunContext, iconStartHeight) + } + rlyErrCh := relayer.StartRelayer( - cmd.Context(), + ctx, a.log, chains, paths, @@ -179,5 +196,7 @@ $ %s start demo-path2 --max-tx-size 10`, appName, appName, appName, appName)), cmd = initBlockFlag(a.viper, cmd) cmd = flushIntervalFlag(a.viper, cmd) cmd = memoFlag(a.viper, cmd) + cmd = BtpUpdateProofContextFlag(a.viper, cmd) + cmd = BtpUpdateProofContextFromHeightFlag(a.viper, cmd) return cmd } From 274cd876f9e9ba6aff96c1d9047ff33065943587 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:48:15 +0800 Subject: [PATCH 52/61] feat: iconchainprocessor startheight fetch from context --- relayer/chains/icon/icon_chain_processor.go | 91 ++++++++++----------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/relayer/chains/icon/icon_chain_processor.go b/relayer/chains/icon/icon_chain_processor.go index cc2be0940..ca1b094e2 100644 --- a/relayer/chains/icon/icon_chain_processor.go +++ b/relayer/chains/icon/icon_chain_processor.go @@ -76,7 +76,7 @@ type Verifier struct { prevNetworkSectionHash []byte } -func NewIconChainProcessor(log *zap.Logger, provider *IconProvider, metrics *processor.PrometheusMetrics, heightSnapshot chan struct{}) *IconChainProcessor { +func NewIconChainProcessor(log *zap.Logger, provider *IconProvider, metrics *processor.PrometheusMetrics) *IconChainProcessor { return &IconChainProcessor{ log: log.With(zap.String("chain_name", provider.ChainName()), zap.String("chain_id", provider.ChainId())), chainProvider: provider, @@ -86,7 +86,7 @@ func NewIconChainProcessor(log *zap.Logger, provider *IconProvider, metrics *pro connectionClients: make(map[string]string), channelConnections: make(map[string]string), metrics: metrics, - heightSnapshotChan: heightSnapshot, + // heightSnapshotChan: heightSnapshot, } } @@ -135,12 +135,12 @@ type queryCyclePersistence struct { } func (icp *IconChainProcessor) Run(ctx context.Context, initialBlockHistory uint64) error { - persistence := queryCyclePersistence{ - minQueryLoopDuration: time.Second, - } var eg errgroup.Group + // passing the value from the context + iconStartHeightFromPreRunContext, _ := rlycommon.AnyToInt64(ctx.Value(rlycommon.IconStartHeightFromPreRunContext)) + eg.Go(func() error { return icp.initializeConnectionState(ctx) }) @@ -153,24 +153,24 @@ func (icp *IconChainProcessor) Run(ctx context.Context, initialBlockHistory uint // start_query_cycle icp.log.Debug("Starting query cycle") - err := icp.monitoring(ctx, &persistence) + err := icp.monitoring(ctx, iconStartHeightFromPreRunContext) return err } -func (icp *IconChainProcessor) StartFromHeight(ctx context.Context) int64 { - cfg := icp.Provider().ProviderConfig().(*IconProviderConfig) - - if cfg.StartHeight != 0 { - return cfg.StartHeight - } - snapshotHeight, err := rlycommon.LoadSnapshotHeight(icp.Provider().ChainId()) - if err != nil { - icp.log.Warn("Failed to load height from snapshot", zap.Error(err)) - } else { - icp.log.Info("Obtained start height from config", zap.Int64("height", snapshotHeight)) - } - return snapshotHeight -} +// func (icp *IconChainProcessor) StartFromHeight(ctx context.Context) int64 { +// cfg := icp.Provider().ProviderConfig().(*IconProviderConfig) + +// if cfg.StartHeight != 0 { +// return cfg.StartHeight +// } +// snapshotHeight, err := rlycommon.LoadSnapshotHeight(icp.Provider().ChainId()) +// if err != nil { +// icp.log.Warn("Failed to load height from snapshot", zap.Error(err)) +// } else { +// icp.log.Info("Obtained start height from config", zap.Int64("height", snapshotHeight)) +// } +// return snapshotHeight +// } func (icp *IconChainProcessor) getLastSavedHeight() int64 { snapshotHeight, err := rlycommon.LoadSnapshotHeight(icp.Provider().ChainId()) @@ -253,7 +253,7 @@ func (icp *IconChainProcessor) GetLatestHeight() uint64 { return icp.latestBlock.Height } -func (icp *IconChainProcessor) monitoring(ctx context.Context, persistence *queryCyclePersistence) error { +func (icp *IconChainProcessor) monitoring(ctx context.Context, startFromHeight int64) error { errCh := make(chan error) // error channel reconnectCh := make(chan struct{}, 1) // reconnect channel @@ -274,7 +274,7 @@ func (icp *IconChainProcessor) monitoring(ctx context.Context, persistence *quer } var err error - processedheight := icp.StartFromHeight(ctx) + processedheight := startFromHeight latestHeight, err := icp.chainProvider.QueryLatestHeight(ctx) if err != nil { icp.log.Error("Error fetching block", zap.Error(err)) @@ -311,8 +311,8 @@ loop: case err := <-errCh: return err - case <-icp.heightSnapshotChan: - icp.SnapshotHeight(icp.getHeightToSave(int64(icp.latestBlock.Height))) + // case <-icp.heightSnapshotChan: + // icp.SnapshotHeight(icp.getHeightToSave(int64(icp.latestBlock.Height))) case <-reconnectCh: cancelMonitorBlock() @@ -329,10 +329,10 @@ loop: }, func(conn *websocket.Conn) { }, func(conn *websocket.Conn, err error) {}) if err != nil { - ht := icp.getHeightToSave(processedheight) - if ht != icp.getLastSavedHeight() { - icp.SnapshotHeight(ht) - } + // ht := icp.getHeightToSave(processedheight) + // if ht != icp.getLastSavedHeight() { + // icp.SnapshotHeight(ht) + // } if errors.Is(err, context.Canceled) { return } @@ -379,9 +379,6 @@ loop: break } time.Sleep(10 * time.Millisecond) - if icp.firstTime { - time.Sleep(4000 * time.Millisecond) - } icp.firstTime = false if br = nil; len(btpBlockRespCh) > 0 { br = <-btpBlockRespCh @@ -476,22 +473,22 @@ loop: } } -func (icp *IconChainProcessor) getHeightToSave(height int64) int64 { - retryAfter := icp.Provider().ProviderConfig().GetFirstRetryBlockAfter() - ht := height - int64(retryAfter) - if ht < 0 { - return 0 - } - return ht -} - -func (icp *IconChainProcessor) SnapshotHeight(height int64) { - icp.log.Info("Save height for snapshot", zap.Int64("height", height)) - err := rlycommon.SnapshotHeight(icp.Provider().ChainId(), height) - if err != nil { - icp.log.Warn("Failed saving height snapshot for height", zap.Int64("height", height)) - } -} +// func (icp *IconChainProcessor) getHeightToSave(height int64) int64 { +// retryAfter := icp.Provider().ProviderConfig().GetFirstRetryBlockAfter() +// ht := height - int64(retryAfter) +// if ht < 0 { +// return 0 +// } +// return ht +// } + +// func (icp *IconChainProcessor) SnapshotHeight(height int64) { +// icp.log.Info("Save height for snapshot", zap.Int64("height", height)) +// err := rlycommon.SnapshotHeight(icp.Provider().ChainId(), height) +// if err != nil { +// icp.log.Warn("Failed saving height snapshot for height", zap.Int64("height", height)) +// } +// } func (icp *IconChainProcessor) verifyBlock(ctx context.Context, ibcHeader provider.IBCHeader) error { header, ok := ibcHeader.(IconIBCHeader) From 6a83caac7179206e8ed80797241044a37b5ccff4 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:49:27 +0800 Subject: [PATCH 53/61] feat: remove start height from IconproviderConfig-> always run from latest height --- relayer/chains/icon/provider.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/relayer/chains/icon/provider.go b/relayer/chains/icon/provider.go index 6fc530af7..e95a31e2f 100644 --- a/relayer/chains/icon/provider.go +++ b/relayer/chains/icon/provider.go @@ -51,17 +51,17 @@ var ( * KeyDirectory/Keystore.json */ type IconProviderConfig struct { - KeyDirectory string `json:"key-directory" yaml:"key-directory"` - ChainName string `json:"-" yaml:"-"` - ChainID string `json:"chain-id" yaml:"chain-id"` - RPCAddr string `json:"rpc-addr" yaml:"rpc-addr"` - Timeout string `json:"timeout" yaml:"timeout"` - Keystore string `json:"keystore" yaml:"keystore"` - Password string `json:"password" yaml:"password"` - ICONNetworkID int64 `json:"icon-network-id" yaml:"icon-network-id" default:"3"` - BTPNetworkID int64 `json:"btp-network-id" yaml:"btp-network-id"` - BTPNetworkTypeID int64 `json:"btp-network-type-id" yaml:"btp-network-type-id"` - StartHeight int64 `json:"start-height" yaml:"start-height"` + KeyDirectory string `json:"key-directory" yaml:"key-directory"` + ChainName string `json:"-" yaml:"-"` + ChainID string `json:"chain-id" yaml:"chain-id"` + RPCAddr string `json:"rpc-addr" yaml:"rpc-addr"` + Timeout string `json:"timeout" yaml:"timeout"` + Keystore string `json:"keystore" yaml:"keystore"` + Password string `json:"password" yaml:"password"` + ICONNetworkID int64 `json:"icon-network-id" yaml:"icon-network-id" default:"3"` + BTPNetworkID int64 `json:"btp-network-id" yaml:"btp-network-id"` + BTPNetworkTypeID int64 `json:"btp-network-type-id" yaml:"btp-network-type-id"` + // StartHeight int64 `json:"start-height" yaml:"start-height"` IbcHandlerAddress string `json:"ibc-handler-address" yaml:"ibc-handler-address"` FirstRetryBlockAfter uint64 `json:"first-retry-block-after" yaml:"first-retry-block-after"` BlockInterval uint64 `json:"block-interval" yaml:"block-interval"` @@ -105,11 +105,11 @@ func (pp *IconProviderConfig) NewProvider(log *zap.Logger, homepath string, debu } return &IconProvider{ - log: log.With(zap.String("chain_id", pp.ChainID)), - client: NewClient(pp.getRPCAddr(), log), - PCfg: pp, - StartHeight: uint64(pp.StartHeight), - codec: MakeCodec(ModuleBasics, []string{}), + log: log.With(zap.String("chain_id", pp.ChainID)), + client: NewClient(pp.getRPCAddr(), log), + PCfg: pp, + // StartHeight: uint64(pp.StartHeight), + codec: MakeCodec(ModuleBasics, []string{}), }, nil } From 683a508dda2bdf6d1811c46a1958a5352b626f90 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:53:46 +0800 Subject: [PATCH 54/61] feat: icon find proofContextChange from height --- relayer/chains/icon/query.go | 225 +++++++++++++++++++++++++++++++---- 1 file changed, 205 insertions(+), 20 deletions(-) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index e6e208a35..16d7f8ac4 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" "math/big" + "sort" "strings" "time" @@ -14,6 +15,7 @@ import ( "github.com/cosmos/gogoproto/proto" "github.com/cosmos/ibc-go/v7/modules/core/exported" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + "github.com/gorilla/websocket" "github.com/pkg/errors" "go.uber.org/zap" @@ -1057,37 +1059,220 @@ func (ip *IconProvider) GetProofContextChangePeriod() (uint64, error) { return 0, nil } -func (ip *IconProvider) QueryProofContextChangeHeights(ctx context.Context, counterpartyClientHeight uint64, latestHeight uint64) ([]uint64, error) { - heights := make([]uint64, 0) - // querying prepterm +func (icp *IconProvider) GetProofContextChangeHeaders(ctx context.Context, afterHeight uint64) ([]provider.IBCHeader, uint64, error) { + proofContextChangeHeights := make([]provider.IBCHeader, 0) - period, err := ip.GetProofContextChangePeriod() + logTicker := time.NewTicker(10 * time.Second) + + errCh := make(chan error) // error channel + reconnectCh := make(chan struct{}, 1) // reconnect channel + btpBlockNotifCh := make(chan *types.BlockNotification, 10) // block notification channel + btpBlockRespCh := make(chan *btpBlockResponse, cap(btpBlockNotifCh)) // block result channel + + // uptoHeight + uptoHeight, err := icp.QueryLatestHeight(ctx) if err != nil { - return heights, err + return nil, 0, fmt.Errorf("error fetching latest height %v", err) } - // 0 suggest that proof context period is not set - if period == 0 { - return heights, nil + reconnect := func() { + select { + case reconnectCh <- struct{}{}: + default: + } + for len(btpBlockRespCh) > 0 || len(btpBlockNotifCh) > 0 { + select { + case <-btpBlockRespCh: // clear block result channel + case <-btpBlockNotifCh: // clear block notification channel + } + } } - // hasn't reached until the latest block - if counterpartyClientHeight+period > latestHeight { - return heights, nil + icp.log.Info("Start to check from height", zap.Int64("height", int64(afterHeight))) + // subscribe to monitor block + ctxMonitorBlock, cancelMonitorBlock := context.WithCancel(ctx) + reconnect() + + processedheight := int64(afterHeight) + 1 + + blockReq := &types.BlockRequest{ + Height: types.NewHexInt(processedheight), } - lastPeriodChangeHeight := counterpartyClientHeight - counterpartyClientHeight%period +loop: + for { + select { + case <-ctx.Done(): + return nil, 0, nil + case err := <-errCh: + return nil, 0, err - for lastPeriodChangeHeight < latestHeight { - lastPeriodChangeHeight += period - btpblock, err := ip.GetBtpHeader(int64(lastPeriodChangeHeight + 1)) - if err != nil { - continue + // this ticker is just to show log + case <-logTicker.C: + // fetching latest height also + h, _ := icp.QueryLatestHeight(ctx) + if h > 0 { + uptoHeight = h + icp.log.Info("finding proof context change height continues...", + zap.Int64("reached height", processedheight)) + } + + case <-reconnectCh: + cancelMonitorBlock() + ctxMonitorBlock, cancelMonitorBlock = context.WithCancel(ctx) + + go func(ctx context.Context, cancel context.CancelFunc) { + blockReq.Height = types.NewHexInt(processedheight) + err := icp.client.MonitorBlock(ctx, blockReq, func(conn *websocket.Conn, v *types.BlockNotification) error { + if !errors.Is(ctx.Err(), context.Canceled) { + btpBlockNotifCh <- v + } + return nil + }, func(conn *websocket.Conn) { + }, func(conn *websocket.Conn, err error) {}) + if err != nil { + if errors.Is(err, context.Canceled) { + return + } + time.Sleep(time.Second * 5) + reconnect() + } + + }(ctxMonitorBlock, cancelMonitorBlock) + case br := <-btpBlockRespCh: + for ; br != nil; processedheight++ { + + if br.Header.ShouldUpdateForProofContextChange() { + icp.log.Info("proof context changed at", zap.Int64("height", int64(br.Header.MainHeight))) + proofContextChangeHeights = append(proofContextChangeHeights, br.Header) + } + // process completed + if br.Header.Height() == uint64(uptoHeight) { + return proofContextChangeHeights, uint64(uptoHeight), nil + } + + if br = nil; len(btpBlockRespCh) > 0 { + br = <-btpBlockRespCh + } + } + // remove unprocessed blockResponses + for len(btpBlockRespCh) > 0 { + <-btpBlockRespCh + } + + default: + select { + default: + case bn := <-btpBlockNotifCh: + requestCh := make(chan *btpBlockRequest, cap(btpBlockNotifCh)) + for i := int64(0); bn != nil; i++ { + height, err := bn.Height.Value() + if err != nil { + return nil, 0, err + } else if height != processedheight+i { + icp.log.Warn("Reconnect: missing block notification", + zap.Int64("got", height), + zap.Int64("expected", processedheight+i), + ) + reconnect() + continue loop + } + + requestCh <- &btpBlockRequest{ + height: height, + hash: bn.Hash, + indexes: bn.Indexes, + events: bn.Events, + retry: queryRetries, + } + if bn = nil; len(btpBlockNotifCh) > 0 && len(requestCh) < cap(requestCh) { + bn = <-btpBlockNotifCh + } + } + + brs := make([]*btpBlockResponse, 0, len(requestCh)) + for request := range requestCh { + switch { + case request.err != nil: + if request.retry > 0 { + request.retry-- + request.response, request.err = nil, nil + requestCh <- request + continue + } + icp.log.Info("Request error ", + zap.Any("height", request.height), + zap.Error(request.err)) + brs = append(brs, nil) + if len(brs) == cap(brs) { + close(requestCh) + } + case request.response != nil: + brs = append(brs, request.response) + if len(brs) == cap(brs) { + close(requestCh) + } + default: + go icp.handleBlockRequest(request, requestCh) + + } + + } + // filter nil + _brs, brs := brs, brs[:0] + for _, v := range _brs { + if v.IsProcessed == processed { + brs = append(brs, v) + } + } + + // sort and forward notifications + if len(brs) > 0 { + sort.SliceStable(brs, func(i, j int) bool { + return brs[i].Height < brs[j].Height + }) + for i, d := range brs { + if d.Height == processedheight+int64(i) { + btpBlockRespCh <- d + } + } + } + + } } - if btpblock != nil { - heights = append(heights, btpblock.MainHeight) + } +} + +func (icp *IconProvider) handleBlockRequest( + request *btpBlockRequest, requestCh chan *btpBlockRequest) { + defer func() { + time.Sleep(500 * time.Millisecond) + requestCh <- request + }() + + if request.response == nil { + request.response = &btpBlockResponse{ + IsProcessed: notProcessed, + Height: request.height, } } - return heights, nil + validators, err := icp.GetProofContextByHeight(request.height) + if err != nil { + request.err = errors.Wrapf(err, "Failed to get proof context: %v", err) + return + } + + btpHeader, err := icp.GetBtpHeader(request.height) + if err != nil { + if btpBlockNotPresent(err) { + request.response.Header = NewIconIBCHeader(nil, validators, (request.height)) + request.response.IsProcessed = processed + return + } + request.err = errors.Wrapf(err, "Failed to get btp header: %v", err) + return + } + request.response.Header = NewIconIBCHeader(btpHeader, validators, int64(btpHeader.MainHeight)) + request.response.IsProcessed = processed } From e857e488533ab220ff3cc723a985bef89c832d7c Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:55:14 +0800 Subject: [PATCH 55/61] feat: wasm chain add concurrency and remove start height --- relayer/chains/wasm/provider.go | 5 +- relayer/chains/wasm/wasm_chain_processor.go | 91 +++++++++++---------- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/relayer/chains/wasm/provider.go b/relayer/chains/wasm/provider.go index e2bed8727..475ad6334 100644 --- a/relayer/chains/wasm/provider.go +++ b/relayer/chains/wasm/provider.go @@ -70,8 +70,9 @@ type WasmProviderConfig struct { Broadcast provider.BroadcastMode `json:"broadcast-mode" yaml:"broadcast-mode"` IbcHandlerAddress string `json:"ibc-handler-address" yaml:"ibc-handler-address"` FirstRetryBlockAfter uint64 `json:"first-retry-block-after" yaml:"first-retry-block-after"` - StartHeight uint64 `json:"start-height" yaml:"start-height"` - BlockInterval uint64 `json:"block-interval" yaml:"block-interval"` + // StartHeight uint64 `json:"start-height" yaml:"start-height"` + BlockInterval uint64 `json:"block-interval" yaml:"block-interval"` + Concurrency int64 `json:"concurrency" yaml:"concurrency"` } type WasmIBCHeader struct { diff --git a/relayer/chains/wasm/wasm_chain_processor.go b/relayer/chains/wasm/wasm_chain_processor.go index 0eb2712d9..f8386bae2 100644 --- a/relayer/chains/wasm/wasm_chain_processor.go +++ b/relayer/chains/wasm/wasm_chain_processor.go @@ -13,7 +13,6 @@ import ( clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" conntypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" chantypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - "github.com/cosmos/relayer/v2/relayer/common" "github.com/cosmos/relayer/v2/relayer/processor" "github.com/cosmos/relayer/v2/relayer/provider" @@ -59,14 +58,14 @@ type WasmChainProcessor struct { verifier *Verifier - heightSnapshotChan chan struct{} + // heightSnapshotChan chan struct{} } type Verifier struct { Header *types.LightBlock } -func NewWasmChainProcessor(log *zap.Logger, provider *WasmProvider, metrics *processor.PrometheusMetrics, heightSnapshot chan struct{}) *WasmChainProcessor { +func NewWasmChainProcessor(log *zap.Logger, provider *WasmProvider, metrics *processor.PrometheusMetrics) *WasmChainProcessor { return &WasmChainProcessor{ log: log.With(zap.String("chain_name", provider.ChainName()), zap.String("chain_id", provider.ChainId())), chainProvider: provider, @@ -76,7 +75,7 @@ func NewWasmChainProcessor(log *zap.Logger, provider *WasmProvider, metrics *pro connectionClients: make(map[string]string), channelConnections: make(map[string]string), metrics: metrics, - heightSnapshotChan: heightSnapshot, + // heightSnapshotChan: heightSnapshot, } } @@ -90,7 +89,7 @@ const ( defaultMinQueryLoopDuration = 1 * time.Second defaultBalanceUpdateWaitDuration = 60 * time.Second inSyncNumBlocksThreshold = 2 - MaxBlockFetch = 100 + MaxBlockFetch = 10000 ) // latestClientState is a map of clientID to the latest clientInfo for that client. @@ -203,19 +202,19 @@ type queryCyclePersistence struct { balanceUpdateWaitDuration time.Duration } -func (ccp *WasmChainProcessor) StartFromHeight(ctx context.Context) int64 { - cfg := ccp.Provider().ProviderConfig().(*WasmProviderConfig) - if cfg.StartHeight != 0 { - return int64(cfg.StartHeight) - } - snapshotHeight, err := common.LoadSnapshotHeight(ccp.Provider().ChainId()) - if err != nil { - ccp.log.Warn("Failed to load height from snapshot", zap.Error(err)) - } else { - ccp.log.Info("Obtained start height from config", zap.Int64("height", snapshotHeight)) - } - return snapshotHeight -} +// func (ccp *WasmChainProcessor) StartFromHeight(ctx context.Context) int64 { +// cfg := ccp.Provider().ProviderConfig().(*WasmProviderConfig) +// if cfg.StartHeight != 0 { +// return int64(cfg.StartHeight) +// } +// snapshotHeight, err := common.LoadSnapshotHeight(ccp.Provider().ChainId()) +// if err != nil { +// ccp.log.Warn("Failed to load height from snapshot", zap.Error(err)) +// } else { +// ccp.log.Info("Obtained start height from config", zap.Int64("height", snapshotHeight)) +// } +// return snapshotHeight +// } // Run starts the query loop for the chain which will gather applicable ibc messages and push events out to the relevant PathProcessors. // The initialBlockHistory parameter determines how many historical blocks should be fetched and processed before continuing with current blocks. @@ -247,14 +246,14 @@ func (ccp *WasmChainProcessor) Run(ctx context.Context, initialBlockHistory uint } // this will make initial QueryLoop iteration look back initialBlockHistory blocks in history - latestQueriedBlock := ccp.StartFromHeight(ctx) - if latestQueriedBlock <= 0 || latestQueriedBlock > persistence.latestHeight { - latestQueriedBlock = persistence.latestHeight - } + // latestQueriedBlock := ccp.StartFromHeight(ctx) + // if latestQueriedBlock <= 0 || latestQueriedBlock > persistence.latestHeight { + // latestQueriedBlock = persistence.latestHeight + // } - persistence.latestQueriedBlock = int64(latestQueriedBlock) + persistence.latestQueriedBlock = int64(persistence.latestHeight) - ccp.log.Info("Start to query from height ", zap.Int64("height", latestQueriedBlock)) + ccp.log.Info("Start to query from height ", zap.Int64("height", persistence.latestQueriedBlock)) _, lightBlock, err := ccp.chainProvider.QueryLightBlock(ctx, persistence.latestQueriedBlock) if err != nil { @@ -292,8 +291,8 @@ func (ccp *WasmChainProcessor) Run(ctx context.Context, initialBlockHistory uint select { case <-ctx.Done(): return nil - case <-ccp.heightSnapshotChan: - ccp.SnapshotHeight(ccp.getHeightToSave(persistence.latestHeight)) + // case <-ccp.heightSnapshotChan: + // ccp.SnapshotHeight(ccp.getHeightToSave(persistence.latestHeight)) case <-ticker.C: ticker.Reset(persistence.minQueryLoopDuration) } @@ -405,9 +404,15 @@ func (ccp *WasmChainProcessor) queryCycle(ctx context.Context, persistence *quer chainID := ccp.chainProvider.ChainId() var latestHeader provider.IBCHeader + // max number of block that can be processed at a time + concurrency := ccp.chainProvider.PCfg.Concurrency + if concurrency <= 0 || concurrency > MaxBlockFetch { + concurrency = MaxBlockFetch + } + syncUpHeight := func() int64 { - if persistence.latestHeight-persistence.latestQueriedBlock > MaxBlockFetch { - return persistence.latestQueriedBlock + MaxBlockFetch + if persistence.latestHeight-persistence.latestQueriedBlock > concurrency { + return persistence.latestQueriedBlock + concurrency } return persistence.latestHeight } @@ -519,22 +524,22 @@ func (ccp *WasmChainProcessor) queryCycle(ctx context.Context, persistence *quer return nil } -func (ccp *WasmChainProcessor) getHeightToSave(height int64) int64 { - retryAfter := ccp.Provider().ProviderConfig().GetFirstRetryBlockAfter() - ht := height - int64(retryAfter) - if ht < 0 { - return 0 - } - return ht -} +// func (ccp *WasmChainProcessor) getHeightToSave(height int64) int64 { +// retryAfter := ccp.Provider().ProviderConfig().GetFirstRetryBlockAfter() +// ht := height - int64(retryAfter) +// if ht < 0 { +// return 0 +// } +// return ht +// } -func (ccp *WasmChainProcessor) SnapshotHeight(height int64) { - ccp.log.Info("Save height for snapshot", zap.Int64("height", height)) - err := common.SnapshotHeight(ccp.Provider().ChainId(), height) - if err != nil { - ccp.log.Warn("Failed saving height snapshot for height", zap.Int64("height", height)) - } -} +// func (ccp *WasmChainProcessor) SnapshotHeight(height int64) { +// ccp.log.Info("Save height for snapshot", zap.Int64("height", height)) +// err := common.SnapshotHeight(ccp.Provider().ChainId(), height) +// if err != nil { +// ccp.log.Warn("Failed saving height snapshot for height", zap.Int64("height", height)) +// } +// } func (ccp *WasmChainProcessor) CollectMetrics(ctx context.Context, persistence *queryCyclePersistence) { ccp.CurrentBlockHeight(ctx, persistence) From e3a21f892224fecedf63fa25cf1b601b216bf419 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:55:37 +0800 Subject: [PATCH 56/61] chore: add constant --- relayer/common/const.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/relayer/common/const.go b/relayer/common/const.go index 70d638bf7..f2923c161 100644 --- a/relayer/common/const.go +++ b/relayer/common/const.go @@ -6,14 +6,15 @@ import ( ) var ( - EventTimeoutRequest = "TimeoutRequest(bytes)" - IconModule = "icon" - WasmModule = "wasm" - TendermintLightClient = "07-tendermint" - IconLightClient = "iconclient" - ConnectionKey = "connection" - ChannelKey = "channel" - ONE_HOUR = 60 * 60 * 1000 + EventTimeoutRequest = "TimeoutRequest(bytes)" + IconModule = "icon" + WasmModule = "wasm" + TendermintLightClient = "07-tendermint" + IconLightClient = "iconclient" + ConnectionKey = "connection" + ChannelKey = "channel" + ONE_HOUR = 60 * 60 * 1000 + IconStartHeightFromPreRunContext = "icon-start-height-from-prerun-context" ) var ( From a90276535bdef098cd604bb3824d1d9db724a0e8 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:55:55 +0800 Subject: [PATCH 57/61] chore: helper method added --- relayer/common/utils.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/relayer/common/utils.go b/relayer/common/utils.go index 47b4ee60c..8f2ea56af 100644 --- a/relayer/common/utils.go +++ b/relayer/common/utils.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path" + "reflect" "strconv" "strings" ) @@ -58,3 +59,19 @@ func LoadSnapshotHeight(chain_id string) (int64, error) { } return strconv.ParseInt(strings.TrimSuffix(string(content), "\n"), 10, 64) } + +func AnyToInt64(value interface{}) (int64, error) { + switch v := reflect.ValueOf(value); v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return int64(v.Uint()), nil + case reflect.Float32, reflect.Float64: + return int64(v.Float()), nil + case reflect.String: + // Parse the string as an int64 + return strconv.ParseInt(v.String(), 10, 64) + default: + return 0, fmt.Errorf("unsupported type: %v", v.Kind()) + } +} From b3b44e8b6c2a72080349db2ffc65488dc71c9c6c Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 10:56:39 +0800 Subject: [PATCH 58/61] chore: removed HeightSnapshot logic --- relayer/processor/chain_processor.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relayer/processor/chain_processor.go b/relayer/processor/chain_processor.go index 5637a47ce..7b1ea825a 100644 --- a/relayer/processor/chain_processor.go +++ b/relayer/processor/chain_processor.go @@ -23,11 +23,11 @@ type ChainProcessor interface { // Take snapshot of height every N blocks or when the chain processor fails, so that the relayer // can restart from that height - SnapshotHeight(height int64) + // SnapshotHeight(height int64) // If the relay goes down, start chain processor from height returned by this function // CAN return max(snapshotHeight, latestHeightFromClient) - StartFromHeight(ctx context.Context) int64 + // StartFromHeight(ctx context.Context) int64 } // ChainProcessors is a slice of ChainProcessor instances. From c584766c7d8d80640d120a9843b2a3c7c8756078 Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 11:49:48 +0800 Subject: [PATCH 59/61] chore: update example config --- examples/config_IBC_ICON.yaml | 110 ++++++++++----------- examples/demo/configs/chains/ibc-icon.json | 1 - examples/demo/configs/chains/ibc-wasm.json | 4 +- relayer/strategies.go | 2 +- 4 files changed, 57 insertions(+), 60 deletions(-) diff --git a/examples/config_IBC_ICON.yaml b/examples/config_IBC_ICON.yaml index d0f69c19b..9f2f68ec1 100644 --- a/examples/config_IBC_ICON.yaml +++ b/examples/config_IBC_ICON.yaml @@ -1,59 +1,57 @@ global: - api-listen-addr: :5183 - timeout: 10s - memo: "" - light-cache-size: 20 + api-listen-addr: :5183 + timeout: 10s + memo: "" + light-cache-size: 20 chains: - archway: - type: wasm - value: - key-directory: /home/user/.relayer/keys - key: relayWallet - chain-id: localnet - rpc-addr: http://localhost:26657 - account-prefix: archway - keyring-backend: test - gas-adjustment: 1.5 - gas-prices: 0.025stake - min-gas-amount: 1000000 - debug: true - timeout: 20s - block-timeout: "" - output-format: json - sign-mode: direct - extra-codecs: [] - coin-type: 0 - broadcast-mode: batch - ibc-handler-address: archway1pvrwmjuusn9wh34j7y520g8gumuy9xtl3gvprlljfdpwju3x7ucszwhc7n - first-retry-block-after: 0 - start-height: 0 - block-interval: 3000 - icon: - type: icon - value: - key-directory: /home/user/.relayer/keys - chain-id: ibc-icon - rpc-addr: http://localhost:9082/api/v3/ - timeout: 30s - keystore: godWallet - password: gochain - icon-network-id: 3 - btp-network-id: 1 - btp-network-type-id: 1 - start-height: 0 - ibc-handler-address: cxbeb5929616e0dbd2fec1e6e950ab09e45e6fb25a - first-retry-block-after: 0 - block-interval: 2000 + archway: + type: wasm + value: + key-directory: /home/user/.relayer/keys + key: relayWallet + chain-id: localnet + rpc-addr: http://localhost:26657 + account-prefix: archway + keyring-backend: test + gas-adjustment: 1.5 + gas-prices: 0.025stake + min-gas-amount: 1000000 + debug: true + timeout: 20s + block-timeout: "" + output-format: json + sign-mode: direct + extra-codecs: [] + coin-type: 0 + broadcast-mode: batch + ibc-handler-address: archway1pvrwmjuusn9wh34j7y520g8gumuy9xtl3gvprlljfdpwju3x7ucszwhc7n + first-retry-block-after: 0 + block-interval: 3000 + icon: + type: icon + value: + key-directory: /home/user/.relayer/keys + chain-id: ibc-icon + rpc-addr: http://localhost:9082/api/v3/ + timeout: 30s + keystore: godWallet + password: gochain + icon-network-id: 3 + btp-network-id: 1 + btp-network-type-id: 1 + ibc-handler-address: cxbeb5929616e0dbd2fec1e6e950ab09e45e6fb25a + first-retry-block-after: 0 + block-interval: 2000 paths: - icon-archway: - src: - chain-id: ibc-icon - client-id: 07-tendermint-0 - connection-id: connection-0 - dst: - chain-id: localnet - client-id: iconclient-0 - connection-id: connection-0 - src-channel-filter: - rule: "" - channel-list: [] + icon-archway: + src: + chain-id: ibc-icon + client-id: 07-tendermint-0 + connection-id: connection-0 + dst: + chain-id: localnet + client-id: iconclient-0 + connection-id: connection-0 + src-channel-filter: + rule: "" + channel-list: [] diff --git a/examples/demo/configs/chains/ibc-icon.json b/examples/demo/configs/chains/ibc-icon.json index 466f153ee..912a1e2a6 100644 --- a/examples/demo/configs/chains/ibc-icon.json +++ b/examples/demo/configs/chains/ibc-icon.json @@ -10,7 +10,6 @@ "icon-network-id": 3, "btp-network-id": 2, "btp-network-type-id": 1, - "start-height": 0, "ibc-handler-address": "cxbeb5929616e0dbd2fec1e6e950ab09e45e6fb25a", "first-retry-block-after": 0, "block-interval": 2000 diff --git a/examples/demo/configs/chains/ibc-wasm.json b/examples/demo/configs/chains/ibc-wasm.json index d0f6bbe3a..73b035289 100644 --- a/examples/demo/configs/chains/ibc-wasm.json +++ b/examples/demo/configs/chains/ibc-wasm.json @@ -20,7 +20,7 @@ "broadcast-mode": "batch", "ibc-handler-address": "archway1pvrwmjuusn9wh34j7y520g8gumuy9xtl3gvprlljfdpwju3x7ucszwhc7n", "first-retry-block-after": 0, - "start-height": 0, - "block-interval": 3000 + "block-interval": 3000, + "concurrency": 100 } } \ No newline at end of file diff --git a/relayer/strategies.go b/relayer/strategies.go index b22e88c09..06d0e3a8e 100644 --- a/relayer/strategies.go +++ b/relayer/strategies.go @@ -565,7 +565,7 @@ type SrcProviderClientState struct { func RunProofContextUpdate(ctx context.Context, log *zap.Logger, chains map[string]*Chain, paths []NamedPath, fromHeight int64) (uint64, error) { - log.Info("runProofContextUpdate: started") + log.Info("running iconchain proof context change update") // finding the height to start from srcProviderClientStates := make([]SrcProviderClientState, 0) From c222afa354a23e204f9e04e7cbd14298cebae1eb Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 4 Dec 2023 12:24:48 +0800 Subject: [PATCH 60/61] chore: reduce sleep time --- relayer/chains/icon/query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 16d7f8ac4..1e2f2f303 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -1246,7 +1246,7 @@ loop: func (icp *IconProvider) handleBlockRequest( request *btpBlockRequest, requestCh chan *btpBlockRequest) { defer func() { - time.Sleep(500 * time.Millisecond) + time.Sleep(50 * time.Millisecond) requestCh <- request }() From 436d7338989cd7bebbeaa837ae0730a4a94e842d Mon Sep 17 00:00:00 2001 From: viveksharmapoudel Date: Mon, 11 Dec 2023 10:56:28 +0800 Subject: [PATCH 61/61] fix: add btp height of only it doesn't exist --- relayer/processor/path_processor_internal.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/relayer/processor/path_processor_internal.go b/relayer/processor/path_processor_internal.go index 76235e2be..8f51f15e4 100644 --- a/relayer/processor/path_processor_internal.go +++ b/relayer/processor/path_processor_internal.go @@ -1841,8 +1841,10 @@ func (pp *PathProcessor) queuePendingRecvAndAcksByHeights( if !header.IsCompleteBlock() { return fmt.Errorf("icon module should have complete block at height: %d because of send packet message: %v", sendPacket.Height, sendPacket) } - // enqueuing this height - src.BTPHeightQueue.Enqueue(sendPacket.Height) + // enqueuing this height if it doesn't exist + if !src.BTPHeightQueue.ItemExist(sendPacket.Height) { + src.BTPHeightQueue.Enqueue(sendPacket.Height) + } } }