diff --git a/.github/workflows/ibctest.yml b/.github/workflows/ibctest.yml index 4233a5b8a6..d973952ea7 100644 --- a/.github/workflows/ibctest.yml +++ b/.github/workflows/ibctest.yml @@ -27,7 +27,7 @@ jobs: ${{ runner.os }}-go- - name: ibctest - run: make ibctest-docker-events + run: make ibctest-events legacy: runs-on: self-hosted steps: @@ -48,4 +48,46 @@ jobs: ${{ runner.os }}-go- - name: ibctest - run: make ibctest-docker-legacy + run: make ibctest-legacy + multiple-paths: + runs-on: self-hosted + steps: + - name: Set up Go 1.18 + uses: actions/setup-go@v1 + with: + go-version: 1.18 + id: go + + - name: checkout relayer + uses: actions/checkout@v2 + + - uses: actions/cache@v1 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: ibctest + run: make ibctest-multiple + path-filter: + runs-on: ubuntu-latest + steps: + - name: Set up Go 1.18 + uses: actions/setup-go@v1 + with: + go-version: 1.18 + id: go + + - name: checkout relayer + uses: actions/checkout@v2 + + - uses: actions/cache@v1 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: ibctest + run: make ibctest-path-filter \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ea28438e0..315deb42d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * [\#467](https://github.com/cosmos/relayer/pull/467) cli: UX cleanup for tx commands * [\#466](https://github.com/cosmos/relayer/pull/466) Docs cleanup. * [\#506](https://github.com/cosmos/relayer/pull/506) Fix Timeout Handling on Relayer restart +* [\#940](https://github.com/cosmos/relayer/pull/940) Add min-gas-amount parameter for chain configs, to workaround gas estimation failure. ## v0.9.3 diff --git a/Makefile b/Makefile index 9f32551234..8280e09ab4 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,18 @@ ibctest-docker-events: ibctest-docker-legacy: cd ibctest && go test -race -v -run TestRelayerDockerLegacyProcessor . +ibctest-events: + cd ibctest && go test -race -v -run TestRelayerEventProcessor . + +ibctest-legacy: + cd ibctest && go test -race -v -run TestRelayerLegacyProcessor . + +ibctest-multiple: + cd ibctest && go test -race -v -run TestRelayerMultiplePathsSingleProcess . + +ibctest-path-filter: + cd ibctest && go test -race -v -run TestPathFilter . + coverage: @echo "viewing test coverage..." @go tool cover --html=coverage.out diff --git a/README.md b/README.md index e507468a7e..9ddde04837 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,8 @@ Additional information on how IBC works can be found [here](https://ibc.cosmos.n ```shell $ rly paths list $ rly start [path] + # Optionally you can omit the `path` argument to start all configured paths + $ rly start ``` You will need to start a separate shell instance for each path you wish to relay over. diff --git a/_test/relayer_chain_test.go b/_test/relayer_chain_test.go index 88c2f10f10..fc0e8ae56d 100644 --- a/_test/relayer_chain_test.go +++ b/_test/relayer_chain_test.go @@ -35,15 +35,18 @@ const ( func chainTest(t *testing.T, tcs []testChain) { chains := spinUpTestChains(t, tcs...) + c, err := chains.Gets("ibc-0", "ibc-1") + require.NoError(t, err) + var ( - src = chains.MustGet(tcs[0].chainID) - dst = chains.MustGet(tcs[1].chainID) + src = c["ibc-0"] + dst = c["ibc-1"] testDenom = "samoleans" testCoin = sdk.NewCoin(testDenom, sdk.NewInt(1000)) twoTestCoin = sdk.NewCoin(testDenom, sdk.NewInt(2000)) ) - _, err := genTestPathAndSet(src, dst) + p, err := genTestPathAndSet(src, dst) require.NoError(t, err) t.Log("Querying initial balances for later comparison") @@ -76,7 +79,7 @@ func chainTest(t *testing.T, tcs []testChain) { require.NoError(t, eg.Wait()) t.Log("Creating clients") - _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") + _, _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") require.NoError(t, err) testClientPair(ctx, t, src, dst) @@ -84,7 +87,7 @@ func chainTest(t *testing.T, tcs []testChain) { require.NoError(t, err) t.Log("Creating connections") - _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") + _, _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") require.NoError(t, err) testConnectionPair(ctx, t, src, dst) @@ -119,8 +122,7 @@ func chainTest(t *testing.T, tcs []testChain) { require.NoError(t, dst.ChainProvider.WaitForNBlocks(ctx, 1)) t.Log("Starting relayer") - filter := relayer.ChannelFilter{} - _ = relayer.StartRelayer(ctx, log, src, dst, filter, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, "", nil) + _ = relayer.StartRelayer(ctx, log, c, []relayer.NamedPath{{Path: p}}, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, nil) t.Log("Waiting for relayer messages to reach both chains") require.NoError(t, src.ChainProvider.WaitForNBlocks(ctx, 2)) @@ -165,14 +167,14 @@ func TestGaiaReuseIdentifiers(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") + _, _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") require.NoError(t, err) testClientPair(ctx, t, src, dst) timeout, err := src.GetTimeout() require.NoError(t, err) - _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") + _, _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") require.NoError(t, err) testConnectionPair(ctx, t, src, dst) @@ -195,11 +197,11 @@ func TestGaiaReuseIdentifiers(t *testing.T) { dst.PathEnd.ClientID = "" dst.PathEnd.ConnectionID = "" - _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") + _, _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") require.NoError(t, err) testClientPair(ctx, t, src, dst) - _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") + _, _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") require.NoError(t, err) testConnectionPair(ctx, t, src, dst) @@ -217,7 +219,7 @@ func TestGaiaReuseIdentifiers(t *testing.T) { src.PathEnd.ClientID = "" dst.PathEnd.ClientID = "" - _, err = src.CreateClients(ctx, dst, true, true, true, 0, "") + _, _, err = src.CreateClients(ctx, dst, true, true, true, 0, "") require.NoError(t, err) testClientPair(ctx, t, src, dst) @@ -234,26 +236,29 @@ func TestGaiaMisbehaviourMonitoring(t *testing.T) { {"testChain1", "ibc-1", 1, gaiaTestConfig, gaiaProviderCfg}, }...) + c, err := chains.Gets("ibc-0", "ibc-1") + require.NoError(t, err) + var ( - src = chains.MustGet("ibc-0") - dst = chains.MustGet("ibc-1") + src = c["ibc-0"] + dst = c["ibc-1"] ) - _, err := genTestPathAndSet(src, dst) + p, err := genTestPathAndSet(src, dst) require.NoError(t, err) // create path ctx, cancel := context.WithCancel(context.Background()) defer cancel() - _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") + _, _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") require.NoError(t, err) testClientPair(ctx, t, src, dst) timeout, err := src.GetTimeout() require.NoError(t, err) - _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") + _, _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") require.NoError(t, err) testConnectionPair(ctx, t, src, dst) @@ -269,8 +274,7 @@ func TestGaiaMisbehaviourMonitoring(t *testing.T) { log := zaptest.NewLogger(t) // start the relayer process in it's own goroutine - filter := relayer.ChannelFilter{} - _ = relayer.StartRelayer(ctx, log, src, dst, filter, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, "", nil) + _ = relayer.StartRelayer(ctx, log, c, []relayer.NamedPath{{Path: p}}, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, nil) // Wait for relay message inclusion in both chains require.NoError(t, src.ChainProvider.WaitForNBlocks(ctx, 1)) @@ -335,15 +339,18 @@ func TestRelayAllChannelsOnConnection(t *testing.T) { {"testChain1", "ibc-1", 1, gaiaTestConfig, gaiaProviderCfg}, }...) + c, err := chains.Gets("ibc-0", "ibc-1") + require.NoError(t, err) + var ( - src = chains.MustGet("ibc-0") - dst = chains.MustGet("ibc-1") + src = c["ibc-0"] + dst = c["ibc-1"] testDenom = "samoleans" testCoin = sdk.NewCoin(testDenom, sdk.NewInt(1000)) twoTestCoin = sdk.NewCoin(testDenom, sdk.NewInt(2000)) ) - _, err := genTestPathAndSet(src, dst) + p, err := genTestPathAndSet(src, dst) require.NoError(t, err) t.Log("Querying initial balances to compare against at the end") @@ -386,7 +393,7 @@ func TestRelayAllChannelsOnConnection(t *testing.T) { require.NoError(t, eg.Wait()) t.Log("Creating clients") - _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") + _, _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") require.NoError(t, err) testClientPair(ctx, t, src, dst) @@ -394,7 +401,7 @@ func TestRelayAllChannelsOnConnection(t *testing.T) { require.NoError(t, err) t.Log("Creating connections") - _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") + _, _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") require.NoError(t, err) testConnectionPair(ctx, t, src, dst) @@ -443,8 +450,7 @@ func TestRelayAllChannelsOnConnection(t *testing.T) { require.NoError(t, dst.ChainProvider.WaitForNBlocks(ctx, 1)) t.Log("Starting relayer") - filter := relayer.ChannelFilter{} - _ = relayer.StartRelayer(ctx, log, src, dst, filter, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, "", nil) + _ = relayer.StartRelayer(ctx, log, c, []relayer.NamedPath{{Path: p}}, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, nil) t.Log("Waiting for relayer message inclusion in both chains") require.NoError(t, src.ChainProvider.WaitForNBlocks(ctx, 1)) @@ -543,14 +549,17 @@ func TestUnorderedChannelBlockHeightTimeout(t *testing.T) { {"testChain1", "ibc-1", 1, gaiaTestConfig, gaiaProviderCfg}, }...) + c, err := chains.Gets("ibc-0", "ibc-1") + require.NoError(t, err) + var ( - src = chains.MustGet("ibc-0") - dst = chains.MustGet("ibc-1") + src = c["ibc-0"] + dst = c["ibc-1"] testDenom = "samoleans" twoTestCoin = sdk.NewCoin(testDenom, sdk.NewInt(2000)) ) - _, err := genTestPathAndSet(src, dst) + p, err := genTestPathAndSet(src, dst) require.NoError(t, err) // query initial balances to compare against at the end @@ -583,14 +592,14 @@ func TestUnorderedChannelBlockHeightTimeout(t *testing.T) { require.NoError(t, eg.Wait()) // create path - _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") + _, _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") require.NoError(t, err) testClientPair(ctx, t, src, dst) timeout, err := src.GetTimeout() require.NoError(t, err) - _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") + _, _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") require.NoError(t, err) testConnectionPair(ctx, t, src, dst) @@ -619,8 +628,7 @@ func TestUnorderedChannelBlockHeightTimeout(t *testing.T) { require.NoError(t, src.ChainProvider.WaitForNBlocks(ctx, 11)) // start the relayer process in it's own goroutine - filter := relayer.ChannelFilter{} - _ = relayer.StartRelayer(ctx, log, src, dst, filter, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, "", nil) + _ = relayer.StartRelayer(ctx, log, c, []relayer.NamedPath{{Path: p}}, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, nil) require.NoError(t, src.ChainProvider.WaitForNBlocks(ctx, 5)) @@ -641,14 +649,17 @@ func TestUnorderedChannelTimestampTimeout(t *testing.T) { {"testChain1", "ibc-1", 1, gaiaTestConfig, gaiaProviderCfg}, }...) + c, err := chains.Gets("ibc-0", "ibc-1") + require.NoError(t, err) + var ( - src = chains.MustGet("ibc-0") - dst = chains.MustGet("ibc-1") + src = c["ibc-0"] + dst = c["ibc-1"] testDenom = "samoleans" twoTestCoin = sdk.NewCoin(testDenom, sdk.NewInt(2000)) ) - _, err := genTestPathAndSet(src, dst) + p, err := genTestPathAndSet(src, dst) require.NoError(t, err) // query initial balances to compare against at the end @@ -681,14 +692,14 @@ func TestUnorderedChannelTimestampTimeout(t *testing.T) { require.NoError(t, eg.Wait()) // create path - _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") + _, _, err = src.CreateClients(ctx, dst, true, true, false, 0, "") require.NoError(t, err) testClientPair(ctx, t, src, dst) timeout, err := src.GetTimeout() require.NoError(t, err) - _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") + _, _, err = src.CreateOpenConnections(ctx, dst, 3, timeout, "", 0, "") require.NoError(t, err) testConnectionPair(ctx, t, src, dst) @@ -717,8 +728,7 @@ func TestUnorderedChannelTimestampTimeout(t *testing.T) { time.Sleep(time.Second * 20) // start the relayer process in it's own goroutine - filter := relayer.ChannelFilter{} - _ = relayer.StartRelayer(ctx, log, src, dst, filter, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, "", nil) + _ = relayer.StartRelayer(ctx, log, c, []relayer.NamedPath{{Path: p}}, 2*cmd.MB, 5, "", relayer.ProcessorEvents, 20, nil) time.Sleep(time.Second * 10) diff --git a/cmd/appstate.go b/cmd/appstate.go index 377782a12e..713cbe9bbf 100644 --- a/cmd/appstate.go +++ b/cmd/appstate.go @@ -3,12 +3,16 @@ package cmd import ( "context" "encoding/json" + "errors" "fmt" "io" "os" "path" + "time" "github.com/cosmos/relayer/v2/relayer" + "github.com/juju/fslock" + "github.com/spf13/cobra" "github.com/spf13/viper" "go.uber.org/zap" "gopkg.in/yaml.v3" @@ -159,3 +163,69 @@ func (a *appState) OverwriteConfig(cfg *Config) error { a.Config = cfg return nil } + +// OverwriteConfigOnTheFly overwrites the config file concurrently, +// locking to read, modify, then write the config. +func (a *appState) OverwriteConfigOnTheFly( + cmd *cobra.Command, + pathName string, + clientSrc, clientDst string, + connectionSrc, connectionDst string, +) error { + if pathName == "" { + return errors.New("empty path name not allowed") + } + + // use lock file to guard concurrent access to config.yaml + lockFilePath := path.Join(a.HomePath, "config", "config.lock") + lock := fslock.New(lockFilePath) + err := lock.LockWithTimeout(10 * time.Second) + if err != nil { + return fmt.Errorf("failed to acquire config lock: %w", err) + } + defer func() { + if err := lock.Unlock(); err != nil { + a.Log.Error("error unlocking config file lock, please manually delete", + zap.String("filepath", lockFilePath), + ) + } + }() + + // load config from file and validate it. don't want to miss + // any changes that may have been made while unlocked. + if err := initConfig(cmd, a); err != nil { + return fmt.Errorf("failed to initialize config from file: %w", err) + } + + path, ok := a.Config.Paths[pathName] + if !ok { + return fmt.Errorf("config does not exist for that path: %s", pathName) + } + if clientSrc != "" { + path.Src.ClientID = clientSrc + } + if clientDst != "" { + path.Dst.ClientID = clientDst + } + if connectionSrc != "" { + path.Src.ConnectionID = connectionSrc + } + if connectionDst != "" { + path.Dst.ConnectionID = connectionDst + } + + // marshal the new config + out, err := yaml.Marshal(a.Config.Wrapped()) + if err != nil { + return err + } + + cfgPath := a.Viper.ConfigFileUsed() + + // Overwrite the config file. + if err := os.WriteFile(cfgPath, out, 0600); err != nil { + return fmt.Errorf("failed to write config file at %s: %w", cfgPath, err) + } + + return nil +} diff --git a/cmd/config.go b/cmd/config.go index 37ba3ac32f..bbd2e74792 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -153,7 +153,7 @@ $ %s cfg i`, appName, defaultHome, appName)), memo, _ := cmd.Flags().GetString(flagMemo) // And write the default config to that location... - if _, err = f.Write(defaultConfig(memo)); err != nil { + if _, err = f.Write(defaultConfigYAML(memo)); err != nil { return err } @@ -432,12 +432,16 @@ func (c Config) MustYAML() []byte { return out } -func defaultConfig(memo string) []byte { - return Config{ +func defaultConfigYAML(memo string) []byte { + return DefaultConfig(memo).MustYAML() +} + +func DefaultConfig(memo string) *Config { + return &Config{ Global: newDefaultGlobalConfig(memo), - Chains: relayer.Chains{}, - Paths: relayer.Paths{}, - }.MustYAML() + Chains: make(relayer.Chains), + Paths: make(relayer.Paths), + } } // GlobalConfig describes any global relayer settings @@ -538,12 +542,15 @@ func validateConfig(c *Config) error { // initConfig reads config file into a.Config if file is present. func initConfig(cmd *cobra.Command, a *appState) error { - home, err := cmd.PersistentFlags().GetString(flagHome) - if err != nil { - return err + if a.HomePath == "" { + var err error + a.HomePath, err = cmd.PersistentFlags().GetString(flagHome) + if err != nil { + return err + } } - cfgPath := path.Join(home, "config", "config.yaml") + cfgPath := path.Join(a.HomePath, "config", "config.yaml") if _, err := os.Stat(cfgPath); err != nil { // don't return error if file doesn't exist return nil diff --git a/cmd/flags.go b/cmd/flags.go index 8f56e9e93a..bd44e723ce 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -45,6 +45,8 @@ const ( flagProcessor = "processor" flagInitialBlockHistory = "block-history" flagMemo = "memo" + flagFilterRule = "filter-rule" + flagFilterChannels = "filter-channels" ) const ( @@ -152,6 +154,18 @@ func fileFlag(v *viper.Viper, cmd *cobra.Command) *cobra.Command { return cmd } +func pathFilterFlags(v *viper.Viper, cmd *cobra.Command) *cobra.Command { + cmd.Flags().String(flagFilterRule, "", `filter rule ("allowlist", "denylist", or "" for no filtering)`) + if err := v.BindPFlag(flagFilterRule, cmd.Flags().Lookup(flagFilterRule)); err != nil { + panic(err) + } + cmd.Flags().String(flagFilterChannels, "", "channels from source chain perspective to filter") + if err := v.BindPFlag(flagFilterRule, cmd.Flags().Lookup(flagFilterRule)); err != nil { + panic(err) + } + return cmd +} + func timeoutFlag(v *viper.Viper, cmd *cobra.Command) *cobra.Command { cmd.Flags().StringP(flagTimeout, "t", "10s", "timeout between relayer runs") if err := v.BindPFlag(flagTimeout, cmd.Flags().Lookup(flagTimeout)); err != nil { @@ -293,7 +307,7 @@ func debugServerFlags(v *viper.Viper, cmd *cobra.Command) *cobra.Command { } func processorFlag(v *viper.Viper, cmd *cobra.Command) *cobra.Command { - cmd.Flags().StringP(flagProcessor, "p", relayer.ProcessorLegacy, "which relayer processor to use") + cmd.Flags().StringP(flagProcessor, "p", relayer.ProcessorEvents, "which relayer processor to use") if err := v.BindPFlag(flagProcessor, cmd.Flags().Lookup(flagProcessor)); err != nil { panic(err) } diff --git a/cmd/paths.go b/cmd/paths.go index cad96d5a52..090ac919ac 100644 --- a/cmd/paths.go +++ b/cmd/paths.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/cosmos/relayer/v2/relayer" + "github.com/cosmos/relayer/v2/relayer/processor" "github.com/google/go-github/v43/github" "github.com/spf13/cobra" "gopkg.in/yaml.v3" @@ -30,6 +31,7 @@ This includes the client, connection, and channel ids from both the source and d pathsAddCmd(a), pathsAddDirCmd(a), pathsNewCmd(a), + pathsUpdateCmd(a), pathsFetchCmd(a), pathsDeleteCmd(a), ) @@ -260,6 +262,52 @@ $ %s pth n ibc-0 ibc-1 demo-path`, appName, appName)), return channelParameterFlags(a.Viper, cmd) } +func pathsUpdateCmd(a *appState) *cobra.Command { + cmd := &cobra.Command{ + Use: "update path_name", + Aliases: []string{"n"}, + Short: `Update a path such as the filter rule ("allowlist", "denylist", or "" for no filtering) and channels`, + Args: withUsage(cobra.ExactArgs(1)), + Example: strings.TrimSpace(fmt.Sprintf(` +$ %s paths update demo-path --filter-rule allowlist --filter-channels channel-0,channel-1 +$ %s paths update demo-path --filter-rule denylist --filter-channels channel-0,channel-1`, + appName, appName)), + RunE: func(cmd *cobra.Command, args []string) error { + name := args[0] + + filterRule, err := cmd.Flags().GetString(flagFilterRule) + if err != nil { + return err + } + if filterRule != "" && filterRule != processor.RuleAllowList && filterRule != processor.RuleDenyList { + return fmt.Errorf(`invalid filter rule : "%s". valid rules: ("", "%s", "%s")`, filterRule, processor.RuleAllowList, processor.RuleDenyList) + } + + filterChannels, err := cmd.Flags().GetString(flagFilterChannels) + if err != nil { + return err + } + + var channelList []string + + if filterChannels != "" { + channelList = strings.Split(filterChannels, ",") + } + + p := a.Config.Paths.MustGet(name) + + p.Filter = relayer.ChannelFilter{ + Rule: filterRule, + ChannelList: channelList, + } + + return a.OverwriteConfig(a.Config) + }, + } + cmd = pathFilterFlags(a.Viper, cmd) + return cmd +} + // pathsFetchCmd attempts to fetch the json files containing the path metadata, for each configured chain, from GitHub func pathsFetchCmd(a *appState) *cobra.Command { cmd := &cobra.Command{ diff --git a/cmd/start.go b/cmd/start.go index 76a0548df3..802bbce016 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -6,7 +6,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -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/processor" "github.com/spf13/cobra" "go.uber.org/zap" @@ -37,31 +38,61 @@ func startCmd(a *appState) *cobra.Command { Use: "start path_name", Aliases: []string{"st"}, Short: "Start the listening relayer on a given path", - Args: withUsage(cobra.ExactArgs(1)), + Args: withUsage(cobra.MinimumNArgs(0)), Example: strings.TrimSpace(fmt.Sprintf(` -$ %s start demo-path -p events # to use event processor +$ %s start # start all configured paths +$ %s start demo-path # start the 'demo-path' path $ %s start demo-path --max-msgs 3 -$ %s start demo-path2 --max-tx-size 10`, appName, appName, appName)), +$ %s start demo-path2 --max-tx-size 10`, appName, appName, appName, appName)), RunE: func(cmd *cobra.Command, args []string) error { - pathName := args[0] - c, src, dst, err := a.Config.ChainsFromPath(pathName) + chains := make(map[string]*relayer.Chain) + paths := make([]relayer.NamedPath, len(args)) + + if len(args) > 0 { + for i, pathName := range args { + path := a.Config.Paths.MustGet(pathName) + paths[i] = relayer.NamedPath{ + Name: pathName, + Path: path, + } + + // collect unique chain IDs + chains[path.Src.ChainID] = nil + chains[path.Dst.ChainID] = nil + } + } else { + for n, path := range a.Config.Paths { + paths = append(paths, relayer.NamedPath{ + Name: n, + Path: path, + }) + + // collect unique chain IDs + chains[path.Src.ChainID] = nil + chains[path.Dst.ChainID] = nil + } + } + + chainIDs := make([]string, 0, len(chains)) + for chainID := range chains { + chainIDs = append(chainIDs, chainID) + } + + // get chain configurations + chains, err := a.Config.Chains.Gets(chainIDs...) if err != nil { return err } - if err = ensureKeysExist(c); err != nil { + if err := ensureKeysExist(chains); err != nil { return err } - path := a.Config.Paths.MustGet(pathName) - maxTxSize, maxMsgLength, err := GetStartOptions(cmd) if err != nil { return err } - filter := path.Filter - var prometheusMetrics *processor.PrometheusMetrics debugAddr, err := cmd.Flags().GetString(flagDebugAddr) @@ -80,6 +111,11 @@ $ %s start demo-path2 --max-tx-size 10`, appName, appName, appName)), log.Info("Debug server listening", zap.String("addr", debugAddr)) relaydebug.StartDebugServer(cmd.Context(), log, ln) prometheusMetrics = processor.NewPrometheusMetrics() + for _, chain := range chains { + if ccp, ok := chain.ChainProvider.(*cosmos.CosmosProvider); ok { + ccp.SetMetrics(prometheusMetrics) + } + } } processorType, err := cmd.Flags().GetString(flagProcessor) @@ -94,12 +130,11 @@ $ %s start demo-path2 --max-tx-size 10`, appName, appName, appName)), rlyErrCh := relayer.StartRelayer( cmd.Context(), a.Log, - c[src], c[dst], - filter, + chains, + paths, maxTxSize, maxMsgLength, a.Config.memo(cmd), processorType, initialBlockHistory, - pathName, prometheusMetrics, ) diff --git a/cmd/tx.go b/cmd/tx.go index 6ed42fa437..d4216d3692 100644 --- a/cmd/tx.go +++ b/cmd/tx.go @@ -77,7 +77,9 @@ func createClientsCmd(a *appState) *cobra.Command { return err } - c, src, dst, err := a.Config.ChainsFromPath(args[0]) + path := args[0] + + c, src, dst, err := a.Config.ChainsFromPath(path) if err != nil { return err } @@ -90,12 +92,12 @@ func createClientsCmd(a *appState) *cobra.Command { return fmt.Errorf("key %s not found on dst chain %s", c[dst].ChainProvider.Key(), c[dst].ChainID()) } - modified, err := c[src].CreateClients(cmd.Context(), c[dst], allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, a.Config.memo(cmd)) + clientSrc, clientDst, err := c[src].CreateClients(cmd.Context(), c[dst], allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, a.Config.memo(cmd)) if err != nil { return err } - if modified { - if err := a.OverwriteConfig(a.Config); err != nil { + if clientSrc != "" || clientDst != "" { + if err := a.OverwriteConfigOnTheFly(cmd, path, clientSrc, clientDst, "", ""); err != nil { return err } } @@ -201,12 +203,18 @@ func createClientCmd(a *appState) *cobra.Command { return err } - modified, err := relayer.CreateClient(cmd.Context(), src, dst, srcUpdateHeader, dstUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, a.Config.memo(cmd)) + clientID, err := relayer.CreateClient(cmd.Context(), src, dst, srcUpdateHeader, dstUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, a.Config.memo(cmd)) if err != nil { return err } - if modified { - if err = a.OverwriteConfig(a.Config); err != nil { + var clientSrc, clientDst string + if path.Src.ChainID == src.ChainID() { + clientSrc = clientID + } else { + clientDst = clientID + } + if clientID != "" { + if err = a.OverwriteConfigOnTheFly(cmd, pathName, clientSrc, clientDst, "", ""); err != nil { return err } } @@ -361,22 +369,22 @@ $ %s tx conn demo-path --timeout 5s`, } // ensure that the clients exist - modified, err := c[src].CreateClients(cmd.Context(), c[dst], allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) + clientSrc, clientDst, err := c[src].CreateClients(cmd.Context(), c[dst], allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) if err != nil { return err } - if modified { - if err := a.OverwriteConfig(a.Config); err != nil { + if clientSrc != "" || clientDst != "" { + if err := a.OverwriteConfigOnTheFly(cmd, pathName, clientSrc, clientDst, "", ""); err != nil { return err } } - modified, err = c[src].CreateOpenConnections(cmd.Context(), c[dst], retries, to, memo, initialBlockHistory, pathName) + connectionSrc, connectionDst, err := c[src].CreateOpenConnections(cmd.Context(), c[dst], retries, to, memo, initialBlockHistory, pathName) if err != nil { return err } - if modified { - if err := a.OverwriteConfig(a.Config); err != nil { + if connectionSrc != "" || connectionDst != "" { + if err := a.OverwriteConfigOnTheFly(cmd, pathName, "", "", connectionSrc, connectionDst); err != nil { return err } } @@ -632,23 +640,23 @@ $ %s tx connect demo-path --src-port transfer --dst-port transfer --order unorde } // create clients if they aren't already created - modified, err := c[src].CreateClients(cmd.Context(), c[dst], allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) + clientSrc, clientDst, err := c[src].CreateClients(cmd.Context(), c[dst], allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) if err != nil { return fmt.Errorf("error creating clients: %w", err) } - if modified { - if err := a.OverwriteConfig(a.Config); err != nil { + if clientSrc != "" || clientDst != "" { + if err := a.OverwriteConfigOnTheFly(cmd, pathName, clientSrc, clientDst, "", ""); err != nil { return err } } // create connection if it isn't already created - modified, err = c[src].CreateOpenConnections(cmd.Context(), c[dst], retries, to, memo, initialBlockHistory, pathName) + connectionSrc, connectionDst, err := c[src].CreateOpenConnections(cmd.Context(), c[dst], retries, to, memo, initialBlockHistory, pathName) if err != nil { return fmt.Errorf("error creating connections: %w", err) } - if modified { - if err := a.OverwriteConfig(a.Config); err != nil { + if connectionSrc != "" || connectionDst != "" { + if err := a.OverwriteConfigOnTheFly(cmd, pathName, "", "", connectionSrc, connectionDst); err != nil { return err } } diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index b945d15e11..1728f4892c 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -55,4 +55,33 @@ you can open `http://localhost:7597` in your browser to explore details from the If you need active assistance from the Relayer development team regarding an unresponsive Relayer instance, it will be helpful to provide the output from `http://localhost:7597/debug/pprof/goroutine?debug=2` at a minimum. +--- + +**Error building or broadcasting transaction** + +When preparing a transaction for relaying, the amount of gas that the transaction will consume is unknown. To compute how much gas the transaction will need, the transaction is prepared with 0 gas and delivered as a `/cosmos.tx.v1beta1.Service/Simulate` query to the RPC endpoint. Recently chains have been creating AnteHandlers in which 0 gas triggers an error case: + +``` +lvl=info msg="Error building or broadcasting transaction" provider_type=cosmos chain_id=evmos_9001-2 attempt=1 max_attempts=5 error="rpc error: code = InvalidArgument desc = provided fee < minimum global fee (0aevmos < ). Please increase the gas price.: insufficient fee: invalid request" +``` + +A workaround is available in which the `min-gas-amount` may be set in the chain's configuration to enable simulation with a non-zero amount of gas. + +``` + evmos: + type: cosmos + value: + key: relayer + chain-id: evmos_9001-2 + rpc-addr: http://127.0.0.1:26657 + account-prefix: evmos + keyring-backend: test + gas-adjustment: 1.2 + gas-prices: 20000000000aevmos + min-gas-amount: 1 + debug: false + timeout: 20s + output-format: json + sign-mode: direct +``` [<-- Create Path Across Chains](create-path-across-chain.md) - [Features -->](./features.md) \ No newline at end of file diff --git a/go.mod b/go.mod index 50db40ceab..8c13ccc26a 100644 --- a/go.mod +++ b/go.mod @@ -14,16 +14,17 @@ require ( github.com/google/go-cmp v0.5.8 github.com/google/go-github/v43 v43.0.0 github.com/jsternberg/zap-logfmt v1.2.0 + github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b github.com/ory/dockertest/v3 v3.9.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.12.2 github.com/spf13/cobra v1.5.0 github.com/spf13/viper v1.12.0 - github.com/strangelove-ventures/lens v0.5.2-0.20220810214843-6af97ce869d8 + github.com/strangelove-ventures/lens v0.5.2-0.20220822201013-1e7ffd450f20 github.com/stretchr/testify v1.8.0 github.com/tendermint/tendermint v0.34.20 go.uber.org/multierr v1.8.0 - go.uber.org/zap v1.21.0 + go.uber.org/zap v1.22.0 golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 diff --git a/go.sum b/go.sum index 883b6234ce..a27ca9b6f8 100644 --- a/go.sum +++ b/go.sum @@ -871,6 +871,8 @@ github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K github.com/jsternberg/zap-logfmt v1.2.0 h1:1v+PK4/B48cy8cfQbxL4FmmNZrjnIMr2BsnyEmXqv2o= github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b h1:FQ7+9fxhyp82ks9vAuyPzG0/vVbWwMwLJ+P6yJI5FN8= +github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b/go.mod h1:HMcgvsgd0Fjj4XXDkbjdmlbI505rUPBs6WBMYg2pXks= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -1366,8 +1368,8 @@ github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiu github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= -github.com/strangelove-ventures/lens v0.5.2-0.20220810214843-6af97ce869d8 h1:s6Ppy7Gaym68hKv1MYaC7O/fimPElznyL1aKLAqopiA= -github.com/strangelove-ventures/lens v0.5.2-0.20220810214843-6af97ce869d8/go.mod h1:sD6+Hy963GymNHWrRfYCMdqPf9mmNPM1GvdYvLfu9ws= +github.com/strangelove-ventures/lens v0.5.2-0.20220822201013-1e7ffd450f20 h1:nYM1gFMJHbV3aYdiNCCS5jfBe/uMkORHwg8DSWZ5MRA= +github.com/strangelove-ventures/lens v0.5.2-0.20220822201013-1e7ffd450f20/go.mod h1:qrmVarKca7XLvuTEkR9jO50FrOprxQxukbmB7fpVrVo= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1551,8 +1553,9 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= +go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/ibctest/go.mod b/ibctest/go.mod index dc18f91bc1..58e98887af 100644 --- a/ibctest/go.mod +++ b/ibctest/go.mod @@ -4,12 +4,14 @@ go 1.18 require ( github.com/cosmos/cosmos-sdk v0.46.0 + github.com/cosmos/ibc-go/v5 v5.0.0-beta1 github.com/cosmos/relayer/v2 v2.0.0 github.com/docker/docker v20.10.17+incompatible github.com/moby/moby v20.10.17+incompatible - github.com/strangelove-ventures/ibctest v0.0.0-20220809152134-4bd6b88f8572 + github.com/strangelove-ventures/ibctest/v5 v5.0.0-20220922235050-6baac8c666ea github.com/stretchr/testify v1.8.0 - go.uber.org/zap v1.21.0 + go.uber.org/zap v1.22.0 + golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 ) require ( @@ -22,9 +24,12 @@ require ( filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect + github.com/BurntSushi/toml v1.2.0 // indirect github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect + github.com/ChainSafe/go-schnorrkel/1 v0.0.0-00010101000000-000000000000 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Microsoft/hcsshim v0.9.3 // indirect + github.com/StirlingMarketingGroup/go-namecase v1.0.0 // indirect github.com/armon/go-metrics v0.4.0 // indirect github.com/avast/retry-go/v4 v4.1.0 // indirect github.com/aws/aws-sdk-go v1.40.45 // indirect @@ -36,6 +41,7 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect + github.com/centrifuge/go-substrate-rpc-client/v4 v4.0.4 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect @@ -47,11 +53,14 @@ require ( github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.19.0 // indirect - github.com/cosmos/ibc-go/v5 v5.0.0-beta1 // indirect github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect github.com/cosmos/ledger-go v0.9.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/base58 v1.0.4 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect @@ -68,6 +77,7 @@ require ( github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/gateway v1.1.0 // indirect github.com/gogo/protobuf v1.3.3 // indirect @@ -96,29 +106,46 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect + github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/ipfs/go-cid v0.0.7 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/jsternberg/zap-logfmt v1.2.0 // indirect + github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/klauspost/compress v1.15.1 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-libp2p-core v0.15.1 // indirect + github.com/libp2p/go-openssl v0.0.7 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/sys/mount v0.3.3 // indirect github.com/moby/sys/mountinfo v0.6.2 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-base32 v0.0.3 // indirect + github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-multiaddr v0.5.0 // indirect + github.com/multiformats/go-multibase v0.0.3 // indirect + github.com/multiformats/go-multicodec v0.4.1 // indirect + github.com/multiformats/go-multihash v0.1.0 // indirect + github.com/multiformats/go-varint v0.0.6 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/opencontainers/runc v1.1.3 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.2 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pierrec/xxHash v0.1.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.12.2 // indirect @@ -129,15 +156,18 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/regen-network/cosmos-proto v0.3.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + github.com/rs/cors v1.8.2 // indirect github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect github.com/sirupsen/logrus v1.8.1 // indirect + github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/cobra v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.12.0 // indirect - github.com/strangelove-ventures/lens v0.5.2-0.20220810214843-6af97ce869d8 // indirect + github.com/strangelove-ventures/lens v0.5.2-0.20220822201013-1e7ffd450f20 // indirect github.com/subosito/gotenv v1.4.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect github.com/tendermint/btcd v0.1.1 // indirect @@ -147,6 +177,7 @@ require ( github.com/tendermint/tm-db v0.6.7 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/ulikunitz/xz v0.5.8 // indirect + github.com/vedhavyas/go-subkey v1.0.3 // indirect github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.opencensus.io v0.23.0 // indirect @@ -156,7 +187,6 @@ require ( golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 // indirect golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect - golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect golang.org/x/text v0.3.7 // indirect @@ -168,8 +198,10 @@ require ( google.golang.org/grpc v1.48.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/ini.v1 v1.66.6 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + lukechampine.com/blake3 v1.1.6 // indirect lukechampine.com/uint128 v1.1.1 // indirect modernc.org/cc/v3 v3.36.0 // indirect modernc.org/ccgo/v3 v3.16.6 // indirect @@ -183,11 +215,13 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect ) -replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 +replace ( + github.com/ChainSafe/go-schnorrkel => github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d + github.com/ChainSafe/go-schnorrkel/1 => github.com/ChainSafe/go-schnorrkel v1.0.0 + // For this nested module, you always want to replace the parent reference with the current worktree. + github.com/cosmos/relayer/v2 => ../ -replace github.com/ChainSafe/go-schnorrkel => github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 -replace github.com/ChainSafe/go-schnorrkel/1 => github.com/ChainSafe/go-schnorrkel v1.0.0 - -// For this nested module, you always want to replace the parent reference with the current worktree. -replace github.com/cosmos/relayer/v2 => ../ + github.com/vedhavyas/go-subkey => github.com/strangelove-ventures/go-subkey v1.0.7 +) diff --git a/ibctest/go.sum b/ibctest/go.sum index ba81eb52dd..6a2a855909 100644 --- a/ibctest/go.sum +++ b/ibctest/go.sum @@ -99,9 +99,13 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= +github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= +github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= @@ -150,6 +154,8 @@ github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:H github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= +github.com/StirlingMarketingGroup/go-namecase v1.0.0 h1:2CzaNtCzc4iNHirR+5ru9OzGg8rQp860gqLBFqRI02Y= +github.com/StirlingMarketingGroup/go-namecase v1.0.0/go.mod h1:ZsoSKcafcAzuBx+sndbxHu/RjDcDTrEdT4UvhniHfio= github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= @@ -252,6 +258,8 @@ github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8 github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/centrifuge/go-substrate-rpc-client/v4 v4.0.4 h1:G2kCJurlIkguX0oxxI9sPPENuQqMVhIhV9RVkh/dpDg= +github.com/centrifuge/go-substrate-rpc-client/v4 v4.0.4/go.mod h1:5g1oM4Zu3BOaLpsKQ+O8PAv2kNuq+kPcA1VzFbsSqxE= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -442,8 +450,16 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/base58 v1.0.4 h1:QJC6B0E0rXOPA8U/kw2rP+qiRJsUaE2Er+pYb3siUeA= +github.com/decred/base58 v1.0.4/go.mod h1:jJswKPEdvpFpvf7dsDvFZyLT22xZ9lWqEByX38oGd9E= +github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU= +github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 h1:3GIJYXQDAKpLEFriGFN8SbSffak10UXHGdIcFaMPykY= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0/go.mod h1:3s92l0paYkZoIHuj4X93Teg/HB7eGM9x/zokGw+u4mY= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= @@ -596,6 +612,7 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= @@ -873,6 +890,8 @@ github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOc github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845 h1:H+uM0Bv88eur3ZSsd2NGKg3YIiuXxwxtlN7HjE66UTU= +github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845/go.mod h1:c1tRKs5Tx7E2+uHGSyyncziFjvGpgv4H2HrqXeUQ/Uk= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -884,6 +903,8 @@ github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2t github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= +github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -925,6 +946,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jsternberg/zap-logfmt v1.2.0 h1:1v+PK4/B48cy8cfQbxL4FmmNZrjnIMr2BsnyEmXqv2o= github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b h1:FQ7+9fxhyp82ks9vAuyPzG0/vVbWwMwLJ+P6yJI5FN8= +github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b/go.mod h1:HMcgvsgd0Fjj4XXDkbjdmlbI505rUPBs6WBMYg2pXks= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -946,6 +969,9 @@ github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -979,6 +1005,10 @@ github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-libp2p-core v0.15.1 h1:0RY+Mi/ARK9DgG1g9xVQLb8dDaaU8tCePMtGALEfBnM= +github.com/libp2p/go-libp2p-core v0.15.1/go.mod h1:agSaboYM4hzB1cWekgVReqV5M4g5M+2eNNejV+1EEhs= +github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw= +github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= @@ -1039,9 +1069,14 @@ github.com/miguelmota/go-ethereum-hdwallet v0.1.1 h1:zdXGlHao7idpCBjEGTXThVAtMKs github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b h1:QrHweqAtyJ9EwCaGHBu1fghwxIPiopAHV06JlXrMHjk= github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b/go.mod h1:xxLb2ip6sSUts3g1irPVHyk/DGslwQsNOo9I7smJfNU= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= @@ -1088,9 +1123,30 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= +github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= +github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= +github.com/multiformats/go-multicodec v0.4.1 h1:BSJbf+zpghcZMZrwTYBGwy0CPcVZGWiC72Cp8bBd4R4= +github.com/multiformats/go-multicodec v0.4.1/go.mod h1:1Hj/eHRaVWSXiSNNfcEPcwZleTmdNP81xlxDLnWU9GQ= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.1.0 h1:CgAgwqk3//SVEw3T+6DqI4mWMyRuDwZtOWcJT0q9+EA= +github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1218,6 +1274,8 @@ github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCr github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/xxHash v0.1.5 h1:n/jBpwTHiER4xYvK3/CdPVnLDPchj8eTJFFLUb4QHBo= +github.com/pierrec/xxHash v0.1.5/go.mod h1:w2waW5Zoa/Wc4Yqe0wgrIYAGKqRMf7czn2HNKXmuL+I= github.com/pierrre/gotestcover v0.0.0-20160517101806-924dca7d15f0/go.mod h1:4xpMLz7RBWyB+ElzHu8Llua96TRCB3YwX+l5EP1wmHk= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= @@ -1370,6 +1428,8 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -1409,10 +1469,12 @@ github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiu github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= -github.com/strangelove-ventures/ibctest v0.0.0-20220809152134-4bd6b88f8572 h1:IwkNh0AX4Lkhc8nvv7sYrCLM323M8pokBEdeg/SUUFs= -github.com/strangelove-ventures/ibctest v0.0.0-20220809152134-4bd6b88f8572/go.mod h1:6sHMhSzbRK7Q2RUt2DRf+qAEYm8JnsiSlYVdQvcatdg= -github.com/strangelove-ventures/lens v0.5.2-0.20220810214843-6af97ce869d8 h1:s6Ppy7Gaym68hKv1MYaC7O/fimPElznyL1aKLAqopiA= -github.com/strangelove-ventures/lens v0.5.2-0.20220810214843-6af97ce869d8/go.mod h1:sD6+Hy963GymNHWrRfYCMdqPf9mmNPM1GvdYvLfu9ws= +github.com/strangelove-ventures/go-subkey v1.0.7 h1:cOP/Lajg3uxV/tvspu0m6+0Cu+DJgygkEAbx/s+f35I= +github.com/strangelove-ventures/go-subkey v1.0.7/go.mod h1:E34izOIEm+sZ1YmYawYRquqBQWeZBjVB4pF7bMuhc1c= +github.com/strangelove-ventures/ibctest/v5 v5.0.0-20220922235050-6baac8c666ea h1:jQvO399MoK7+NLigd7Vj7lGsa1Y7LWt8uTtbYGPTyYo= +github.com/strangelove-ventures/ibctest/v5 v5.0.0-20220922235050-6baac8c666ea/go.mod h1:C284t8FhFrldr1BfQHDLsAMMzAWczTgeruePi7M6TmA= +github.com/strangelove-ventures/lens v0.5.2-0.20220822201013-1e7ffd450f20 h1:nYM1gFMJHbV3aYdiNCCS5jfBe/uMkORHwg8DSWZ5MRA= +github.com/strangelove-ventures/lens v0.5.2-0.20220822201013-1e7ffd450f20/go.mod h1:qrmVarKca7XLvuTEkR9jO50FrOprxQxukbmB7fpVrVo= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -1588,8 +1650,9 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= +go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1614,6 +1677,7 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= @@ -1873,6 +1937,7 @@ golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2302,6 +2367,8 @@ gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -2369,6 +2436,8 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c= +lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc/v3 v3.36.0 h1:0kmRkTmqNidmu3c7BNDSdVHCxXCkWLmWmCIVX4LUboo= diff --git a/ibctest/ibc_test.go b/ibctest/ibc_test.go index fa79f4b5b7..16c10420b3 100644 --- a/ibctest/ibc_test.go +++ b/ibctest/ibc_test.go @@ -1,14 +1,16 @@ package ibctest_test import ( + "context" "testing" relayeribctest "github.com/cosmos/relayer/v2/ibctest" - "github.com/strangelove-ventures/ibctest" - "github.com/strangelove-ventures/ibctest/conformance" - "github.com/strangelove-ventures/ibctest/ibc" - ibctestrelayer "github.com/strangelove-ventures/ibctest/relayer" - "github.com/strangelove-ventures/ibctest/testreporter" + "github.com/cosmos/relayer/v2/relayer" + ibctest "github.com/strangelove-ventures/ibctest/v5" + "github.com/strangelove-ventures/ibctest/v5/conformance" + "github.com/strangelove-ventures/ibctest/v5/ibc" + ibctestrelayer "github.com/strangelove-ventures/ibctest/v5/relayer" + "github.com/strangelove-ventures/ibctest/v5/testreporter" "go.uber.org/zap/zaptest" ) @@ -26,6 +28,7 @@ func ibctestConformance(t *testing.T, rf ibctest.RelayerFactory) { }) conformance.Test( t, + context.Background(), []ibctest.ChainFactory{cf}, []ibctest.RelayerFactory{rf}, testreporter.NewNopReporter(), @@ -39,17 +42,16 @@ func TestRelayerInProcess(t *testing.T) { ibctestConformance(t, relayeribctest.RelayerFactory{}) } -// TestRelayerDocker runs the ibctest conformance tests against +// TestRelayerDockerEventProcessor runs the ibctest conformance tests against // the current state of this relayer implementation built in docker. // Relayer runs using the event processor. func TestRelayerDockerEventProcessor(t *testing.T) { t.Parallel() - relayeribctest.BuildRelayerImage(t) rf := ibctest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - ibctestrelayer.CustomDockerImage(relayeribctest.RelayerImageName, "latest"), + ibctestrelayer.CustomDockerImage(relayeribctest.RelayerImageName, "latest", "100:1000"), ibctestrelayer.ImagePull(false), ibctestrelayer.StartupFlags("--processor", "events", "--block-history", "100"), ) @@ -57,7 +59,7 @@ func TestRelayerDockerEventProcessor(t *testing.T) { ibctestConformance(t, rf) } -// TestRelayerDocker runs the ibctest conformance tests against +// TestRelayerDockerLegacyProcessor runs the ibctest conformance tests against // the current state of this relayer implementation built in docker. // Relayer runs using the legacy processor. func TestRelayerDockerLegacyProcessor(t *testing.T) { @@ -67,10 +69,33 @@ func TestRelayerDockerLegacyProcessor(t *testing.T) { rf := ibctest.NewBuiltinRelayerFactory( ibc.CosmosRly, zaptest.NewLogger(t), - ibctestrelayer.CustomDockerImage(relayeribctest.RelayerImageName, "latest"), + ibctestrelayer.CustomDockerImage(relayeribctest.RelayerImageName, "latest", "100:1000"), ibctestrelayer.ImagePull(false), ibctestrelayer.StartupFlags("--processor", "legacy"), ) ibctestConformance(t, rf) } + +// TestRelayerEventProcessor runs the ibctest conformance tests against +// the local relayer code. This is helpful for detecting race conditions. +// Relayer runs using the event processor. +func TestRelayerEventProcessor(t *testing.T) { + t.Parallel() + + ibctestConformance(t, relayeribctest.NewRelayerFactory(relayeribctest.RelayerConfig{ + Processor: relayer.ProcessorEvents, + InitialBlockHistory: 100, + })) +} + +// TestRelayerLegacyProcessor runs the ibctest conformance tests against +// the local relayer code. This is helpful for detecting race conditions. +// Relayer runs using the legacy processor. +func TestRelayerLegacyProcessor(t *testing.T) { + t.Parallel() + + ibctestConformance(t, relayeribctest.NewRelayerFactory(relayeribctest.RelayerConfig{ + Processor: relayer.ProcessorLegacy, + })) +} diff --git a/ibctest/path_filter_test.go b/ibctest/path_filter_test.go new file mode 100644 index 0000000000..a40bf577e9 --- /dev/null +++ b/ibctest/path_filter_test.go @@ -0,0 +1,306 @@ +package ibctest_test + +import ( + "context" + "fmt" + "testing" + + transfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types" + relayeribctest "github.com/cosmos/relayer/v2/ibctest" + "github.com/cosmos/relayer/v2/relayer" + "github.com/cosmos/relayer/v2/relayer/processor" + ibctest "github.com/strangelove-ventures/ibctest/v5" + "github.com/strangelove-ventures/ibctest/v5/ibc" + "github.com/strangelove-ventures/ibctest/v5/test" + "github.com/strangelove-ventures/ibctest/v5/testreporter" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" + "golang.org/x/sync/errgroup" +) + +// TestPathFilterAllow tests the channel allowlist +func TestPathFilterAllow(t *testing.T) { + t.Parallel() + ctx := context.Background() + + nv := 1 + nf := 0 + + // Chain Factory + cf := ibctest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*ibctest.ChainSpec{ + {Name: "gaia", Version: "v7.0.3", NumValidators: &nv, NumFullNodes: &nf}, + {Name: "osmosis", Version: "v11.0.1", NumValidators: &nv, NumFullNodes: &nf}, + }) + + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + gaia, osmosis := chains[0], chains[1] + + // Relayer Factory to construct relayer + r := relayeribctest.NewRelayerFactory(relayeribctest.RelayerConfig{ + Processor: relayer.ProcessorEvents, + InitialBlockHistory: 100, + }).Build(t, nil, "") + + // Prep Interchain + const ibcPath = "gaia-osmosis" + ic := ibctest.NewInterchain(). + AddChain(gaia). + AddChain(osmosis). + AddRelayer(r, "relayer"). + AddLink(ibctest.InterchainLink{ + Chain1: gaia, + Chain2: osmosis, + Relayer: r, + Path: ibcPath, + }) + + // Reporter/logs + rep := testreporter.NewNopReporter() + eRep := rep.RelayerExecReporter(t) + + client, network := ibctest.DockerSetup(t) + + // Build interchain + require.NoError(t, ic.Build(ctx, eRep, ibctest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + + SkipPathCreation: false, + })) + + // Get Channel ID + gaiaChans, err := r.GetChannels(ctx, eRep, gaia.Config().ChainID) + require.NoError(t, err) + gaiaChannel := gaiaChans[0] + osmosisChannel := gaiaChans[0].Counterparty + + r.UpdatePath(ctx, eRep, ibcPath, ibc.ChannelFilter{ + Rule: processor.RuleAllowList, + ChannelList: []string{gaiaChannel.ChannelID}, + }) + + // Create and Fund User Wallets + fundAmount := int64(10_000_000) + users := ibctest.GetAndFundTestUsers(t, ctx, "default", int64(fundAmount), gaia, osmosis) + + gaiaUser, osmosisUser := users[0], users[1] + + r.StartRelayer(ctx, eRep, ibcPath) + + // Send Transaction + amountToSend := int64(1_000_000) + gaiaDstAddress := gaiaUser.Bech32Address(osmosis.Config().Bech32Prefix) + osmosisDstAddress := osmosisUser.Bech32Address(gaia.Config().Bech32Prefix) + + gaiaHeight, err := gaia.Height(ctx) + require.NoError(t, err) + + osmosisHeight, err := osmosis.Height(ctx) + require.NoError(t, err) + + var eg errgroup.Group + eg.Go(func() error { + tx, err := gaia.SendIBCTransfer(ctx, gaiaChannel.ChannelID, gaiaUser.KeyName, ibc.WalletAmount{ + Address: gaiaDstAddress, + Denom: gaia.Config().Denom, + Amount: amountToSend, + }, + nil, + ) + if err != nil { + return err + } + if err := tx.Validate(); err != nil { + return err + } + _, err = test.PollForAck(ctx, gaia, gaiaHeight, gaiaHeight+10, tx.Packet) + return err + }) + + eg.Go(func() error { + tx, err := osmosis.SendIBCTransfer(ctx, osmosisChannel.ChannelID, osmosisUser.KeyName, ibc.WalletAmount{ + Address: osmosisDstAddress, + Denom: osmosis.Config().Denom, + Amount: amountToSend, + }, + nil, + ) + if err != nil { + return err + } + if err := tx.Validate(); err != nil { + return err + } + _, err = test.PollForAck(ctx, osmosis, osmosisHeight, osmosisHeight+10, tx.Packet) + return err + }) + // Acks should exist + require.NoError(t, eg.Wait()) + + // Trace IBC Denom + gaiaDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom(osmosisChannel.PortID, osmosisChannel.ChannelID, gaia.Config().Denom)) + gaiaIbcDenom := gaiaDenomTrace.IBCDenom() + + osmosisDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom(gaiaChannel.PortID, gaiaChannel.ChannelID, osmosis.Config().Denom)) + osmosisIbcDenom := osmosisDenomTrace.IBCDenom() + + // Test destination wallets have increased funds + gaiaIBCBalance, err := osmosis.GetBalance(ctx, gaiaDstAddress, gaiaIbcDenom) + require.NoError(t, err) + require.Equal(t, amountToSend, gaiaIBCBalance) + + osmosisIBCBalance, err := gaia.GetBalance(ctx, osmosisDstAddress, osmosisIbcDenom) + require.NoError(t, err) + require.Equal(t, amountToSend, osmosisIBCBalance) +} + +// TestPathFilterDeny tests the channel denylist +func TestPathFilterDeny(t *testing.T) { + t.Parallel() + ctx := context.Background() + + nv := 1 + nf := 0 + + // Chain Factory + cf := ibctest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*ibctest.ChainSpec{ + {Name: "gaia", Version: "v7.0.3", NumValidators: &nv, NumFullNodes: &nf}, + {Name: "osmosis", Version: "v11.0.1", NumValidators: &nv, NumFullNodes: &nf}, + }) + + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + gaia, osmosis := chains[0], chains[1] + + // Relayer Factory to construct relayer + r := relayeribctest.NewRelayerFactory(relayeribctest.RelayerConfig{ + Processor: relayer.ProcessorEvents, + InitialBlockHistory: 100, + }).Build(t, nil, "") + + // Prep Interchain + const ibcPath = "gaia-osmosis" + ic := ibctest.NewInterchain(). + AddChain(gaia). + AddChain(osmosis). + AddRelayer(r, "relayer"). + AddLink(ibctest.InterchainLink{ + Chain1: gaia, + Chain2: osmosis, + Relayer: r, + Path: ibcPath, + }) + + rep := testreporter.NewNopReporter() + eRep := rep.RelayerExecReporter(t) + + client, network := ibctest.DockerSetup(t) + + // Build interchain + require.NoError(t, ic.Build(ctx, eRep, ibctest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + + SkipPathCreation: false, + })) + + // Get Channel ID + gaiaChans, err := r.GetChannels(ctx, eRep, gaia.Config().ChainID) + require.NoError(t, err) + gaiaChannel := gaiaChans[0] + osmosisChannel := gaiaChans[0].Counterparty + + r.UpdatePath(ctx, eRep, ibcPath, ibc.ChannelFilter{ + Rule: processor.RuleDenyList, + ChannelList: []string{gaiaChannel.ChannelID}, + }) + + // Create and Fund User Wallets + fundAmount := int64(10_000_000) + users := ibctest.GetAndFundTestUsers(t, ctx, "default", int64(fundAmount), gaia, osmosis) + + gaiaUser, osmosisUser := users[0], users[1] + + r.StartRelayer(ctx, eRep, ibcPath) + + // Send Transaction + amountToSend := int64(1_000_000) + gaiaDstAddress := gaiaUser.Bech32Address(osmosis.Config().Bech32Prefix) + osmosisDstAddress := osmosisUser.Bech32Address(gaia.Config().Bech32Prefix) + + gaiaHeight, err := gaia.Height(ctx) + require.NoError(t, err) + + osmosisHeight, err := osmosis.Height(ctx) + require.NoError(t, err) + + var eg errgroup.Group + eg.Go(func() error { + tx, err := gaia.SendIBCTransfer(ctx, gaiaChannel.ChannelID, gaiaUser.KeyName, ibc.WalletAmount{ + Address: gaiaDstAddress, + Denom: gaia.Config().Denom, + Amount: amountToSend, + }, + nil, + ) + if err != nil { + return err + } + if err := tx.Validate(); err != nil { + return err + } + + // we want an error here + ack, err := test.PollForAck(ctx, gaia, gaiaHeight, gaiaHeight+10, tx.Packet) + if err == nil { + return fmt.Errorf("no error when error was expected when polling for ack: %+v", ack) + } + + return nil + }) + + eg.Go(func() error { + tx, err := osmosis.SendIBCTransfer(ctx, osmosisChannel.ChannelID, osmosisUser.KeyName, ibc.WalletAmount{ + Address: osmosisDstAddress, + Denom: osmosis.Config().Denom, + Amount: amountToSend, + }, + nil, + ) + if err != nil { + return err + } + if err := tx.Validate(); err != nil { + return err + } + + // we want an error here + ack, err := test.PollForAck(ctx, osmosis, osmosisHeight, osmosisHeight+10, tx.Packet) + if err == nil { + return fmt.Errorf("no error when error was expected when polling for ack: %+v", ack) + } + + return nil + }) + // Test that acks do not show up + require.NoError(t, eg.Wait()) + + // Trace IBC Denom + gaiaDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom(osmosisChannel.PortID, osmosisChannel.ChannelID, gaia.Config().Denom)) + gaiaIbcDenom := gaiaDenomTrace.IBCDenom() + + osmosisDenomTrace := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom(gaiaChannel.PortID, gaiaChannel.ChannelID, osmosis.Config().Denom)) + osmosisIbcDenom := osmosisDenomTrace.IBCDenom() + + // Test destination wallets do not have increased funds + gaiaIBCBalance, err := osmosis.GetBalance(ctx, gaiaDstAddress, gaiaIbcDenom) + require.NoError(t, err) + require.Equal(t, int64(0), gaiaIBCBalance) + + osmosisIBCBalance, err := gaia.GetBalance(ctx, osmosisDstAddress, osmosisIbcDenom) + require.NoError(t, err) + require.Equal(t, int64(0), osmosisIBCBalance) +} diff --git a/ibctest/relay_many_test.go b/ibctest/relay_many_test.go new file mode 100644 index 0000000000..a55595a7bf --- /dev/null +++ b/ibctest/relay_many_test.go @@ -0,0 +1,189 @@ +package ibctest_test + +import ( + "context" + "testing" + + transfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types" + relayeribctest "github.com/cosmos/relayer/v2/ibctest" + ibctest "github.com/strangelove-ventures/ibctest/v5" + "github.com/strangelove-ventures/ibctest/v5/chain/cosmos" + "github.com/strangelove-ventures/ibctest/v5/ibc" + "github.com/strangelove-ventures/ibctest/v5/test" + "github.com/strangelove-ventures/ibctest/v5/testreporter" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" + "golang.org/x/sync/errgroup" +) + +// TestRelayerMultiplePathsSingleProcess tests relaying multiple paths +// from the same process using the go relayer. A single +// CosmosChainProcessor (gaia) will feed data to two PathProcessors (gaia-osmosis and gaia-juno). +func TestRelayerMultiplePathsSingleProcess(t *testing.T) { + r := relayeribctest.NewRelayer(t, relayeribctest.RelayerConfig{}) + + rep := testreporter.NewNopReporter() + eRep := rep.RelayerExecReporter(t) + + ctx := context.Background() + + // Define chains involved in test + cf := ibctest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*ibctest.ChainSpec{ + { + Name: "gaia", + ChainName: "gaia", + Version: "v7.0.3", + }, + { + Name: "osmosis", + ChainName: "osmosis", + Version: "v11.0.1", + }, + { + Name: "juno", + ChainName: "juno", + Version: "v9.0.0", + }, + }) + + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + + gaia, osmosis, juno := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain), chains[2].(*cosmos.CosmosChain) + gaiaCfg, osmosisCfg, junoCfg := gaia.Config(), osmosis.Config(), juno.Config() + + // Build the network; spin up the chains and configure the relayer + const pathGaiaOsmosis = "gaia-osmosis" + const pathGaiaJuno = "gaia-juno" + const relayerName = "relayer" + + ic := ibctest.NewInterchain(). + AddChain(gaia). + AddChain(osmosis). + AddChain(juno). + AddRelayer(r, relayerName). + AddLink(ibctest.InterchainLink{ + Chain1: gaia, + Chain2: osmosis, + Relayer: r, + Path: pathGaiaOsmosis, + }). + AddLink(ibctest.InterchainLink{ + Chain1: gaia, + Chain2: juno, + Relayer: r, + Path: pathGaiaJuno, + }) + + client, network := ibctest.DockerSetup(t) + + require.NoError(t, ic.Build(ctx, eRep, ibctest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + BlockDatabaseFile: ibctest.DefaultBlockDatabaseFilepath(), + + SkipPathCreation: false, + })) + t.Cleanup(func() { + _ = ic.Close() + }) + + // Fund user accounts, so we can query balances and make assertions. + const userFunds = int64(10_000_000) + users := ibctest.GetAndFundTestUsers(t, ctx, t.Name(), userFunds, gaia, osmosis, juno) + gaiaUser, osmosisUser, junoUser := users[0], users[1], users[2] + + // Wait a few blocks for user accounts to be created on chain. + err = test.WaitForBlocks(ctx, 2, gaia, osmosis, juno) + require.NoError(t, err) + + // Start the relayers + err = r.StartRelayer(ctx, eRep, pathGaiaOsmosis, pathGaiaJuno) + require.NoError(t, err) + + t.Cleanup( + func() { + err := r.StopRelayer(ctx, eRep) + if err != nil { + t.Logf("an error occured while stopping the relayer: %s", err) + } + }, + ) + + // Wait a few blocks for the relayer to start. + err = test.WaitForBlocks(ctx, 2, gaia, osmosis, juno) + require.NoError(t, err) + + gaiaAddress := gaiaUser.Bech32Address(gaiaCfg.Bech32Prefix) + require.NotEmpty(t, gaiaAddress) + + osmosisAddress := osmosisUser.Bech32Address(osmosisCfg.Bech32Prefix) + require.NotEmpty(t, osmosisAddress) + + junoAddress := junoUser.Bech32Address(junoCfg.Bech32Prefix) + require.NotEmpty(t, junoAddress) + + // get ibc chans + osmosisChans, err := r.GetChannels(ctx, eRep, osmosisCfg.ChainID) + require.NoError(t, err) + + junoChans, err := r.GetChannels(ctx, eRep, junoCfg.ChainID) + require.NoError(t, err) + + osmosisIBCDenom := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom(osmosisChans[0].Counterparty.PortID, osmosisChans[0].Counterparty.ChannelID, osmosisCfg.Denom)).IBCDenom() + junoIBCDenom := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom(junoChans[0].Counterparty.PortID, junoChans[0].Counterparty.ChannelID, junoCfg.Denom)).IBCDenom() + + var eg errgroup.Group + + const transferAmount = int64(1_000_000) + + eg.Go(func() error { + osmosisHeight, err := osmosis.Height(ctx) + if err != nil { + return err + } + // Fund gaia user with ibc denom osmo + tx, err := osmosis.SendIBCTransfer(ctx, osmosisChans[0].ChannelID, osmosisUser.KeyName, ibc.WalletAmount{ + Amount: transferAmount, + Denom: osmosisCfg.Denom, + Address: gaiaAddress, + }, nil) + if err != nil { + return err + } + _, err = test.PollForAck(ctx, osmosis, osmosisHeight, osmosisHeight+10, tx.Packet) + return err + }) + + eg.Go(func() error { + junoHeight, err := juno.Height(ctx) + if err != nil { + return err + } + // Fund gaia user with ibc denom juno + tx, err := juno.SendIBCTransfer(ctx, junoChans[0].ChannelID, junoUser.KeyName, ibc.WalletAmount{ + Amount: transferAmount, + Denom: junoCfg.Denom, + Address: gaiaAddress, + }, nil) + if err != nil { + return err + } + _, err = test.PollForAck(ctx, juno, junoHeight, junoHeight+10, tx.Packet) + return err + }) + + require.NoError(t, eg.Wait()) + + osmosisOnGaiaBalance, err := gaia.GetBalance(ctx, gaiaAddress, osmosisIBCDenom) + require.NoError(t, err) + + require.Equal(t, transferAmount, osmosisOnGaiaBalance) + + junoOnGaiaBalance, err := gaia.GetBalance(ctx, gaiaAddress, junoIBCDenom) + require.NoError(t, err) + + require.Equal(t, transferAmount, junoOnGaiaBalance) + +} diff --git a/ibctest/relayer.go b/ibctest/relayer.go index 423f7ed0fb..670d3d9b09 100644 --- a/ibctest/relayer.go +++ b/ibctest/relayer.go @@ -4,14 +4,16 @@ import ( "context" "encoding/json" "fmt" + "strconv" "strings" "testing" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/relayer/v2/cmd" "github.com/cosmos/relayer/v2/internal/relayertest" + "github.com/cosmos/relayer/v2/relayer" "github.com/cosmos/relayer/v2/relayer/chains/cosmos" - "github.com/strangelove-ventures/ibctest/ibc" + "github.com/strangelove-ventures/ibctest/v5/ibc" "go.uber.org/zap" "go.uber.org/zap/zaptest" ) @@ -19,13 +21,33 @@ import ( type Relayer struct { t *testing.T - home string + config RelayerConfig + home string // Set during StartRelayer. errCh chan error cancel context.CancelFunc } +// Build returns a relayer interface +func NewRelayer( + t *testing.T, + config RelayerConfig, +) ibc.Relayer { + r := &Relayer{ + t: t, + home: t.TempDir(), + config: config, + } + + res := r.sys().Run(zaptest.NewLogger(t), "config", "init", "--memo", config.Memo) + if res.Err != nil { + t.Fatalf("failed to rly config init: %v", res.Err) + } + + return r +} + func (r *Relayer) sys() *relayertest.System { return &relayertest.System{HomeDir: r.home} } @@ -47,25 +69,26 @@ func (r *Relayer) AddChainConfiguration(ctx context.Context, _ ibc.RelayerExecRe KeyringBackend: keyring.BackendTest, GasAdjustment: chainConfig.GasAdjustment, GasPrices: chainConfig.GasPrices, - Debug: true, - Timeout: "10s", - OutputFormat: "json", - SignModeStr: "direct", + // MinGasAmount: chainConfig.MinGasAmount, // TODO + Debug: true, + Timeout: "10s", + OutputFormat: "json", + SignModeStr: "direct", }, }) return nil } -func (r *Relayer) AddKey(ctx context.Context, _ ibc.RelayerExecReporter, chainID, keyName string) (ibc.RelayerWallet, error) { +func (r *Relayer) AddKey(ctx context.Context, _ ibc.RelayerExecReporter, chainID, keyName string) (ibc.Wallet, error) { res := r.sys().RunC(ctx, r.log(), "keys", "add", chainID, keyName) if res.Err != nil { - return ibc.RelayerWallet{}, res.Err + return ibc.Wallet{}, res.Err } - var w ibc.RelayerWallet + var w ibc.Wallet if err := json.Unmarshal(res.Stdout.Bytes(), &w); err != nil { - return ibc.RelayerWallet{}, err + return ibc.Wallet{}, err } return w, nil @@ -87,6 +110,17 @@ func (r *Relayer) GeneratePath(ctx context.Context, _ ibc.RelayerExecReporter, s return nil } +func (r *Relayer) UpdatePath(ctx context.Context, _ ibc.RelayerExecReporter, pathName string, filter ibc.ChannelFilter) error { + res := r.sys().RunC(ctx, r.log(), "paths", "update", pathName, + "--filter-rule", filter.Rule, + "--filter-channels", strings.Join(filter.ChannelList, ","), + ) + if res.Err != nil { + return res.Err + } + return nil +} + func (r *Relayer) GetChannels(ctx context.Context, _ ibc.RelayerExecReporter, chainID string) ([]ibc.ChannelOutput, error) { res := r.sys().RunC(ctx, r.log(), "q", "channels", chainID) if res.Err != nil { @@ -108,12 +142,14 @@ func (r *Relayer) GetChannels(ctx context.Context, _ ibc.RelayerExecReporter, ch return channels, nil } -func (r *Relayer) LinkPath(ctx context.Context, _ ibc.RelayerExecReporter, pathName string, opts ibc.CreateChannelOptions) error { +func (r *Relayer) LinkPath(ctx context.Context, _ ibc.RelayerExecReporter, pathName string, chanOpts ibc.CreateChannelOptions, clientOpts ibc.CreateClientOptions) error { res := r.sys().RunC(ctx, r.log(), "tx", "link", pathName, - "--src-port", opts.SourcePortName, - "--dst-port", opts.DestPortName, - "--order", opts.Order.String(), - "--version", opts.Version) + "--src-port", chanOpts.SourcePortName, + "--dst-port", chanOpts.DestPortName, + "--order", chanOpts.Order.String(), + "--version", chanOpts.Version, + "--client-tp", clientOpts.TrustingPeriod, + ) if res.Err != nil { return res.Err } @@ -171,8 +207,8 @@ func (r *Relayer) CreateConnections(ctx context.Context, _ ibc.RelayerExecReport return nil } -func (r *Relayer) CreateClients(ctx context.Context, _ ibc.RelayerExecReporter, pathName string) error { - res := r.sys().RunC(ctx, r.log(), "tx", "clients", pathName) +func (r *Relayer) CreateClients(ctx context.Context, _ ibc.RelayerExecReporter, pathName string, clientOpts ibc.CreateClientOptions) error { + res := r.sys().RunC(ctx, r.log(), "tx", "clients", pathName, "--client-tp", clientOpts.TrustingPeriod) if res.Err != nil { return res.Err } @@ -187,7 +223,7 @@ func (r *Relayer) UpdateClients(ctx context.Context, _ ibc.RelayerExecReporter, return nil } -func (r *Relayer) StartRelayer(ctx context.Context, _ ibc.RelayerExecReporter, pathName string) error { +func (r *Relayer) StartRelayer(ctx context.Context, _ ibc.RelayerExecReporter, pathNames ...string) error { if r.errCh != nil || r.cancel != nil { panic(fmt.Errorf("StartRelayer called multiple times without being stopped")) } @@ -195,11 +231,22 @@ func (r *Relayer) StartRelayer(ctx context.Context, _ ibc.RelayerExecReporter, p r.errCh = make(chan error, 1) ctx, r.cancel = context.WithCancel(ctx) - go r.start(ctx, pathName) + if r.config.Processor == "" { + r.config.Processor = relayer.ProcessorEvents + } + args := append([]string{ + "--processor", r.config.Processor, + "--block-history", strconv.FormatUint(r.config.InitialBlockHistory, 10), + }, pathNames...) + + go r.start(ctx, args...) return nil } func (r *Relayer) StopRelayer(ctx context.Context, _ ibc.RelayerExecReporter) error { + if r.cancel == nil { + return nil + } r.cancel() err := <-r.errCh @@ -209,11 +256,12 @@ func (r *Relayer) StopRelayer(ctx context.Context, _ ibc.RelayerExecReporter) er } // start runs in its own goroutine, blocking until "rly start" finishes. -func (r *Relayer) start(ctx context.Context, pathName string) { +func (r *Relayer) start(ctx context.Context, remainingArgs ...string) { // Start the debug server on a random port. // It won't be reachable without introspecting the output, // but this will allow catching any possible data races around the debug server. - res := r.sys().RunC(ctx, r.log(), "start", pathName, "--debug-addr", "localhost:0") + args := append([]string{"start", "--debug-addr", "localhost:0"}, remainingArgs...) + res := r.sys().RunC(ctx, r.log(), args...) if res.Err != nil { r.errCh <- res.Err return @@ -258,11 +306,11 @@ func (r *Relayer) FlushPackets(ctx context.Context, _ ibc.RelayerExecReporter, p return nil } -func (r *Relayer) GetWallet(chainID string) (ibc.RelayerWallet, bool) { +func (r *Relayer) GetWallet(chainID string) (ibc.Wallet, bool) { res := r.sys().RunC(context.Background(), r.log(), "keys", "show", chainID) if res.Err != nil { - return ibc.RelayerWallet{}, false + return ibc.Wallet{}, false } address := strings.TrimSpace(res.Stdout.String()) - return ibc.RelayerWallet{Address: address}, true + return ibc.Wallet{Address: address}, true } diff --git a/ibctest/relayer_factory.go b/ibctest/relayer_factory.go index a1dbf8ad76..3802f83b01 100644 --- a/ibctest/relayer_factory.go +++ b/ibctest/relayer_factory.go @@ -1,36 +1,39 @@ package ibctest import ( - "fmt" "testing" "github.com/docker/docker/client" - "github.com/strangelove-ventures/ibctest/ibc" - "github.com/strangelove-ventures/ibctest/label" - ibctestrelayer "github.com/strangelove-ventures/ibctest/relayer" - "go.uber.org/zap/zaptest" + "github.com/strangelove-ventures/ibctest/v5/ibc" + "github.com/strangelove-ventures/ibctest/v5/label" + ibctestrelayer "github.com/strangelove-ventures/ibctest/v5/relayer" ) // RelayerFactory implements the ibctest RelayerFactory interface. -type RelayerFactory struct{} +type RelayerFactory struct { + config RelayerConfig +} + +// LocalRelayerConfig defines parameters for customizing a LocalRelayer. +type RelayerConfig struct { + Processor string + Memo string + InitialBlockHistory uint64 +} + +func NewRelayerFactory(config RelayerConfig) RelayerFactory { + return RelayerFactory{ + config: config, + } +} // Build returns a relayer interface -func (RelayerFactory) Build( +func (rf RelayerFactory) Build( t *testing.T, _ *client.Client, networkID string, ) ibc.Relayer { - r := &Relayer{ - t: t, - home: t.TempDir(), - } - - res := r.sys().Run(zaptest.NewLogger(t), "config", "init") - if res.Err != nil { - panic(fmt.Errorf("failed to rly config init: %w", res.Err)) - } - - return r + return NewRelayer(t, rf.config) } func (RelayerFactory) Capabilities() map[ibctestrelayer.Capability]bool { diff --git a/ibctest/relayer_override_test.go b/ibctest/relayer_override_test.go new file mode 100644 index 0000000000..b665fce2ee --- /dev/null +++ b/ibctest/relayer_override_test.go @@ -0,0 +1,183 @@ +package ibctest_test + +import ( + "context" + "encoding/json" + "testing" + + "github.com/cosmos/relayer/v2/cmd" + relayeribctest "github.com/cosmos/relayer/v2/ibctest" + "github.com/strangelove-ventures/ibctest/v5" + "github.com/strangelove-ventures/ibctest/v5/chain/cosmos" + "github.com/strangelove-ventures/ibctest/v5/ibc" + ibctestrelayer "github.com/strangelove-ventures/ibctest/v5/relayer" + ibctestrly "github.com/strangelove-ventures/ibctest/v5/relayer/rly" + "github.com/strangelove-ventures/ibctest/v5/test" + "github.com/strangelove-ventures/ibctest/v5/testreporter" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" +) + +// TestClientOverrideFlag tests that the --override flag is being respected when attempting to create new light clients. +// If the override flag is not present, the relayer should attempt to look for an existing light client if there +// is a client-id present in the relative path config. If the override flag is present, the relayer should always +// attempt to create a new light client and then overwrite the config file if successful. +func TestClientOverrideFlag(t *testing.T) { + relayeribctest.BuildRelayerImage(t) + + client, network := ibctest.DockerSetup(t) + r := ibctest.NewBuiltinRelayerFactory( + ibc.CosmosRly, + zaptest.NewLogger(t), + ibctestrelayer.CustomDockerImage(relayeribctest.RelayerImageName, "latest", "100:1000"), + ibctestrelayer.ImagePull(false), + ).Build(t, client, network) + + rep := testreporter.NewNopReporter() + eRep := rep.RelayerExecReporter(t) + + ctx := context.Background() + + // Define chains involved in test + cf := ibctest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*ibctest.ChainSpec{ + { + Name: "gaia", + ChainName: "gaia", + Version: "v7.0.3", + }, + { + Name: "osmosis", + ChainName: "osmosis", + Version: "v11.0.1", + }, + }) + + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + + gaia, osmosis := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain) + + // Build the network; spin up the chains and configure the relayer + const pathGaiaOsmosis = "gaia-osmosis" + const relayerName = "relayer" + + ic := ibctest.NewInterchain(). + AddChain(gaia). + AddChain(osmosis). + AddRelayer(r, relayerName). + AddLink(ibctest.InterchainLink{ + Chain1: gaia, + Chain2: osmosis, + Relayer: r, + Path: pathGaiaOsmosis, + }) + + require.NoError(t, ic.Build(ctx, eRep, ibctest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + BlockDatabaseFile: ibctest.DefaultBlockDatabaseFilepath(), + + SkipPathCreation: true, + })) + t.Cleanup(func() { + _ = ic.Close() + }) + + // Start the relayer + err = r.StartRelayer(ctx, eRep, pathGaiaOsmosis) + require.NoError(t, err) + + t.Cleanup( + func() { + err := r.StopRelayer(ctx, eRep) + if err != nil { + t.Logf("an error occured while stopping the relayer: %s", err) + } + }, + ) + + // Wait a few blocks for the relayer to start. + err = test.WaitForBlocks(ctx, 2, gaia, osmosis) + require.NoError(t, err) + + // Generate a new IBC path + err = r.GeneratePath(ctx, eRep, gaia.Config().ChainID, osmosis.Config().ChainID, pathGaiaOsmosis) + require.NoError(t, err) + + // Create clients and wait a few blocks for the clients to be created + err = r.CreateClients(ctx, eRep, pathGaiaOsmosis, ibc.DefaultClientOpts()) + require.NoError(t, err) + + err = test.WaitForBlocks(ctx, 5, gaia, osmosis) + require.NoError(t, err) + + // Dump relayer config and verify client IDs are written to path config + rly := r.(*ibctestrly.CosmosRelayer) + + showConfig := []string{"rly", "config", "show", "-j", "--home", rly.HomeDir()} + res := r.Exec(ctx, eRep, showConfig, nil) + require.NoError(t, res.Err) + + config := &cmd.Config{} + err = json.Unmarshal(res.Stdout, config) + require.NoError(t, err) + + rlyPath, err := config.Paths.Get(pathGaiaOsmosis) + require.NoError(t, err) + + srcClientID := rlyPath.Src.ClientID + dstClientID := rlyPath.Dst.ClientID + + require.NotEmpty(t, srcClientID) + require.NotEmpty(t, dstClientID) + + // Create clients again without override and verify it was a noop + err = r.CreateClients(ctx, eRep, pathGaiaOsmosis, ibc.DefaultClientOpts()) + require.NoError(t, err) + + err = test.WaitForBlocks(ctx, 2, gaia, osmosis) + require.NoError(t, err) + + res = r.Exec(ctx, eRep, showConfig, nil) + require.NoError(t, res.Err) + + err = json.Unmarshal(res.Stdout, config) + require.NoError(t, err) + + rlyPath, err = config.Paths.Get(pathGaiaOsmosis) + require.NoError(t, err) + + newSrcClientID := rlyPath.Src.ClientID + newDstClientID := rlyPath.Dst.ClientID + + require.NotEmpty(t, newSrcClientID) + require.NotEmpty(t, newDstClientID) + require.Equal(t, srcClientID, newSrcClientID) + require.Equal(t, dstClientID, newDstClientID) + + // Create clients again with override and verify new client IDs are generated and added to config + clientsOverride := []string{"rly", "tx", "clients", pathGaiaOsmosis, "--override", "--home", rly.HomeDir()} + res = r.Exec(ctx, eRep, clientsOverride, nil) + require.NoError(t, res.Err) + + err = test.WaitForBlocks(ctx, 5, gaia, osmosis) + require.NoError(t, err) + + res = r.Exec(ctx, eRep, showConfig, nil) + require.NoError(t, res.Err) + + err = json.Unmarshal(res.Stdout, config) + require.NoError(t, err) + + rlyPath, err = config.Paths.Get(pathGaiaOsmosis) + require.NoError(t, err) + + newSrcClientID = rlyPath.Src.ClientID + newDstClientID = rlyPath.Dst.ClientID + + require.NotEmpty(t, newSrcClientID) + require.NotEmpty(t, newDstClientID) + require.NotEqual(t, srcClientID, newSrcClientID) + require.NotEqual(t, dstClientID, newDstClientID) +} diff --git a/relayer/chains/cosmos/cosmos_chain_processor.go b/relayer/chains/cosmos/cosmos_chain_processor.go index 2b49b81f68..43f15f493a 100644 --- a/relayer/chains/cosmos/cosmos_chain_processor.go +++ b/relayer/chains/cosmos/cosmos_chain_processor.go @@ -55,9 +55,6 @@ type CosmosChainProcessor struct { } func NewCosmosChainProcessor(log *zap.Logger, provider *CosmosProvider, metrics *processor.PrometheusMetrics) *CosmosChainProcessor { - - provider.SetMetrics(metrics) - return &CosmosChainProcessor{ log: log.With(zap.String("chain_name", provider.ChainName()), zap.String("chain_id", provider.ChainId())), chainProvider: provider, @@ -398,12 +395,12 @@ func (ccp *CosmosChainProcessor) queryCycle(ctx context.Context, persistence *qu pp.HandleNewData(chainID, processor.ChainProcessorCacheData{ LatestBlock: ccp.latestBlock, LatestHeader: latestHeader, - IBCMessagesCache: ibcMessagesCache, + IBCMessagesCache: ibcMessagesCache.Clone(), InSync: ccp.inSync, ClientState: clientState, ConnectionStateCache: ccp.connectionStateCache.FilterForClient(clientID), ChannelStateCache: ccp.channelStateCache.FilterForClient(clientID, ccp.channelConnections, ccp.connectionClients), - IBCHeaderCache: ibcHeaderCache, + IBCHeaderCache: ibcHeaderCache.Clone(), }) } diff --git a/relayer/chains/cosmos/provider.go b/relayer/chains/cosmos/provider.go index 91ee984d1e..4f455d725a 100644 --- a/relayer/chains/cosmos/provider.go +++ b/relayer/chains/cosmos/provider.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "sync" "time" sdk "github.com/cosmos/cosmos-sdk/types" @@ -34,6 +35,7 @@ type CosmosProviderConfig struct { KeyringBackend string `json:"keyring-backend" yaml:"keyring-backend"` GasAdjustment float64 `json:"gas-adjustment" yaml:"gas-adjustment"` GasPrices string `json:"gas-prices" yaml:"gas-prices"` + MinGasAmount uint64 `json:"min-gas-amount" yaml:"min-gas-amount"` Debug bool `json:"debug" yaml:"debug"` Timeout string `json:"timeout" yaml:"timeout"` OutputFormat string `json:"output-format" yaml:"output-format"` @@ -82,6 +84,7 @@ func ChainClientConfig(pcfg *CosmosProviderConfig) *lens.ChainClientConfig { KeyringBackend: pcfg.KeyringBackend, GasAdjustment: pcfg.GasAdjustment, GasPrices: pcfg.GasPrices, + MinGasAmount: pcfg.MinGasAmount, Debug: pcfg.Debug, Timeout: pcfg.Timeout, OutputFormat: pcfg.OutputFormat, @@ -100,8 +103,10 @@ type CosmosProvider struct { txMu sync.Mutex // metrics to monitor the provider - TotalFees sdk.Coins - metrics *processor.PrometheusMetrics + TotalFees sdk.Coins + totalFeesMu sync.Mutex + + metrics *processor.PrometheusMetrics } type CosmosIBCHeader struct { diff --git a/relayer/chains/cosmos/tx.go b/relayer/chains/cosmos/tx.go index ef74368fda..fdd770f0c3 100644 --- a/relayer/chains/cosmos/tx.go +++ b/relayer/chains/cosmos/tx.go @@ -1116,7 +1116,9 @@ func (cc *CosmosProvider) UpdateFeesSpent(chain, key string, fees sdk.Coins) { return } + cc.totalFeesMu.Lock() cc.TotalFees = cc.TotalFees.Add(fees...) + cc.totalFeesMu.Unlock() for _, fee := range cc.TotalFees { // Convert to a big float to get a float64 for metrics diff --git a/relayer/channel.go b/relayer/channel.go index 0ec489974b..60411410b7 100644 --- a/relayer/channel.go +++ b/relayer/channel.go @@ -45,15 +45,6 @@ func (c *Chain) CreateOpenChannels( } } - srcPathChain := pathChain{ - provider: c.ChainProvider, - pathEnd: processor.NewPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, "", []processor.ChainChannelKey{}), - } - dstPathChain := pathChain{ - provider: dst.ChainProvider, - pathEnd: processor.NewPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, "", []processor.ChainChannelKey{}), - } - // Timeout is per message. Four channel handshake messages, allowing maxRetries for each. processorTimeout := timeout * 4 * time.Duration(maxRetries) @@ -62,8 +53,8 @@ func (c *Chain) CreateOpenChannels( pp := processor.NewPathProcessor( c.log, - srcPathChain.pathEnd, - dstPathChain.pathEnd, + processor.NewPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, "", []processor.ChainChannelKey{}), + processor.NewPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, "", []processor.ChainChannelKey{}), nil, memo, ) @@ -77,8 +68,8 @@ func (c *Chain) CreateOpenChannels( return processor.NewEventProcessor(). WithChainProcessors( - srcPathChain.chainProcessor(c.log, nil), - dstPathChain.chainProcessor(c.log, nil), + c.chainProcessor(c.log, nil), + dst.chainProcessor(c.log, nil), ). WithPathProcessors(pp). WithInitialBlockHistory(0). @@ -118,15 +109,6 @@ func (c *Chain) CloseChannel( memo string, pathName string, ) error { - srcPathChain := pathChain{ - provider: c.ChainProvider, - pathEnd: processor.NewPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, "", []processor.ChainChannelKey{}), - } - dstPathChain := pathChain{ - provider: dst.ChainProvider, - pathEnd: processor.NewPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, "", []processor.ChainChannelKey{}), - } - // Timeout is per message. Two close channel handshake messages, allowing maxRetries for each. processorTimeout := timeout * 2 * time.Duration(maxRetries) @@ -135,13 +117,13 @@ func (c *Chain) CloseChannel( return processor.NewEventProcessor(). WithChainProcessors( - srcPathChain.chainProcessor(c.log, nil), - dstPathChain.chainProcessor(c.log, nil), + c.chainProcessor(c.log, nil), + dst.chainProcessor(c.log, nil), ). WithPathProcessors(processor.NewPathProcessor( c.log, - srcPathChain.pathEnd, - dstPathChain.pathEnd, + processor.NewPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, "", []processor.ChainChannelKey{}), + processor.NewPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, "", []processor.ChainChannelKey{}), nil, memo, )). diff --git a/relayer/client.go b/relayer/client.go index 15e7670d57..cb5c0cfae6 100644 --- a/relayer/client.go +++ b/relayer/client.go @@ -14,7 +14,7 @@ import ( ) // CreateClients creates clients for src on dst and dst on src if the client ids are unspecified. -func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override bool, customClientTrustingPeriod time.Duration, memo string) (bool, error) { +func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override bool, customClientTrustingPeriod time.Duration, memo string) (string, string, error) { // Query the latest heights on src and dst and retry if the query fails var srch, dsth int64 if err := retry.Do(func() error { @@ -25,7 +25,7 @@ func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterE } return nil }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr); err != nil { - return false, err + return "", "", err } // Query the light signed headers for src & dst at the heights srch & dsth, retry if the query fails @@ -50,15 +50,15 @@ func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterE ) srch, dsth, _ = QueryLatestHeights(ctx, c, dst) })); err != nil { - return false, err + return "", "", err } - var modifiedSrc, modifiedDst bool + var clientSrc, clientDst string eg, egCtx := errgroup.WithContext(ctx) eg.Go(func() error { var err error // Create client on src for dst if the client id is unspecified - modifiedSrc, err = CreateClient(egCtx, c, dst, srcUpdateHeader, dstUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) + clientSrc, err = CreateClient(egCtx, c, dst, srcUpdateHeader, dstUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) if err != nil { return fmt.Errorf("failed to create client on src chain{%s}: %w", c.ChainID(), err) } @@ -68,7 +68,7 @@ func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterE eg.Go(func() error { var err error // Create client on dst for src if the client id is unspecified - modifiedDst, err = CreateClient(egCtx, dst, c, dstUpdateHeader, srcUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) + clientDst, err = CreateClient(egCtx, dst, c, dstUpdateHeader, srcUpdateHeader, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour, override, customClientTrustingPeriod, memo) if err != nil { return fmt.Errorf("failed to create client on dst chain{%s}: %w", dst.ChainID(), err) } @@ -77,7 +77,7 @@ func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterE if err := eg.Wait(); err != nil { // If one completed successfully and the other didn't, we can still report modified. - return modifiedSrc || modifiedDst, err + return clientSrc, clientDst, err } c.log.Info( @@ -88,7 +88,7 @@ func (c *Chain) CreateClients(ctx context.Context, dst *Chain, allowUpdateAfterE zap.String("dst_chain_id", dst.ChainID()), ) - return modifiedSrc || modifiedDst, nil + return clientSrc, clientDst, nil } // CreateClient creates client tracking dst on src. @@ -100,23 +100,22 @@ func CreateClient( allowUpdateAfterMisbehaviour bool, override bool, customClientTrustingPeriod time.Duration, - memo string) (bool, error) { - // If a client ID was specified in the path, ensure it exists. - if src.PathEnd.ClientID != "" { + memo string) (string, error) { + // If a client ID was specified in the path and override is not set, ensure the client exists. + if !override && src.PathEnd.ClientID != "" { // TODO: check client is not expired _, err := src.ChainProvider.QueryClientStateResponse(ctx, int64(srcUpdateHeader.Height()), src.ClientID()) if err != nil { - return false, fmt.Errorf("please ensure provided on-chain client (%s) exists on the chain (%s): %v", + return "", fmt.Errorf("please ensure provided on-chain client (%s) exists on the chain (%s): %w", src.PathEnd.ClientID, src.ChainID(), err) } - return false, nil + return "", nil } // Otherwise, create client for the destination chain on the source chain. // Query the trusting period for dst and retry if the query fails - // var tp time.Duration tp := customClientTrustingPeriod if tp == 0 { if err := retry.Do(func() error { @@ -130,7 +129,7 @@ func CreateClient( } return nil }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr); err != nil { - return false, err + return "", err } } @@ -152,14 +151,14 @@ func CreateClient( } return nil }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr); err != nil { - return false, err + return "", err } // We want to create a light client on the src chain which tracks the state of the dst chain. // So we build a new client state from dst and attempt to use this for creating the light client on src. clientState, err := dst.ChainProvider.NewClientState(dst.ChainID(), dstUpdateHeader, tp, ubdPeriod, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour) if err != nil { - return false, fmt.Errorf("failed to create new client state for chain{%s}: %w", dst.ChainID(), err) + return "", fmt.Errorf("failed to create new client state for chain{%s}: %w", dst.ChainID(), err) } var clientID string @@ -170,7 +169,7 @@ func CreateClient( // proposed new client state from dst. clientID, err = findMatchingClient(ctx, src, dst, clientState) if err != nil { - return false, fmt.Errorf("failed to find a matching client for the new client state: %w", err) + return "", fmt.Errorf("failed to find a matching client for the new client state: %w", err) } } @@ -182,7 +181,7 @@ func CreateClient( zap.String("dst_chain_id", dst.ChainID()), ) src.PathEnd.ClientID = clientID - return true, nil + return clientID, nil } src.log.Debug( @@ -195,10 +194,9 @@ func CreateClient( // the dst chains implementation of CreateClient, to ensure the proper client/header // logic is executed, but the message gets submitted on the src chain which means // we need to sign with the address from src. - createMsg, err := src.ChainProvider.MsgCreateClient(clientState, dstUpdateHeader.ConsensusState()) if err != nil { - return false, fmt.Errorf("failed to compose CreateClient msg for chain{%s} tracking the state of chain{%s}: %w", + return "", fmt.Errorf("failed to compose CreateClient msg for chain{%s} tracking the state of chain{%s}: %w", src.ChainID(), dst.ChainID(), err) } @@ -222,13 +220,13 @@ func CreateClient( return nil }, retry.Context(ctx), RtyAtt, RtyDel, RtyErr); err != nil { - return false, err + return "", err } // update the client identifier // use index 0, the transaction only has one message if clientID, err = parseClientIDFromEvents(res.Events); err != nil { - return false, err + return "", err } src.PathEnd.ClientID = clientID @@ -240,7 +238,7 @@ func CreateClient( zap.String("dst_chain_id", dst.ChainID()), ) - return true, nil + return clientID, nil } // MsgUpdateClient queries for the current client state on dst, diff --git a/relayer/connection.go b/relayer/connection.go index 1882341dec..5ae3c2c7dc 100644 --- a/relayer/connection.go +++ b/relayer/connection.go @@ -20,19 +20,10 @@ func (c *Chain) CreateOpenConnections( memo string, initialBlockHistory uint64, pathName string, -) (modified bool, err error) { +) (string, string, error) { // client identifiers must be filled in - if err = ValidateClientPaths(c, dst); err != nil { - return modified, err - } - - srcpathChain := pathChain{ - provider: c.ChainProvider, - pathEnd: processor.NewPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, "", []processor.ChainChannelKey{}), - } - dstpathChain := pathChain{ - provider: dst.ChainProvider, - pathEnd: processor.NewPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, "", []processor.ChainChannelKey{}), + if err := ValidateClientPaths(c, dst); err != nil { + return "", "", err } // Timeout is per message. Four connection handshake messages, allowing maxRetries for each. @@ -43,16 +34,19 @@ func (c *Chain) CreateOpenConnections( pp := processor.NewPathProcessor( c.log, - srcpathChain.pathEnd, - dstpathChain.pathEnd, + processor.NewPathEnd(pathName, c.PathEnd.ChainID, c.PathEnd.ClientID, "", []processor.ChainChannelKey{}), + processor.NewPathEnd(pathName, dst.PathEnd.ChainID, dst.PathEnd.ClientID, "", []processor.ChainChannelKey{}), nil, memo, ) + var connectionSrc, connectionDst string + pp.OnConnectionMessage(dst.PathEnd.ChainID, conntypes.EventTypeConnectionOpenConfirm, func(ci provider.ConnectionInfo) { dst.PathEnd.ConnectionID = ci.ConnID c.PathEnd.ConnectionID = ci.CounterpartyConnID - modified = true + connectionSrc = ci.CounterpartyConnID + connectionDst = ci.ConnID }) c.log.Info("Starting event processor for connection handshake", @@ -62,10 +56,10 @@ func (c *Chain) CreateOpenConnections( zap.String("dst_client_id", dst.PathEnd.ClientID), ) - return modified, processor.NewEventProcessor(). + return connectionSrc, connectionDst, processor.NewEventProcessor(). WithChainProcessors( - srcpathChain.chainProcessor(c.log, nil), - dstpathChain.chainProcessor(c.log, nil), + c.chainProcessor(c.log, nil), + dst.chainProcessor(c.log, nil), ). WithPathProcessors(pp). WithInitialBlockHistory(initialBlockHistory). diff --git a/relayer/path.go b/relayer/path.go index 6c031db7c4..fb3558fb8d 100644 --- a/relayer/path.go +++ b/relayer/path.go @@ -6,15 +6,14 @@ import ( clienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types" conntypes "github.com/cosmos/ibc-go/v5/modules/core/03-connection/types" + "github.com/cosmos/relayer/v2/relayer/processor" "golang.org/x/sync/errgroup" "gopkg.in/yaml.v3" ) const ( - check = "✔" - xIcon = "✘" - allowList = "allowlist" - denyList = "denylist" + check = "✔" + xIcon = "✘" ) // Paths represent connection paths between chains @@ -95,6 +94,12 @@ type Path struct { Filter ChannelFilter `yaml:"src-channel-filter" json:"src-channel-filter"` } +// Named path wraps a Path with its name. +type NamedPath struct { + Name string + Path *Path +} + // ChannelFilter provides the means for either creating an allowlist or a denylist of channels on the src chain // which will be used to narrow down the list of channels a user wants to relay on. type ChannelFilter struct { @@ -136,9 +141,9 @@ type IBCdata struct { // ValidateChannelFilterRule verifies that the configured ChannelFilter rule is set to an appropriate value. func (p *Path) ValidateChannelFilterRule() error { - if p.Filter.Rule != allowList && p.Filter.Rule != denyList && p.Filter.Rule != "" { + if p.Filter.Rule != processor.RuleAllowList && p.Filter.Rule != processor.RuleDenyList && p.Filter.Rule != "" { return fmt.Errorf("%s is not a valid channel filter rule, please "+ - "ensure your channel filter rule is `%s` or '%s'", p.Filter.Rule, allowList, denyList) + "ensure your channel filter rule is `%s` or '%s'", p.Filter.Rule, processor.RuleAllowList, processor.RuleDenyList) } return nil } diff --git a/relayer/processor/metrics.go b/relayer/processor/metrics.go index 0e267cff12..f5f4245e77 100644 --- a/relayer/processor/metrics.go +++ b/relayer/processor/metrics.go @@ -6,6 +6,7 @@ import ( ) type PrometheusMetrics struct { + Registry *prometheus.Registry PacketObservedCounter *prometheus.CounterVec PacketRelayedCounter *prometheus.CounterVec LatestHeightGauge *prometheus.GaugeVec @@ -37,24 +38,27 @@ func NewPrometheusMetrics() *PrometheusMetrics { packetLabels := []string{"path", "chain", "channel", "port", "type"} heightLabels := []string{"chain"} walletLabels := []string{"chain", "key", "denom"} + registry := prometheus.NewRegistry() + registerer := promauto.With(registry) return &PrometheusMetrics{ - PacketObservedCounter: promauto.NewCounterVec(prometheus.CounterOpts{ + Registry: registry, + PacketObservedCounter: registerer.NewCounterVec(prometheus.CounterOpts{ Name: "cosmos_relayer_observed_packets", Help: "The total number of observed packets", }, packetLabels), - PacketRelayedCounter: promauto.NewCounterVec(prometheus.CounterOpts{ + PacketRelayedCounter: registerer.NewCounterVec(prometheus.CounterOpts{ Name: "cosmos_relayer_relayed_packets", Help: "The total number of relayed packets", }, packetLabels), - LatestHeightGauge: promauto.NewGaugeVec(prometheus.GaugeOpts{ + LatestHeightGauge: registerer.NewGaugeVec(prometheus.GaugeOpts{ Name: "cosmos_relayer_chain_latest_height", Help: "The current height of the chain", }, heightLabels), - WalletBalance: promauto.NewGaugeVec(prometheus.GaugeOpts{ + WalletBalance: registerer.NewGaugeVec(prometheus.GaugeOpts{ Name: "cosmos_relayer_wallet_balance", Help: "The current balance for the relayer's wallet", }, walletLabels), - FeesSpent: promauto.NewGaugeVec(prometheus.GaugeOpts{ + FeesSpent: registerer.NewGaugeVec(prometheus.GaugeOpts{ Name: "cosmos_relayer_fees_spent", Help: "The amount of fees spent from the relayer's wallet", }, walletLabels), diff --git a/relayer/processor/path_end_runtime.go b/relayer/processor/path_end_runtime.go index 0f187cdaa5..abd567bed4 100644 --- a/relayer/processor/path_end_runtime.go +++ b/relayer/processor/path_end_runtime.go @@ -89,13 +89,13 @@ func (pathEnd *pathEndRuntime) isRelevantChannel(channelID string) bool { // mergeMessageCache merges relevant IBC messages for packet flows, connection handshakes, and channel handshakes. // inSync indicates whether both involved ChainProcessors are in sync or not. When true, the observed packets // metrics will be counted so that observed vs relayed packets can be compared. -func (pathEnd *pathEndRuntime) mergeMessageCache(messageCache IBCMessagesCache, inSync bool) { +func (pathEnd *pathEndRuntime) mergeMessageCache(messageCache IBCMessagesCache, counterpartyChainID string, inSync bool) { packetMessages := make(ChannelPacketMessagesCache) connectionHandshakeMessages := make(ConnectionMessagesCache) channelHandshakeMessages := make(ChannelMessagesCache) for ch, pmc := range messageCache.PacketFlow { - if pathEnd.info.ShouldRelayChannel(ChainChannelKey{ChainID: pathEnd.info.ChainID, ChannelKey: ch}) { + if pathEnd.info.ShouldRelayChannel(ChainChannelKey{ChainID: pathEnd.info.ChainID, CounterpartyChainID: counterpartyChainID, ChannelKey: ch}) { if inSync && pathEnd.metrics != nil { for eventType, pCache := range pmc { pathEnd.metrics.AddPacketsObserved(pathEnd.info.PathName, pathEnd.info.ChainID, ch.ChannelID, ch.PortID, eventType, len(pCache)) @@ -271,7 +271,7 @@ func (pathEnd *pathEndRuntime) shouldTerminate(ibcMessagesCache IBCMessagesCache return false } -func (pathEnd *pathEndRuntime) mergeCacheData(ctx context.Context, cancel func(), d ChainProcessorCacheData, counterpartyInSync bool, messageLifecycle MessageLifecycle) { +func (pathEnd *pathEndRuntime) mergeCacheData(ctx context.Context, cancel func(), d ChainProcessorCacheData, counterpartyChainID string, counterpartyInSync bool, messageLifecycle MessageLifecycle) { pathEnd.inSync = d.InSync pathEnd.latestBlock = d.LatestBlock pathEnd.latestHeader = d.LatestHeader @@ -287,7 +287,7 @@ func (pathEnd *pathEndRuntime) mergeCacheData(ctx context.Context, cancel func() pathEnd.connectionStateCache = d.ConnectionStateCache // Update latest connection open state for chain pathEnd.channelStateCache = d.ChannelStateCache // Update latest channel open state for chain - pathEnd.mergeMessageCache(d.IBCMessagesCache, pathEnd.inSync && counterpartyInSync) // Merge incoming packet IBC messages into the backlog + pathEnd.mergeMessageCache(d.IBCMessagesCache, counterpartyChainID, pathEnd.inSync && counterpartyInSync) // Merge incoming packet IBC messages into the backlog pathEnd.ibcHeaderCache.Merge(d.IBCHeaderCache) // Update latest IBC header state pathEnd.ibcHeaderCache.Prune(ibcHeadersToCache) // Only keep most recent IBC headers diff --git a/relayer/processor/path_processor.go b/relayer/processor/path_processor.go index b05c0d2312..6b066b1b95 100644 --- a/relayer/processor/path_processor.go +++ b/relayer/processor/path_processor.go @@ -166,9 +166,9 @@ func (pp *PathProcessor) SetChainProviderIfApplicable(chainProvider provider.Cha func (pp *PathProcessor) IsRelayedChannel(chainID string, channelKey ChannelKey) bool { if pp.pathEnd1.info.ChainID == chainID { - return pp.pathEnd1.info.ShouldRelayChannel(ChainChannelKey{ChainID: chainID, ChannelKey: channelKey}) + return pp.pathEnd1.info.ShouldRelayChannel(ChainChannelKey{ChainID: chainID, CounterpartyChainID: pp.pathEnd2.info.ChainID, ChannelKey: channelKey}) } else if pp.pathEnd2.info.ChainID == chainID { - return pp.pathEnd2.info.ShouldRelayChannel(ChainChannelKey{ChainID: chainID, ChannelKey: channelKey}) + return pp.pathEnd2.info.ShouldRelayChannel(ChainChannelKey{ChainID: chainID, CounterpartyChainID: pp.pathEnd1.info.ChainID, ChannelKey: channelKey}) } return false } @@ -237,11 +237,11 @@ func (pp *PathProcessor) processAvailableSignals(ctx context.Context, cancel fun return true case d := <-pp.pathEnd1.incomingCacheData: // we have new data from ChainProcessor for pathEnd1 - pp.pathEnd1.mergeCacheData(ctx, cancel, d, pp.pathEnd2.inSync, messageLifecycle) + pp.pathEnd1.mergeCacheData(ctx, cancel, d, pp.pathEnd2.info.ChainID, pp.pathEnd2.inSync, messageLifecycle) case d := <-pp.pathEnd2.incomingCacheData: // we have new data from ChainProcessor for pathEnd2 - pp.pathEnd2.mergeCacheData(ctx, cancel, d, pp.pathEnd1.inSync, messageLifecycle) + pp.pathEnd2.mergeCacheData(ctx, cancel, d, pp.pathEnd1.info.ChainID, pp.pathEnd1.inSync, messageLifecycle) case <-pp.retryProcess: // No new data to merge in, just retry handling. diff --git a/relayer/processor/types.go b/relayer/processor/types.go index 92341f2947..c411a101c7 100644 --- a/relayer/processor/types.go +++ b/relayer/processor/types.go @@ -77,6 +77,19 @@ type IBCMessagesCache struct { ChannelHandshake ChannelMessagesCache } +// Clone makes a deep copy of an IBCMessagesCache. +func (c IBCMessagesCache) Clone() IBCMessagesCache { + x := IBCMessagesCache{ + PacketFlow: make(ChannelPacketMessagesCache, len(c.PacketFlow)), + ConnectionHandshake: make(ConnectionMessagesCache, len(c.ConnectionHandshake)), + ChannelHandshake: make(ChannelMessagesCache, len(c.ChannelHandshake)), + } + x.PacketFlow.Merge(c.PacketFlow) + x.ConnectionHandshake.Merge(c.ConnectionHandshake) + x.ChannelHandshake.Merge(c.ChannelHandshake) + return x +} + // NewIBCMessagesCache returns an empty IBCMessagesCache. func NewIBCMessagesCache() IBCMessagesCache { return IBCMessagesCache{ @@ -257,12 +270,10 @@ func (c PacketMessagesCache) DeleteMessages(toDelete ...map[string][]uint64) { // Merge merges another ChannelPacketMessagesCache into this one. func (c ChannelPacketMessagesCache) Merge(other ChannelPacketMessagesCache) { for channelKey, messageCache := range other { - _, ok := c[channelKey] - if !ok { - c[channelKey] = messageCache - } else { - c[channelKey].Merge(messageCache) + if _, ok := c[channelKey]; !ok { + c[channelKey] = make(PacketMessagesCache) } + c[channelKey].Merge(messageCache) } } @@ -304,12 +315,10 @@ func (c ChannelPacketMessagesCache) Retain(k ChannelKey, m string, pi provider.P // Merge merges another PacketMessagesCache into this one. func (c PacketMessagesCache) Merge(other PacketMessagesCache) { for ibcMessage, messageCache := range other { - _, ok := c[ibcMessage] - if !ok { - c[ibcMessage] = messageCache - } else { - c[ibcMessage].Merge(messageCache) + if _, ok := c[ibcMessage]; !ok { + c[ibcMessage] = make(PacketSequenceCache) } + c[ibcMessage].Merge(messageCache) } } @@ -323,12 +332,10 @@ func (c PacketSequenceCache) Merge(other PacketSequenceCache) { // Merge merges another ConnectionMessagesCache into this one. func (c ConnectionMessagesCache) Merge(other ConnectionMessagesCache) { for ibcMessage, messageCache := range other { - _, ok := c[ibcMessage] - if !ok { - c[ibcMessage] = messageCache - } else { - c[ibcMessage].Merge(messageCache) + if _, ok := c[ibcMessage]; !ok { + c[ibcMessage] = make(ConnectionMessageCache) } + c[ibcMessage].Merge(messageCache) } } @@ -360,12 +367,10 @@ func (c ConnectionMessageCache) Merge(other ConnectionMessageCache) { // Merge merges another ChannelMessagesCache into this one. func (c ChannelMessagesCache) Merge(other ChannelMessagesCache) { for ibcMessage, messageCache := range other { - _, ok := c[ibcMessage] - if !ok { - c[ibcMessage] = messageCache - } else { - c[ibcMessage].Merge(messageCache) + if _, ok := c[ibcMessage]; !ok { + c[ibcMessage] = make(ChannelMessageCache) } + c[ibcMessage].Merge(messageCache) } } @@ -397,6 +402,13 @@ func (c ChannelMessageCache) Merge(other ChannelMessageCache) { // IBCHeaderCache holds a mapping of IBCHeaders for their block height. type IBCHeaderCache map[uint64]provider.IBCHeader +// Clone makes a deep copy of an IBCHeaderCache. +func (c IBCHeaderCache) Clone() IBCHeaderCache { + x := make(IBCHeaderCache, len(c)) + x.Merge(c) + return x +} + // Merge merges another IBCHeaderCache into this one. func (c IBCHeaderCache) Merge(other IBCHeaderCache) { for k, v := range other { diff --git a/relayer/strategies.go b/relayer/strategies.go index 32fd7803f5..b49b0b98ce 100644 --- a/relayer/strategies.go +++ b/relayer/strategies.go @@ -12,7 +12,6 @@ import ( "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types" "github.com/cosmos/relayer/v2/relayer/chains/cosmos" "github.com/cosmos/relayer/v2/relayer/processor" - "github.com/cosmos/relayer/v2/relayer/provider" "go.uber.org/zap" ) @@ -31,42 +30,55 @@ const ( func StartRelayer( ctx context.Context, log *zap.Logger, - src, dst *Chain, - filter ChannelFilter, + chains map[string]*Chain, + paths []NamedPath, maxTxSize, maxMsgLength uint64, memo string, processorType string, initialBlockHistory uint64, - pathName string, metrics *processor.PrometheusMetrics, ) chan error { errorChan := make(chan error, 1) switch processorType { case ProcessorEvents: - var filterSrc, filterDst []processor.ChainChannelKey + chainProcessors := make([]processor.ChainProcessor, 0, len(chains)) - for _, ch := range filter.ChannelList { - ruleSrc := processor.ChainChannelKey{ChainID: src.ChainProvider.ChainId(), ChannelKey: processor.ChannelKey{ChannelID: ch}} - ruleDst := processor.ChainChannelKey{CounterpartyChainID: src.ChainProvider.ChainId(), ChannelKey: processor.ChannelKey{CounterpartyChannelID: ch}} - filterSrc = append(filterSrc, ruleSrc) - filterDst = append(filterDst, ruleDst) + for _, chain := range chains { + chainProcessors = append(chainProcessors, chain.chainProcessor(log, metrics)) } - paths := []path{{ - src: pathChain{ - provider: src.ChainProvider, - pathEnd: processor.NewPathEnd(pathName, src.ChainProvider.ChainId(), src.ClientID(), filter.Rule, filterSrc), - }, - dst: pathChain{ - provider: dst.ChainProvider, - pathEnd: processor.NewPathEnd(pathName, dst.ChainProvider.ChainId(), dst.ClientID(), filter.Rule, filterDst), - }, - }} - - go relayerStartEventProcessor(ctx, log, paths, initialBlockHistory, maxTxSize, maxMsgLength, memo, errorChan, metrics) + + ePaths := make([]path, len(paths)) + for i, np := range paths { + pathName := np.Name + p := np.Path + + filter := p.Filter + var filterSrc, filterDst []processor.ChainChannelKey + + for _, ch := range filter.ChannelList { + ruleSrc := processor.ChainChannelKey{ChainID: p.Src.ChainID, ChannelKey: processor.ChannelKey{ChannelID: ch}} + ruleDst := processor.ChainChannelKey{CounterpartyChainID: p.Src.ChainID, ChannelKey: processor.ChannelKey{CounterpartyChannelID: ch}} + filterSrc = append(filterSrc, ruleSrc) + filterDst = append(filterDst, ruleDst) + } + ePaths[i] = path{ + src: processor.NewPathEnd(pathName, p.Src.ChainID, p.Src.ClientID, filter.Rule, filterSrc), + dst: processor.NewPathEnd(pathName, p.Dst.ChainID, p.Dst.ClientID, filter.Rule, filterDst), + } + } + + go relayerStartEventProcessor(ctx, log, chainProcessors, ePaths, initialBlockHistory, maxTxSize, maxMsgLength, memo, errorChan, metrics) return errorChan case ProcessorLegacy: - go relayerMainLoop(ctx, log, src, dst, filter, maxTxSize, maxMsgLength, memo, errorChan) + if len(paths) != 1 { + panic(errors.New("only one path supported for legacy processor")) + } + p := paths[0].Path + src, dst := chains[p.Src.ChainID], chains[p.Dst.ChainID] + src.PathEnd = p.Src + dst.PathEnd = p.Dst + go relayerStartLegacy(ctx, log, src, dst, p.Filter, maxTxSize, maxMsgLength, memo, errorChan) return errorChan default: panic(fmt.Errorf("unexpected processor type: %s, supports one of: [%s, %s]", processorType, ProcessorEvents, ProcessorLegacy)) @@ -76,23 +88,18 @@ func StartRelayer( // TODO: intermediate types. Should combine/replace with the relayer.Chain, relayer.Path, and relayer.PathEnd structs // as the stateless and stateful/event-based relaying mechanisms are consolidated. type path struct { - src pathChain - dst pathChain -} - -type pathChain struct { - provider provider.ChainProvider - pathEnd processor.PathEnd + src processor.PathEnd + dst processor.PathEnd } // chainProcessor returns the corresponding ChainProcessor implementation instance for a pathChain. -func (chain pathChain) chainProcessor(log *zap.Logger, metrics *processor.PrometheusMetrics) processor.ChainProcessor { +func (chain *Chain) chainProcessor(log *zap.Logger, metrics *processor.PrometheusMetrics) processor.ChainProcessor { // Handle new ChainProcessor implementations as cases here - switch p := chain.provider.(type) { + switch p := chain.ChainProvider.(type) { case *cosmos.CosmosProvider: return cosmos.NewCosmosChainProcessor(log, p, metrics) default: - panic(fmt.Errorf("unsupported chain provider type: %T", chain.provider)) + panic(fmt.Errorf("unsupported chain provider type: %T", chain.ChainProvider)) } } @@ -100,6 +107,7 @@ func (chain pathChain) chainProcessor(log *zap.Logger, metrics *processor.Promet func relayerStartEventProcessor( ctx context.Context, log *zap.Logger, + chainProcessors []processor.ChainProcessor, paths []path, initialBlockHistory uint64, maxTxSize, @@ -110,18 +118,14 @@ func relayerStartEventProcessor( ) { defer close(errCh) - epb := processor.NewEventProcessor() + epb := processor.NewEventProcessor().WithChainProcessors(chainProcessors...) for _, p := range paths { epb = epb. - WithChainProcessors( - p.src.chainProcessor(log, metrics), - p.dst.chainProcessor(log, metrics), - ). WithPathProcessors(processor.NewPathProcessor( log, - p.src.pathEnd, - p.dst.pathEnd, + p.src, + p.dst, metrics, memo, )) @@ -134,8 +138,8 @@ func relayerStartEventProcessor( errCh <- ep.Run(ctx) } -// relayerMainLoop is the main loop of the relayer. -func relayerMainLoop(ctx context.Context, log *zap.Logger, src, dst *Chain, filter ChannelFilter, maxTxSize, maxMsgLength uint64, memo string, errCh chan<- error) { +// relayerStartLegacy is the main loop of the relayer. +func relayerStartLegacy(ctx context.Context, log *zap.Logger, src, dst *Chain, filter ChannelFilter, maxTxSize, maxMsgLength uint64, memo string, errCh chan<- error) { defer close(errCh) // Query the list of channels on the src connection. @@ -282,7 +286,7 @@ func filterOpenChannels(channels []*types.IdentifiedChannel) map[string]*ActiveC // channels to relay on. func applyChannelFilterRule(filter ChannelFilter, channels []*types.IdentifiedChannel) []*types.IdentifiedChannel { switch filter.Rule { - case allowList: + case processor.RuleAllowList: var filteredChans []*types.IdentifiedChannel for _, c := range channels { if filter.InChannelList(c.ChannelId) { @@ -290,7 +294,7 @@ func applyChannelFilterRule(filter ChannelFilter, channels []*types.IdentifiedCh } } return filteredChans - case denyList: + case processor.RuleDenyList: var filteredChans []*types.IdentifiedChannel for _, c := range channels { if filter.InChannelList(c.ChannelId) {