From 097da3a4d6538773577cf8ee994169cb0f3a6732 Mon Sep 17 00:00:00 2001 From: Dan Kanefsky <56059752+boojamya@users.noreply.github.com> Date: Mon, 7 Nov 2022 16:24:03 -0800 Subject: [PATCH] Integrate coin-type configuration (#338) * integrate coin-type configuration * account for cointype 0 * fix types * add comment * handle feedback --- chain/cosmos/chain_node.go | 3 ++- chainspec.go | 6 ++++++ ibc/relayer.go | 4 ++-- ibc/types.go | 31 +++++++++++++++++++++++++++++++ interchain.go | 15 +++++++++------ relayer/docker.go | 12 ++++++------ relayer/rly/cosmos_relayer.go | 9 +++++---- 7 files changed, 61 insertions(+), 19 deletions(-) diff --git a/chain/cosmos/chain_node.go b/chain/cosmos/chain_node.go index 13ef2a368..2ce6fdaf1 100644 --- a/chain/cosmos/chain_node.go +++ b/chain/cosmos/chain_node.go @@ -495,6 +495,7 @@ func (tn *ChainNode) CreateKey(ctx context.Context, name string) error { _, _, err := tn.ExecBin(ctx, "keys", "add", name, + "--coin-type", tn.Chain.Config().CoinType, "--keyring-backend", keyring.BackendTest, ) return err @@ -505,7 +506,7 @@ func (tn *ChainNode) RecoverKey(ctx context.Context, keyName, mnemonic string) e command := []string{ "sh", "-c", - fmt.Sprintf(`echo %q | %s keys add %s --recover --keyring-backend %s --home %s --output json`, mnemonic, tn.Chain.Config().Bin, keyName, keyring.BackendTest, tn.HomeDir()), + fmt.Sprintf(`echo %q | %s keys add %s --recover --keyring-backend %s --coin-type %s --home %s --output json`, mnemonic, tn.Chain.Config().Bin, keyName, keyring.BackendTest, tn.Chain.Config().CoinType, tn.HomeDir()), } tn.lock.Lock() diff --git a/chainspec.go b/chainspec.go index 8fa73c5dc..18c077d58 100644 --- a/chainspec.go +++ b/chainspec.go @@ -106,6 +106,12 @@ func (s *ChainSpec) Config(log *zap.Logger) (*ibc.ChainConfig, error) { // Apply any overrides from this ChainSpec. cfg = cfg.MergeChainSpecConfig(s.ChainConfig) + coinType, err := cfg.VerifyCoinType() + if err != nil { + return nil, err + } + cfg.CoinType = coinType + // Apply remaining top-level overrides. return s.applyConfigOverrides(cfg) } diff --git a/ibc/relayer.go b/ibc/relayer.go index 23ef5da3b..c2ad78e2d 100644 --- a/ibc/relayer.go +++ b/ibc/relayer.go @@ -24,10 +24,10 @@ import ( // but the report will be missing details. type Relayer interface { // restore a mnemonic to be used as a relayer wallet for a chain - RestoreKey(ctx context.Context, rep RelayerExecReporter, chainID, keyName, mnemonic string) error + RestoreKey(ctx context.Context, rep RelayerExecReporter, chainID, keyName, coinType, mnemonic string) error // generate a new key - AddKey(ctx context.Context, rep RelayerExecReporter, chainID, keyName string) (Wallet, error) + AddKey(ctx context.Context, rep RelayerExecReporter, chainID, keyName, coinType string) (Wallet, error) // GetWallet returns a Wallet for that relayer on the given chain and a boolean indicating if it was found. GetWallet(chainID string) (Wallet, bool) diff --git a/ibc/types.go b/ibc/types.go index 7428cbcc3..692a4ce56 100644 --- a/ibc/types.go +++ b/ibc/types.go @@ -1,6 +1,9 @@ package ibc import ( + "reflect" + "strconv" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" "github.com/cosmos/cosmos-sdk/types" ibcexported "github.com/cosmos/ibc-go/v6/modules/core/03-connection/types" @@ -22,6 +25,8 @@ type ChainConfig struct { Bech32Prefix string `yaml:"bech32-prefix"` // Denomination of native currency, e.g. uatom. Denom string `yaml:"denom"` + // Coin type + CoinType string `default:"118" yaml:"coin-type"` // Minimum gas prices for sending transactions, in native currency denom. GasPrices string `yaml:"gas-prices"` // Adjustment multiplier for gas fees. @@ -46,6 +51,27 @@ func (c ChainConfig) Clone() ChainConfig { return x } +func (c ChainConfig) VerifyCoinType() (string, error) { + // If coin-type is left blank in the ChainConfig, + // the Cosmos SDK default of 118 is used. + if c.CoinType == "" { + typ := reflect.TypeOf(c) + f, _ := typ.FieldByName("CoinType") + coinType := f.Tag.Get("default") + _, err := strconv.ParseUint(coinType, 10, 32) + if err != nil { + return "", err + } + return coinType, nil + } else { + _, err := strconv.ParseUint(c.CoinType, 10, 32) + if err != nil { + return "", err + } + return c.CoinType, nil + } +} + func (c ChainConfig) MergeChainSpecConfig(other ChainConfig) ChainConfig { // Make several in-place modifications to c, // which is a value, not a reference, @@ -77,6 +103,10 @@ func (c ChainConfig) MergeChainSpecConfig(other ChainConfig) ChainConfig { c.Denom = other.Denom } + if other.CoinType != "" { + c.CoinType = other.CoinType + } + if other.GasPrices != "" { c.GasPrices = other.GasPrices } @@ -178,6 +208,7 @@ type Wallet struct { Mnemonic string `json:"mnemonic"` Address string `json:"address"` KeyName string + CoinType uint32 } func (w *Wallet) GetKeyName() string { diff --git a/interchain.go b/interchain.go index dcd8be3f2..4a3e92def 100644 --- a/interchain.go +++ b/interchain.go @@ -3,6 +3,7 @@ package ibctest import ( "context" "fmt" + "strconv" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -423,6 +424,7 @@ func (ic *Interchain) configureRelayerKeys(ctx context.Context, rep *testreporte if err := r.RestoreKey(ctx, rep, c.Config().ChainID, chainName, + c.Config().CoinType, ic.relayerWallets[relayerChain{R: r, C: c}].Mnemonic, ); err != nil { return fmt.Errorf("failed to restore key to relayer %s for chain %s: %w", ic.relayers[r], chainName, err) @@ -442,14 +444,15 @@ type relayerChain struct { // BuildWallet will generate a random key for the key name in the provided keyring. // Returns the mnemonic and address in the bech32 format of the provided ChainConfig. func BuildWallet(kr keyring.Keyring, keyName string, config ibc.ChainConfig) ibc.Wallet { - // NOTE: this is hardcoded to the cosmos coin type. - // In the future, we may need to get the coin type from the chain config. - const coinType = types.CoinType + coinType, err := strconv.ParseUint(config.CoinType, 10, 32) + if err != nil { + panic(fmt.Errorf("invalid coin type: %w", err)) + } info, mnemonic, err := kr.NewMnemonic( keyName, keyring.English, - hd.CreateHDPath(coinType, 0, 0).String(), + hd.CreateHDPath(uint32(coinType), 0, 0).String(), "", // Empty passphrase. hd.Secp256k1, ) @@ -463,9 +466,9 @@ func BuildWallet(kr keyring.Keyring, keyName string, config ibc.ChainConfig) ibc } return ibc.Wallet{ - Address: types.MustBech32ifyAddressBytes(config.Bech32Prefix, addr.Bytes()), - + Address: types.MustBech32ifyAddressBytes(config.Bech32Prefix, addr.Bytes()), Mnemonic: mnemonic, + CoinType: uint32(coinType), } } diff --git a/relayer/docker.go b/relayer/docker.go index 767a088e0..e9882ffc4 100644 --- a/relayer/docker.go +++ b/relayer/docker.go @@ -189,8 +189,8 @@ func (r *DockerRelayer) generateConfigTar(relativeConfigPath string, content []b return &buf, nil } -func (r *DockerRelayer) AddKey(ctx context.Context, rep ibc.RelayerExecReporter, chainID, keyName string) (ibc.Wallet, error) { - cmd := r.c.AddKey(chainID, keyName, r.HomeDir()) +func (r *DockerRelayer) AddKey(ctx context.Context, rep ibc.RelayerExecReporter, chainID, keyName, coinType string) (ibc.Wallet, error) { + cmd := r.c.AddKey(chainID, keyName, coinType, r.HomeDir()) // Adding a key should be near-instantaneous, so add a 1-minute timeout // to detect if Docker has hung. @@ -317,8 +317,8 @@ func (r *DockerRelayer) Exec(ctx context.Context, rep ibc.RelayerExecReporter, c } } -func (r *DockerRelayer) RestoreKey(ctx context.Context, rep ibc.RelayerExecReporter, chainID, keyName, mnemonic string) error { - cmd := r.c.RestoreKey(chainID, keyName, mnemonic, r.HomeDir()) +func (r *DockerRelayer) RestoreKey(ctx context.Context, rep ibc.RelayerExecReporter, chainID, keyName, coinType, mnemonic string) error { + cmd := r.c.RestoreKey(chainID, keyName, coinType, mnemonic, r.HomeDir()) // Restoring a key should be near-instantaneous, so add a 1-minute timeout // to detect if Docker has hung. @@ -644,7 +644,7 @@ type RelayerCommander interface { // The remaining methods produce the command to run inside the container. AddChainConfiguration(containerFilePath, homeDir string) []string - AddKey(chainID, keyName, homeDir string) []string + AddKey(chainID, keyName, coinType, homeDir string) []string CreateChannel(pathName string, opts ibc.CreateChannelOptions, homeDir string) []string CreateClients(pathName string, opts ibc.CreateClientOptions, homeDir string) []string CreateConnections(pathName, homeDir string) []string @@ -655,7 +655,7 @@ type RelayerCommander interface { GetChannels(chainID, homeDir string) []string GetConnections(chainID, homeDir string) []string LinkPath(pathName, homeDir string, channelOpts ibc.CreateChannelOptions, clientOpts ibc.CreateClientOptions) []string - RestoreKey(chainID, keyName, mnemonic, homeDir string) []string + RestoreKey(chainID, keyName, coinType, mnemonic, homeDir string) []string StartRelayer(homeDir string, pathNames ...string) []string UpdateClients(pathName, homeDir string) []string } diff --git a/relayer/rly/cosmos_relayer.go b/relayer/rly/cosmos_relayer.go index 41ff2beb7..e2bbb80f4 100644 --- a/relayer/rly/cosmos_relayer.go +++ b/relayer/rly/cosmos_relayer.go @@ -4,6 +4,7 @@ package rly import ( "context" "encoding/json" + "fmt" "strings" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -116,10 +117,10 @@ func (commander) AddChainConfiguration(containerFilePath, homeDir string) []stri } } -func (commander) AddKey(chainID, keyName, homeDir string) []string { +func (commander) AddKey(chainID, keyName, coinType, homeDir string) []string { return []string{ "rly", "keys", "add", chainID, keyName, - "--home", homeDir, + "--coin-type", fmt.Sprint(coinType), "--home", homeDir, } } @@ -214,10 +215,10 @@ func (commander) LinkPath(pathName, homeDir string, channelOpts ibc.CreateChanne } } -func (commander) RestoreKey(chainID, keyName, mnemonic, homeDir string) []string { +func (commander) RestoreKey(chainID, keyName, coinType, mnemonic, homeDir string) []string { return []string{ "rly", "keys", "restore", chainID, keyName, mnemonic, - "--home", homeDir, + "--coin-type", fmt.Sprint(coinType), "--home", homeDir, } }