From 6e8347d78eefa2b1ddf9651a3f8f01eed1e4b0f2 Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Mon, 4 Sep 2023 13:04:17 -0600 Subject: [PATCH 1/8] Create utils dir --- utils/configUtil.go | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 utils/configUtil.go diff --git a/utils/configUtil.go b/utils/configUtil.go new file mode 100644 index 000000000..d30aa296b --- /dev/null +++ b/utils/configUtil.go @@ -0,0 +1,46 @@ +package utils + +import ( + "fmt" + "os" + + "gopkg.in/yaml.v2" +) + +func UpdateConfig(filePath string, pathKeys []string, newValue interface{}) error { + content, err := os.ReadFile(filePath) + if err != nil { + return err + } + + var data map[string]interface{} + err = yaml.Unmarshal(content, &data) + if err != nil { + return err + } + + currentMap := data + for i, key := range pathKeys { + if i == len(pathKeys)-1 { + currentMap[key] = newValue + } else { + nextMap, ok := currentMap[key].(map[string]interface{}) + if !ok { + return fmt.Errorf("%s does not lead to a nested map", key) + } + currentMap = nextMap + } + } + + updatedContent, err := yaml.Marshal(data) + if err != nil { + return err + } + + err = os.WriteFile(filePath, updatedContent, 0644) + if err != nil { + return err + } + + return nil +} From 513637c66a240c694212627dafdc36f4ec0cab95 Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Mon, 4 Sep 2023 15:44:59 -0600 Subject: [PATCH 2/8] Add use subcommand for rly keys --- cmd/config.go | 4 ++-- cmd/keys.go | 33 ++++++++++++++++++++++++++ relayer/chains/cosmos/keys.go | 21 ++++++++++++++++- relayer/chains/penumbra/keys.go | 6 +++++ relayer/provider/provider.go | 1 + utils/configUtil.go | 42 ++++++++++++++++++++++++++++----- 6 files changed, 98 insertions(+), 9 deletions(-) diff --git a/cmd/config.go b/cmd/config.go index 9888a4596..80ae95e4c 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -395,8 +395,8 @@ func UnmarshalJSONProviderConfig(data []byte, customTypes map[string]reflect.Typ } typeName, ok := m["type"].(string) - if !ok { - return nil, errors.New("cannot find type"); + if !ok { + return nil, errors.New("cannot find type") } var provCfg provider.ProviderConfig diff --git a/cmd/keys.go b/cmd/keys.go index 0ddd447d4..8d858368d 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -45,6 +45,7 @@ func keysCmd(a *appState) *cobra.Command { cmd.AddCommand( keysAddCmd(a), + keysUseCmd(a), keysRestoreCmd(a), keysDeleteCmd(a), keysListCmd(a), @@ -55,6 +56,38 @@ func keysCmd(a *appState) *cobra.Command { return cmd } +func keysUseCmd(a *appState) *cobra.Command { + + cmd := &cobra.Command{ + Use: "use chain_name key_name", + Aliases: []string{"a"}, + Short: "Use a key from the keychain associated with a particular chain. Look at ~/.relayer/keys/ibc-0/keyring-test ", + Args: withUsage(cobra.ExactArgs(2)), + Example: strings.TrimSpace(fmt.Sprintf(` +$ %s keys use ibc-0 key_name`, appName)), + RunE: func(cmd *cobra.Command, args []string) error { + chain, ok := a.config.Chains[args[0]] + if !ok { + return errChainNotFound(args[0]) + } + + chainName := args[0] + if chain.ChainProvider.KeyExists(chainName) { + return errKeyExists(chainName) + } + + key := args[1] + chain, exists := a.config.Chains[chainName] + if !exists { + return fmt.Errorf("chain %s not found in config", chainName) + } + + return chain.ChainProvider.UseKey(key, a.configPath()) + }, + } + return cmd +} + // keysAddCmd respresents the `keys add` command func keysAddCmd(a *appState) *cobra.Command { cmd := &cobra.Command{ diff --git a/relayer/chains/cosmos/keys.go b/relayer/chains/cosmos/keys.go index 858f77505..f58870cc7 100644 --- a/relayer/chains/cosmos/keys.go +++ b/relayer/chains/cosmos/keys.go @@ -2,8 +2,12 @@ package cosmos import ( "errors" + "fmt" "os" + "github.com/cosmos/relayer/v2/relayer/provider" + "github.com/cosmos/relayer/v2/utils" + ckeys "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -12,7 +16,6 @@ import ( "github.com/cosmos/relayer/v2/relayer/chains/cosmos/keys/sr25519" "github.com/cosmos/relayer/v2/relayer/codecs/ethermint" "github.com/cosmos/relayer/v2/relayer/codecs/injective" - "github.com/cosmos/relayer/v2/relayer/provider" ) const ethereumCoinType = uint32(60) @@ -69,6 +72,22 @@ func (cc *CosmosProvider) AddKey(name string, coinType uint32, signingAlgorithm return ko, nil } +func (cc *CosmosProvider) UseKey(key, configPath string) error { + info, err := cc.ListAddresses() + if err != nil { + return err + } + value, exists := info[key] + + if exists { + fmt.Printf("Using %s -> %s for %s", key, value, cc.ChainName()) + } else { + return fmt.Errorf("key %s does not exist for chain %s", key, cc.ChainName()) + } + + return utils.UpdateConfig(configPath, []string{utils.Chains, cc.ChainName(), utils.Value, utils.Key}, key) +} + // RestoreKey converts a mnemonic to a private key and BIP-39 HD Path and persists it to the keystore. // It fails if there is an existing key with the same address. func (cc *CosmosProvider) RestoreKey(name, mnemonic string, coinType uint32, signingAlgorithm string) (address string, err error) { diff --git a/relayer/chains/penumbra/keys.go b/relayer/chains/penumbra/keys.go index aa09fa7b1..f4f0653ec 100644 --- a/relayer/chains/penumbra/keys.go +++ b/relayer/chains/penumbra/keys.go @@ -66,6 +66,12 @@ func (cc *PenumbraProvider) AddKey(name string, coinType uint32, signingAlgorith return ko, nil } +// UseKey generates a new mnemonic which is then converted to a private key and BIP-39 HD Path and persists it to the keystore. +// It fails if there is an existing key with the same address. +func (cc *PenumbraProvider) UseKey(name, configPath string) error { + return nil +} + // RestoreKey converts a mnemonic to a private key and BIP-39 HD Path and persists it to the keystore. // It fails if there is an existing key with the same address. func (cc *PenumbraProvider) RestoreKey(name, mnemonic string, coinType uint32, signingAlgorithm string) (address string, err error) { diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 34cee434d..680feab52 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -216,6 +216,7 @@ type KeyProvider interface { CreateKeystore(path string) error KeystoreCreated(path string) bool AddKey(name string, coinType uint32, signingAlgorithm string) (output *KeyOutput, err error) + UseKey(name, configPath string) error RestoreKey(name, mnemonic string, coinType uint32, signingAlgorithm string) (address string, err error) ShowAddress(name string) (address string, err error) ListAddresses() (map[string]string, error) diff --git a/utils/configUtil.go b/utils/configUtil.go index d30aa296b..9d31eb2cc 100644 --- a/utils/configUtil.go +++ b/utils/configUtil.go @@ -7,24 +7,54 @@ import ( "gopkg.in/yaml.v2" ) -func UpdateConfig(filePath string, pathKeys []string, newValue interface{}) error { - content, err := os.ReadFile(filePath) +const ( + //Add more consts when configUtil is used for other updates + Chains = "chains" + Value = "value" + Key = "key" +) + +// convertMap recursively converts map[interface{}]interface{} to map[string]interface{} +func convertMap(input map[interface{}]interface{}) map[string]interface{} { + result := make(map[string]interface{}) + for key, value := range input { + strKey, ok := key.(string) + if !ok { + continue + } + if nestedMap, ok := value.(map[interface{}]interface{}); ok { + result[strKey] = convertMap(nestedMap) + } else { + result[strKey] = value + } + } + return result +} + +func UpdateConfig(configPath string, pathKeys []string, newValue interface{}) error { + content, err := os.ReadFile(configPath) if err != nil { return err } - var data map[string]interface{} - err = yaml.Unmarshal(content, &data) + var rawData map[interface{}]interface{} + err = yaml.Unmarshal(content, &rawData) if err != nil { return err } + data := convertMap(rawData) currentMap := data for i, key := range pathKeys { + value, exists := currentMap[key] + if !exists { + return fmt.Errorf("key %s does not exist", key) + } + if i == len(pathKeys)-1 { currentMap[key] = newValue } else { - nextMap, ok := currentMap[key].(map[string]interface{}) + nextMap, ok := value.(map[string]interface{}) if !ok { return fmt.Errorf("%s does not lead to a nested map", key) } @@ -37,7 +67,7 @@ func UpdateConfig(filePath string, pathKeys []string, newValue interface{}) erro return err } - err = os.WriteFile(filePath, updatedContent, 0644) + err = os.WriteFile(configPath, updatedContent, 0644) if err != nil { return err } From 2354db22e849acd448f5b6264a48ed5f9be84fc6 Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Mon, 4 Sep 2023 16:47:31 -0600 Subject: [PATCH 3/8] Optimization to ensure key exists & is not the same as being used currently --- cmd/keys.go | 10 +-------- relayer/chains/cosmos/keys.go | 16 ++++++++++++-- utils/configUtil.go | 39 ++++++++++++++++++++++++++++++++--- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/cmd/keys.go b/cmd/keys.go index 8d858368d..e9dce4076 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -66,17 +66,9 @@ func keysUseCmd(a *appState) *cobra.Command { Example: strings.TrimSpace(fmt.Sprintf(` $ %s keys use ibc-0 key_name`, appName)), RunE: func(cmd *cobra.Command, args []string) error { - chain, ok := a.config.Chains[args[0]] - if !ok { - return errChainNotFound(args[0]) - } - chainName := args[0] - if chain.ChainProvider.KeyExists(chainName) { - return errKeyExists(chainName) - } - key := args[1] + chain, exists := a.config.Chains[chainName] if !exists { return fmt.Errorf("chain %s not found in config", chainName) diff --git a/relayer/chains/cosmos/keys.go b/relayer/chains/cosmos/keys.go index f58870cc7..fc55b2d95 100644 --- a/relayer/chains/cosmos/keys.go +++ b/relayer/chains/cosmos/keys.go @@ -79,13 +79,25 @@ func (cc *CosmosProvider) UseKey(key, configPath string) error { } value, exists := info[key] + mappath := []string{utils.Chains, cc.ChainName(), utils.Value, utils.Key} + + currentValue, success := utils.GetValueFromPath(configPath, mappath) + + if !success { + return fmt.Errorf("unable to get value from path %s", mappath) + } + + if currentValue == key { + return fmt.Errorf("config is already using %s -> %s for %s", key, value, cc.ChainName()) + } + if exists { - fmt.Printf("Using %s -> %s for %s", key, value, cc.ChainName()) + fmt.Printf("Config will now use %s -> %s for %s", key, value, cc.ChainName()) } else { return fmt.Errorf("key %s does not exist for chain %s", key, cc.ChainName()) } - return utils.UpdateConfig(configPath, []string{utils.Chains, cc.ChainName(), utils.Value, utils.Key}, key) + return utils.UpdateConfig(configPath, mappath, key) } // RestoreKey converts a mnemonic to a private key and BIP-39 HD Path and persists it to the keystore. diff --git a/utils/configUtil.go b/utils/configUtil.go index 9d31eb2cc..3edfdab7b 100644 --- a/utils/configUtil.go +++ b/utils/configUtil.go @@ -31,20 +31,53 @@ func convertMap(input map[interface{}]interface{}) map[string]interface{} { return result } -func UpdateConfig(configPath string, pathKeys []string, newValue interface{}) error { +func ReadConfig(configPath string) (map[string]interface{}, error) { content, err := os.ReadFile(configPath) if err != nil { - return err + return nil, err } var rawData map[interface{}]interface{} err = yaml.Unmarshal(content, &rawData) + if err != nil { + return nil, err + } + return convertMap(rawData), nil +} + +func GetValueFromPath(configPath string, path []string) (interface{}, bool) { + data, err := ReadConfig(configPath) + if err != nil { + return nil, false + } + + current := interface{}(data) + for _, key := range path { + // Ensure the current value is a map + asMap, ok := current.(map[string]interface{}) + if !ok { + return nil, false + } + + // Get the next value from the map + current, ok = asMap[key] + if !ok { + return nil, false + } + } + + return current, true +} + +func UpdateConfig(configPath string, pathKeys []string, newValue interface{}) error { + + data, err := ReadConfig(configPath) if err != nil { return err } - data := convertMap(rawData) currentMap := data + for i, key := range pathKeys { value, exists := currentMap[key] if !exists { From a3d90880bf7ac037fde3759f8037817d092a6b0b Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Mon, 4 Sep 2023 18:02:00 -0600 Subject: [PATCH 4/8] Optimize to move some logic into cmd/keys.go instead of duplicating in chains/_/keys.go --- cmd/keys.go | 29 ++++++++++++++++++++++++++++- relayer/chains/cosmos/keys.go | 32 +++++--------------------------- relayer/chains/penumbra/keys.go | 10 ++++++---- relayer/provider/provider.go | 2 +- 4 files changed, 40 insertions(+), 33 deletions(-) diff --git a/cmd/keys.go b/cmd/keys.go index e9dce4076..6e032cebf 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -25,6 +25,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/hd" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/relayer/v2/relayer/chains/cosmos" + "github.com/cosmos/relayer/v2/utils" "github.com/spf13/cobra" "go.uber.org/zap" ) @@ -74,7 +75,33 @@ $ %s keys use ibc-0 key_name`, appName)), return fmt.Errorf("chain %s not found in config", chainName) } - return chain.ChainProvider.UseKey(key, a.configPath()) + cc := chain.ChainProvider + + info, err := cc.ListAddresses() + if err != nil { + return err + } + value, exists := info[key] + + kvpath := []string{utils.Chains, cc.ChainName(), utils.Value, utils.Key} + + currentValue, success := utils.GetValueFromPath(a.configPath(), kvpath) + + if !success { + return fmt.Errorf("unable to get value from path %s", kvpath) + } + + if currentValue == key { + return fmt.Errorf("config is already using %s -> %s for %s", key, value, cc.ChainName()) + } + + if exists { + fmt.Printf("Config will now use %s -> %s for %s\n", key, value, cc.ChainName()) + } else { + return fmt.Errorf("key %s does not exist for chain %s", key, cc.ChainName()) + } + + return chain.ChainProvider.UseKey(a.configPath(), kvpath, key) }, } return cmd diff --git a/relayer/chains/cosmos/keys.go b/relayer/chains/cosmos/keys.go index fc55b2d95..c7b183a36 100644 --- a/relayer/chains/cosmos/keys.go +++ b/relayer/chains/cosmos/keys.go @@ -2,7 +2,6 @@ package cosmos import ( "errors" - "fmt" "os" "github.com/cosmos/relayer/v2/relayer/provider" @@ -72,32 +71,11 @@ func (cc *CosmosProvider) AddKey(name string, coinType uint32, signingAlgorithm return ko, nil } -func (cc *CosmosProvider) UseKey(key, configPath string) error { - info, err := cc.ListAddresses() - if err != nil { - return err - } - value, exists := info[key] - - mappath := []string{utils.Chains, cc.ChainName(), utils.Value, utils.Key} - - currentValue, success := utils.GetValueFromPath(configPath, mappath) - - if !success { - return fmt.Errorf("unable to get value from path %s", mappath) - } - - if currentValue == key { - return fmt.Errorf("config is already using %s -> %s for %s", key, value, cc.ChainName()) - } - - if exists { - fmt.Printf("Config will now use %s -> %s for %s", key, value, cc.ChainName()) - } else { - return fmt.Errorf("key %s does not exist for chain %s", key, cc.ChainName()) - } - - return utils.UpdateConfig(configPath, mappath, key) +// Updates config.yaml chain with the specified key. +// It fails if config.yaml is already using the same key or if the key does not exist +// Note , this is not a runtime update cmd. +func (cc *CosmosProvider) UseKey(configPath string, kvpath []string, key string) error { + return utils.UpdateConfig(configPath, kvpath, key) } // RestoreKey converts a mnemonic to a private key and BIP-39 HD Path and persists it to the keystore. diff --git a/relayer/chains/penumbra/keys.go b/relayer/chains/penumbra/keys.go index f4f0653ec..887965c7c 100644 --- a/relayer/chains/penumbra/keys.go +++ b/relayer/chains/penumbra/keys.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/relayer/v2/relayer/codecs/ethermint" "github.com/cosmos/relayer/v2/relayer/codecs/injective" "github.com/cosmos/relayer/v2/relayer/provider" + "github.com/cosmos/relayer/v2/utils" ) const ethereumCoinType = uint32(60) @@ -66,10 +67,11 @@ func (cc *PenumbraProvider) AddKey(name string, coinType uint32, signingAlgorith return ko, nil } -// UseKey generates a new mnemonic which is then converted to a private key and BIP-39 HD Path and persists it to the keystore. -// It fails if there is an existing key with the same address. -func (cc *PenumbraProvider) UseKey(name, configPath string) error { - return nil +// Updates config.yaml chain with the specified key. +// It fails if config.yaml is already using the same key or if the key does not exist +// Note , this is not a runtime update cmd. +func (cc *PenumbraProvider) UseKey(configPath string, kvpath []string, key string) error { + return utils.UpdateConfig(configPath, kvpath, key) } // RestoreKey converts a mnemonic to a private key and BIP-39 HD Path and persists it to the keystore. diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 680feab52..bcc77502e 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -216,7 +216,7 @@ type KeyProvider interface { CreateKeystore(path string) error KeystoreCreated(path string) bool AddKey(name string, coinType uint32, signingAlgorithm string) (output *KeyOutput, err error) - UseKey(name, configPath string) error + UseKey(configPath string, kvpath []string, key string) error RestoreKey(name, mnemonic string, coinType uint32, signingAlgorithm string) (address string, err error) ShowAddress(name string) (address string, err error) ListAddresses() (map[string]string, error) From ae6a78fb13f0eb8d678590b9a40c20e6e2082b0d Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Mon, 4 Sep 2023 19:07:15 -0600 Subject: [PATCH 5/8] Cleanup --- utils/configUtil.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/utils/configUtil.go b/utils/configUtil.go index 3edfdab7b..83689c6b5 100644 --- a/utils/configUtil.go +++ b/utils/configUtil.go @@ -7,14 +7,14 @@ import ( "gopkg.in/yaml.v2" ) +// Constants used in the config utility.Add more as required. const ( - //Add more consts when configUtil is used for other updates Chains = "chains" Value = "value" Key = "key" ) -// convertMap recursively converts map[interface{}]interface{} to map[string]interface{} +// convertMap recursively converts map[interface{}]interface{} to map[string]interface{}. func convertMap(input map[interface{}]interface{}) map[string]interface{} { result := make(map[string]interface{}) for key, value := range input { @@ -31,20 +31,22 @@ func convertMap(input map[interface{}]interface{}) map[string]interface{} { return result } +// ReadConfig reads and parses a YAML configuration file. func ReadConfig(configPath string) (map[string]interface{}, error) { content, err := os.ReadFile(configPath) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to read config file: %w", err) } var rawData map[interface{}]interface{} err = yaml.Unmarshal(content, &rawData) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to unmarshal YAML: %w", err) } return convertMap(rawData), nil } +// GetValueFromPath retrieves a value from the configuration using a given path. func GetValueFromPath(configPath string, path []string) (interface{}, bool) { data, err := ReadConfig(configPath) if err != nil { @@ -53,13 +55,11 @@ func GetValueFromPath(configPath string, path []string) (interface{}, bool) { current := interface{}(data) for _, key := range path { - // Ensure the current value is a map asMap, ok := current.(map[string]interface{}) if !ok { return nil, false } - // Get the next value from the map current, ok = asMap[key] if !ok { return nil, false @@ -69,15 +69,14 @@ func GetValueFromPath(configPath string, path []string) (interface{}, bool) { return current, true } +// UpdateConfig updates a value in the configuration using a given path. func UpdateConfig(configPath string, pathKeys []string, newValue interface{}) error { - data, err := ReadConfig(configPath) if err != nil { return err } currentMap := data - for i, key := range pathKeys { value, exists := currentMap[key] if !exists { @@ -97,12 +96,12 @@ func UpdateConfig(configPath string, pathKeys []string, newValue interface{}) er updatedContent, err := yaml.Marshal(data) if err != nil { - return err + return fmt.Errorf("failed to marshal updated data: %w", err) } err = os.WriteFile(configPath, updatedContent, 0644) if err != nil { - return err + return fmt.Errorf("failed to write updated config: %w", err) } return nil From a402a77a758b312e9612330983023f8cae614af9 Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Tue, 5 Sep 2023 22:39:42 -0600 Subject: [PATCH 6/8] remove redundant utils package.Use appState instead --- cmd/appstate.go | 31 +++++++++ cmd/keys.go | 37 +---------- relayer/chains/cosmos/keys.go | 6 +- relayer/chains/penumbra/keys.go | 6 +- relayer/provider/provider.go | 2 +- utils/configUtil.go | 108 -------------------------------- 6 files changed, 39 insertions(+), 151 deletions(-) delete mode 100644 utils/configUtil.go diff --git a/cmd/appstate.go b/cmd/appstate.go index d6378bb8a..5017df85e 100644 --- a/cmd/appstate.go +++ b/cmd/appstate.go @@ -251,3 +251,34 @@ func (a *appState) updatePathConfig( return nil }) } + +func (a *appState) useKey(chainName, key string) error { + + chain, exists := a.config.Chains[chainName] + if !exists { + return fmt.Errorf("chain %s not found in config", chainName) + } + + cc := chain.ChainProvider + + info, err := cc.ListAddresses() + if err != nil { + return err + } + value, exists := info[key] + currentValue := a.config.Chains[chainName].ChainProvider.Key() + + if currentValue == key { + return fmt.Errorf("config is already using %s -> %s for %s", key, value, cc.ChainName()) + } + + if exists { + fmt.Printf("Config will now use %s -> %s for %s\n", key, value, cc.ChainName()) + } else { + return fmt.Errorf("key %s does not exist for chain %s", key, cc.ChainName()) + } + return a.performConfigLockingOperation(context.Background(), func() error { + a.config.Chains[chainName].ChainProvider.UseKey(key) + return nil + }) +} diff --git a/cmd/keys.go b/cmd/keys.go index 6e032cebf..fb09cf46f 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -25,7 +25,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/hd" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/relayer/v2/relayer/chains/cosmos" - "github.com/cosmos/relayer/v2/utils" "github.com/spf13/cobra" "go.uber.org/zap" ) @@ -67,41 +66,7 @@ func keysUseCmd(a *appState) *cobra.Command { Example: strings.TrimSpace(fmt.Sprintf(` $ %s keys use ibc-0 key_name`, appName)), RunE: func(cmd *cobra.Command, args []string) error { - chainName := args[0] - key := args[1] - - chain, exists := a.config.Chains[chainName] - if !exists { - return fmt.Errorf("chain %s not found in config", chainName) - } - - cc := chain.ChainProvider - - info, err := cc.ListAddresses() - if err != nil { - return err - } - value, exists := info[key] - - kvpath := []string{utils.Chains, cc.ChainName(), utils.Value, utils.Key} - - currentValue, success := utils.GetValueFromPath(a.configPath(), kvpath) - - if !success { - return fmt.Errorf("unable to get value from path %s", kvpath) - } - - if currentValue == key { - return fmt.Errorf("config is already using %s -> %s for %s", key, value, cc.ChainName()) - } - - if exists { - fmt.Printf("Config will now use %s -> %s for %s\n", key, value, cc.ChainName()) - } else { - return fmt.Errorf("key %s does not exist for chain %s", key, cc.ChainName()) - } - - return chain.ChainProvider.UseKey(a.configPath(), kvpath, key) + return a.useKey(args[0], args[1]) }, } return cmd diff --git a/relayer/chains/cosmos/keys.go b/relayer/chains/cosmos/keys.go index c7b183a36..e3a0fddaf 100644 --- a/relayer/chains/cosmos/keys.go +++ b/relayer/chains/cosmos/keys.go @@ -5,7 +5,6 @@ import ( "os" "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/cosmos/relayer/v2/utils" ckeys "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/crypto/hd" @@ -74,8 +73,9 @@ func (cc *CosmosProvider) AddKey(name string, coinType uint32, signingAlgorithm // Updates config.yaml chain with the specified key. // It fails if config.yaml is already using the same key or if the key does not exist // Note , this is not a runtime update cmd. -func (cc *CosmosProvider) UseKey(configPath string, kvpath []string, key string) error { - return utils.UpdateConfig(configPath, kvpath, key) +func (cc *CosmosProvider) UseKey(key string) error { + cc.PCfg.Key = key + return nil } // RestoreKey converts a mnemonic to a private key and BIP-39 HD Path and persists it to the keystore. diff --git a/relayer/chains/penumbra/keys.go b/relayer/chains/penumbra/keys.go index 887965c7c..1a22ef436 100644 --- a/relayer/chains/penumbra/keys.go +++ b/relayer/chains/penumbra/keys.go @@ -12,7 +12,6 @@ import ( "github.com/cosmos/relayer/v2/relayer/codecs/ethermint" "github.com/cosmos/relayer/v2/relayer/codecs/injective" "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/cosmos/relayer/v2/utils" ) const ethereumCoinType = uint32(60) @@ -70,8 +69,9 @@ func (cc *PenumbraProvider) AddKey(name string, coinType uint32, signingAlgorith // Updates config.yaml chain with the specified key. // It fails if config.yaml is already using the same key or if the key does not exist // Note , this is not a runtime update cmd. -func (cc *PenumbraProvider) UseKey(configPath string, kvpath []string, key string) error { - return utils.UpdateConfig(configPath, kvpath, key) +func (cc *PenumbraProvider) UseKey(key string) error { + cc.PCfg.Key = key + return nil } // RestoreKey converts a mnemonic to a private key and BIP-39 HD Path and persists it to the keystore. diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index bcc77502e..2bce8c2c4 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -216,7 +216,7 @@ type KeyProvider interface { CreateKeystore(path string) error KeystoreCreated(path string) bool AddKey(name string, coinType uint32, signingAlgorithm string) (output *KeyOutput, err error) - UseKey(configPath string, kvpath []string, key string) error + UseKey(key string) error RestoreKey(name, mnemonic string, coinType uint32, signingAlgorithm string) (address string, err error) ShowAddress(name string) (address string, err error) ListAddresses() (map[string]string, error) diff --git a/utils/configUtil.go b/utils/configUtil.go deleted file mode 100644 index 83689c6b5..000000000 --- a/utils/configUtil.go +++ /dev/null @@ -1,108 +0,0 @@ -package utils - -import ( - "fmt" - "os" - - "gopkg.in/yaml.v2" -) - -// Constants used in the config utility.Add more as required. -const ( - Chains = "chains" - Value = "value" - Key = "key" -) - -// convertMap recursively converts map[interface{}]interface{} to map[string]interface{}. -func convertMap(input map[interface{}]interface{}) map[string]interface{} { - result := make(map[string]interface{}) - for key, value := range input { - strKey, ok := key.(string) - if !ok { - continue - } - if nestedMap, ok := value.(map[interface{}]interface{}); ok { - result[strKey] = convertMap(nestedMap) - } else { - result[strKey] = value - } - } - return result -} - -// ReadConfig reads and parses a YAML configuration file. -func ReadConfig(configPath string) (map[string]interface{}, error) { - content, err := os.ReadFile(configPath) - if err != nil { - return nil, fmt.Errorf("failed to read config file: %w", err) - } - - var rawData map[interface{}]interface{} - err = yaml.Unmarshal(content, &rawData) - if err != nil { - return nil, fmt.Errorf("failed to unmarshal YAML: %w", err) - } - return convertMap(rawData), nil -} - -// GetValueFromPath retrieves a value from the configuration using a given path. -func GetValueFromPath(configPath string, path []string) (interface{}, bool) { - data, err := ReadConfig(configPath) - if err != nil { - return nil, false - } - - current := interface{}(data) - for _, key := range path { - asMap, ok := current.(map[string]interface{}) - if !ok { - return nil, false - } - - current, ok = asMap[key] - if !ok { - return nil, false - } - } - - return current, true -} - -// UpdateConfig updates a value in the configuration using a given path. -func UpdateConfig(configPath string, pathKeys []string, newValue interface{}) error { - data, err := ReadConfig(configPath) - if err != nil { - return err - } - - currentMap := data - for i, key := range pathKeys { - value, exists := currentMap[key] - if !exists { - return fmt.Errorf("key %s does not exist", key) - } - - if i == len(pathKeys)-1 { - currentMap[key] = newValue - } else { - nextMap, ok := value.(map[string]interface{}) - if !ok { - return fmt.Errorf("%s does not lead to a nested map", key) - } - currentMap = nextMap - } - } - - updatedContent, err := yaml.Marshal(data) - if err != nil { - return fmt.Errorf("failed to marshal updated data: %w", err) - } - - err = os.WriteFile(configPath, updatedContent, 0644) - if err != nil { - return fmt.Errorf("failed to write updated config: %w", err) - } - - return nil -} From ae7f3b9578c22b21125eee2726a533f8ddbe8f87 Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Tue, 5 Sep 2023 23:20:53 -0600 Subject: [PATCH 7/8] Update comments to reflect realilty --- relayer/chains/cosmos/keys.go | 3 +-- relayer/chains/penumbra/keys.go | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/relayer/chains/cosmos/keys.go b/relayer/chains/cosmos/keys.go index e3a0fddaf..ce6c2a2ef 100644 --- a/relayer/chains/cosmos/keys.go +++ b/relayer/chains/cosmos/keys.go @@ -71,8 +71,7 @@ func (cc *CosmosProvider) AddKey(name string, coinType uint32, signingAlgorithm } // Updates config.yaml chain with the specified key. -// It fails if config.yaml is already using the same key or if the key does not exist -// Note , this is not a runtime update cmd. +// It fails config is already using the same key or if the key does not exist func (cc *CosmosProvider) UseKey(key string) error { cc.PCfg.Key = key return nil diff --git a/relayer/chains/penumbra/keys.go b/relayer/chains/penumbra/keys.go index 1a22ef436..0c6131fda 100644 --- a/relayer/chains/penumbra/keys.go +++ b/relayer/chains/penumbra/keys.go @@ -67,8 +67,7 @@ func (cc *PenumbraProvider) AddKey(name string, coinType uint32, signingAlgorith } // Updates config.yaml chain with the specified key. -// It fails if config.yaml is already using the same key or if the key does not exist -// Note , this is not a runtime update cmd. +// It fails config is already using the same key or if the key does not exist func (cc *PenumbraProvider) UseKey(key string) error { cc.PCfg.Key = key return nil From 6df284dfa4075fc30847abc4098db3427fcd9369 Mon Sep 17 00:00:00 2001 From: vimystic <122659254+vimystic@users.noreply.github.com> Date: Wed, 6 Sep 2023 21:13:37 -0600 Subject: [PATCH 8/8] Update scenarios test to prune dangling images --- .github/workflows/interchaintest.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/interchaintest.yml b/.github/workflows/interchaintest.yml index f136b26d1..b31ab3c1e 100644 --- a/.github/workflows/interchaintest.yml +++ b/.github/workflows/interchaintest.yml @@ -152,4 +152,8 @@ jobs: ${{ runner.os }}-go- - name: interchaintest - run: make interchaintest-scenario \ No newline at end of file + run: make interchaintest-scenario + + - name: Prune Docker images + if: always() #ensure dangling images are pruned after interchain-test scenario passes or fails + run: docker image prune -f