diff --git a/changelog.md b/changelog.md index 805c6d4a26..8e53bb366b 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,9 @@ * [2984](https://github.com/zeta-chain/node/pull/2984) - add Whitelist message ability to whitelist SPL tokens on Solana * [3091](https://github.com/zeta-chain/node/pull/3091) - improve build reproducability. `make release{,-build-only}` checksums should now be stable. +### Refactor +* [3122](https://github.com/zeta-chain/node/pull/3122) - improve & refactor zetaclientd cli + ### Tests * [3075](https://github.com/zeta-chain/node/pull/3075) - ton: withdraw concurrent, deposit & revert. diff --git a/cmd/config.go b/cmd/config.go deleted file mode 100644 index 978d90c433..0000000000 --- a/cmd/config.go +++ /dev/null @@ -1,12 +0,0 @@ -package cmd - -const ( - Bech32PrefixAccAddr = "zeta" - Bech32PrefixAccPub = "zetapub" - Bech32PrefixValAddr = "zetav" - Bech32PrefixValPub = "zetavpub" - Bech32PrefixConsAddr = "zetac" - Bech32PrefixConsPub = "zetacpub" - DenomRegex = `[a-zA-Z][a-zA-Z0-9:\\/\\\-\\_\\.]{2,127}` - ZetaChainHDPath string = `m/44'/60'/0'/0/0` -) diff --git a/cmd/cosmos.go b/cmd/cosmos.go new file mode 100644 index 0000000000..9c0b3b8e3d --- /dev/null +++ b/cmd/cosmos.go @@ -0,0 +1,36 @@ +// Package cmd provides cosmos constants for ZetaClient. +package cmd + +import ( + "sync" + + cosmos "github.com/cosmos/cosmos-sdk/types" +) + +const ( + Bech32PrefixAccAddr = "zeta" + Bech32PrefixAccPub = "zetapub" + Bech32PrefixValAddr = "zetav" + Bech32PrefixValPub = "zetavpub" + Bech32PrefixConsAddr = "zetac" + Bech32PrefixConsPub = "zetacpub" + DenomRegex = `[a-zA-Z][a-zA-Z0-9:\\/\\\-\\_\\.]{2,127}` + ZetaChainHDPath string = `m/44'/60'/0'/0/0` +) + +var setupConfig sync.Once + +// SetupCosmosConfig configures basic Cosmos parameters. +// This function is required because some parts of ZetaClient rely on these constants. +func SetupCosmosConfig() { + setupConfig.Do(setupCosmosConfig) +} + +func setupCosmosConfig() { + config := cosmos.GetConfig() + config.SetBech32PrefixForAccount(Bech32PrefixAccAddr, Bech32PrefixAccPub) + config.SetBech32PrefixForValidator(Bech32PrefixValAddr, Bech32PrefixValPub) + config.SetBech32PrefixForConsensusNode(Bech32PrefixConsAddr, Bech32PrefixConsPub) + config.SetFullFundraiserPath(ZetaChainHDPath) + cosmos.SetCoinDenomRegex(func() string { return DenomRegex }) +} diff --git a/cmd/zetaclientd/encrypt_tss.go b/cmd/zetaclientd/encrypt_tss.go deleted file mode 100644 index 92be57a190..0000000000 --- a/cmd/zetaclientd/encrypt_tss.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "encoding/json" - "os" - "path/filepath" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - - "github.com/zeta-chain/node/pkg/crypto" -) - -var encTssCmd = &cobra.Command{ - Use: "tss-encrypt [file-path] [secret-key]", - Short: "Utility command to encrypt existing tss key-share file", - Args: cobra.ExactArgs(2), - RunE: EncryptTSSFile, -} - -func init() { - RootCmd.AddCommand(encTssCmd) -} - -// EncryptTSSFile encrypts the given file with the given secret key -func EncryptTSSFile(_ *cobra.Command, args []string) error { - filePath := args[0] - password := args[1] - - filePath = filepath.Clean(filePath) - data, err := os.ReadFile(filePath) - if err != nil { - return err - } - - if !json.Valid(data) { - return errors.New("file does not contain valid json, may already be encrypted") - } - - // encrypt the data - cipherText, err := crypto.EncryptAES256GCM(data, password) - if err != nil { - return errors.Wrap(err, "failed to encrypt data") - } - - return os.WriteFile(filePath, cipherText, 0o600) -} diff --git a/cmd/zetaclientd/gen_pre_params.go b/cmd/zetaclientd/gen_pre_params.go deleted file mode 100644 index c61f31ec2b..0000000000 --- a/cmd/zetaclientd/gen_pre_params.go +++ /dev/null @@ -1,40 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "os" - "time" - - "github.com/bnb-chain/tss-lib/ecdsa/keygen" - "github.com/spf13/cobra" -) - -func init() { - RootCmd.AddCommand(GenPrePramsCmd) -} - -var GenPrePramsCmd = &cobra.Command{ - Use: "gen-pre-params ", - Short: "Generate pre parameters for TSS", - Args: cobra.ExactArgs(1), - RunE: func(_ *cobra.Command, args []string) error { - startTime := time.Now() - preParams, err := keygen.GeneratePreParams(time.Second * 300) - if err != nil { - return err - } - - file, err := os.OpenFile(args[0], os.O_RDWR|os.O_CREATE, 0600) - if err != nil { - return err - } - defer file.Close() - err = json.NewEncoder(file).Encode(preParams) - if err != nil { - return err - } - fmt.Printf("Generated new pre-parameters in %v\n", time.Since(startTime)) - return nil - }, -} diff --git a/cmd/zetaclientd/import_relayer_keys.go b/cmd/zetaclientd/import_relayer_keys.go deleted file mode 100644 index ecd71a6f5c..0000000000 --- a/cmd/zetaclientd/import_relayer_keys.go +++ /dev/null @@ -1,153 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/pkg/errors" - "github.com/rs/zerolog/log" - "github.com/spf13/cobra" - - "github.com/zeta-chain/node/pkg/chains" - "github.com/zeta-chain/node/pkg/crypto" - zetaos "github.com/zeta-chain/node/pkg/os" - "github.com/zeta-chain/node/zetaclient/config" - "github.com/zeta-chain/node/zetaclient/keys" -) - -var CmdImportRelayerKey = &cobra.Command{ - Use: "import-relayer-key --network= --private-key= --password= --relayer-key-path=", - Short: "Import a relayer private key", - Example: `zetaclientd import-relayer-key --network=7 --private-key= --password=`, - RunE: ImportRelayerKey, -} - -var CmdRelayerAddress = &cobra.Command{ - Use: "relayer-address --network= --password= --relayer-key-path=", - Short: "Show the relayer address", - Example: `zetaclientd relayer-address --network=7 --password=my_password`, - RunE: ShowRelayerAddress, -} - -var importArgs = importRelayerKeyArguments{} -var addressArgs = relayerAddressArguments{} - -// importRelayerKeyArguments is the struct that holds the arguments for the import command -type importRelayerKeyArguments struct { - network int32 - privateKey string - password string - relayerKeyPath string -} - -// relayerAddressArguments is the struct that holds the arguments for the show command -type relayerAddressArguments struct { - network int32 - password string - relayerKeyPath string -} - -func init() { - RootCmd.AddCommand(CmdImportRelayerKey) - RootCmd.AddCommand(CmdRelayerAddress) - - // resolve default relayer key path - defaultRelayerKeyPath, err := zetaos.ExpandHomeDir(config.DefaultRelayerKeyPath) - if err != nil { - log.Fatal().Err(err).Msg("failed to resolve default relayer key path") - } - - CmdImportRelayerKey.Flags().Int32Var(&importArgs.network, "network", 7, "network id, (7: solana)") - CmdImportRelayerKey.Flags(). - StringVar(&importArgs.privateKey, "private-key", "", "the relayer private key to import") - CmdImportRelayerKey.Flags(). - StringVar(&importArgs.password, "password", "", "the password to encrypt the relayer private key") - CmdImportRelayerKey.Flags(). - StringVar(&importArgs.relayerKeyPath, "relayer-key-path", defaultRelayerKeyPath, "path to relayer keys") - - CmdRelayerAddress.Flags().Int32Var(&addressArgs.network, "network", 7, "network id, (7:solana)") - CmdRelayerAddress.Flags(). - StringVar(&addressArgs.password, "password", "", "the password to decrypt the relayer private key") - CmdRelayerAddress.Flags(). - StringVar(&addressArgs.relayerKeyPath, "relayer-key-path", defaultRelayerKeyPath, "path to relayer keys") -} - -// ImportRelayerKey imports a relayer private key -func ImportRelayerKey(_ *cobra.Command, _ []string) error { - // validate private key and password - if importArgs.privateKey == "" { - return errors.New("must provide a private key") - } - if importArgs.password == "" { - return errors.New("must provide a password") - } - if !keys.IsRelayerPrivateKeyValid(importArgs.privateKey, chains.Network(importArgs.network)) { - return errors.New("invalid private key") - } - - // resolve the relayer key file path - fileName, err := keys.ResolveRelayerKeyFile(importArgs.relayerKeyPath, chains.Network(importArgs.network)) - if err != nil { - return errors.Wrap(err, "failed to resolve relayer key file path") - } - - // create path (owner `rwx` permissions) if it does not exist - keyPath := filepath.Dir(fileName) - if _, err := os.Stat(keyPath); os.IsNotExist(err) { - if err := os.MkdirAll(keyPath, 0o700); err != nil { - return errors.Wrapf(err, "failed to create relayer key path: %s", keyPath) - } - } - - // avoid overwriting existing key file - if zetaos.FileExists(fileName) { - return errors.Errorf( - "relayer key %s already exists, please backup and remove it before importing a new key", - fileName, - ) - } - - // encrypt the private key - ciphertext, err := crypto.EncryptAES256GCMBase64(importArgs.privateKey, importArgs.password) - if err != nil { - return errors.Wrap(err, "private key encryption failed") - } - - // create the relayer key file - err = keys.WriteRelayerKeyToFile(fileName, keys.RelayerKey{PrivateKey: ciphertext}) - if err != nil { - return errors.Wrapf(err, "failed to create relayer key file: %s", fileName) - } - fmt.Printf("successfully imported relayer key: %s\n", fileName) - - return nil -} - -// ShowRelayerAddress shows the relayer address -func ShowRelayerAddress(_ *cobra.Command, _ []string) error { - // try loading the relayer key if present - network := chains.Network(addressArgs.network) - relayerKey, err := keys.LoadRelayerKey(addressArgs.relayerKeyPath, network, addressArgs.password) - if err != nil { - return errors.Wrap(err, "failed to load relayer key") - } - - // relayer key does not exist, return error - if relayerKey == nil { - return fmt.Errorf( - "relayer key not found for network %d in path: %s", - addressArgs.network, - addressArgs.relayerKeyPath, - ) - } - - // resolve the relayer address - networkName, address, err := relayerKey.ResolveAddress(network) - if err != nil { - return errors.Wrap(err, "failed to resolve relayer address") - } - fmt.Printf("relayer address (%s): %s\n", networkName, address) - - return nil -} diff --git a/cmd/zetaclientd/debug.go b/cmd/zetaclientd/inbound.go similarity index 84% rename from cmd/zetaclientd/debug.go rename to cmd/zetaclientd/inbound.go index c0abb69db6..bac3c96725 100644 --- a/cmd/zetaclientd/debug.go +++ b/cmd/zetaclientd/inbound.go @@ -3,7 +3,6 @@ package main import ( "context" "fmt" - "os" "strconv" "strings" @@ -26,36 +25,24 @@ import ( "github.com/zeta-chain/node/zetaclient/zetacore" ) -var debugArgs = debugArguments{} - -type debugArguments struct { - zetaCoreHome string - zetaNode string - zetaChainID string +type inboundOptions struct { + Node string + ChainID string } -func init() { - defaultHomeDir := os.ExpandEnv("$HOME/.zetacored") +var inboundOpts inboundOptions - cmd := DebugCmd() - cmd.Flags().StringVar(&debugArgs.zetaCoreHome, "core-home", defaultHomeDir, "zetacore home directory") - cmd.Flags().StringVar(&debugArgs.zetaNode, "node", "46.4.15.110", "public ip address") - cmd.Flags().StringVar(&debugArgs.zetaChainID, "chain-id", "athens_7001-1", "pre-params file path") +func setupInboundOptions() { + f, cfg := InboundCmd.PersistentFlags(), &inboundOpts - RootCmd.AddCommand(cmd) + f.StringVar(&cfg.Node, "node", "46.4.15.110", "zeta public ip address") + f.StringVar(&cfg.ChainID, "chain-id", "athens_7001-1", "zeta chain id") } -func DebugCmd() *cobra.Command { - return &cobra.Command{ - Use: "get-inbound-ballot [inboundHash] [chainID]", - Short: "provide txHash and chainID to get the ballot status for the txHash", - RunE: debugCmd, - } -} - -func debugCmd(_ *cobra.Command, args []string) error { +func InboundGetBallot(_ *cobra.Command, args []string) error { cobra.ExactArgs(2) - cfg, err := config.Load(debugArgs.zetaCoreHome) + + cfg, err := config.Load(globalOpts.ZetacoreHome) if err != nil { return errors.Wrap(err, "failed to load config") } @@ -70,9 +57,9 @@ func debugCmd(_ *cobra.Command, args []string) error { // create a new zetacore client client, err := zetacore.NewClient( &keys.Keys{OperatorAddress: sdk.MustAccAddressFromBech32(sample.AccAddress())}, - debugArgs.zetaNode, + inboundOpts.Node, "", - debugArgs.zetaChainID, + inboundOpts.ChainID, zerolog.Nop(), ) if err != nil { diff --git a/cmd/zetaclientd/init.go b/cmd/zetaclientd/init.go deleted file mode 100644 index c8fef11552..0000000000 --- a/cmd/zetaclientd/init.go +++ /dev/null @@ -1,110 +0,0 @@ -package main - -import ( - "github.com/rs/zerolog" - "github.com/spf13/cobra" - - "github.com/zeta-chain/node/testutil/sample" - "github.com/zeta-chain/node/zetaclient/config" -) - -var InitCmd = &cobra.Command{ - Use: "init", - Short: "Initialize Configuration", - RunE: Initialize, -} - -var initArgs = initArguments{} - -type initArguments struct { - peer string - publicIP string - logFormat string - logSampler bool - preParamsPath string - chainID string - zetacoreURL string - authzGranter string - authzHotkey string - level int8 - configUpdateTicker uint64 - - p2pDiagnostic bool - p2pDiagnosticTicker uint64 - TssPath string - TestTssKeysign bool - KeyringBackend string - RelayerKeyPath string -} - -func init() { - RootCmd.AddCommand(InitCmd) - RootCmd.AddCommand(VersionCmd) - - InitCmd.Flags(). - StringVar(&initArgs.peer, "peer", "", "peer address, e.g. /dns/tss1/tcp/6668/ipfs/16Uiu2HAmACG5DtqmQsHtXg4G2sLS65ttv84e7MrL4kapkjfmhxAp") - InitCmd.Flags().StringVar(&initArgs.publicIP, "public-ip", "", "public ip address") - InitCmd.Flags().StringVar(&initArgs.preParamsPath, "pre-params", "~/preParams.json", "pre-params file path") - InitCmd.Flags().StringVar(&initArgs.chainID, "chain-id", "athens_7001-1", "chain id") - InitCmd.Flags().StringVar(&initArgs.zetacoreURL, "zetacore-url", "127.0.0.1", "zetacore node URL") - InitCmd.Flags(). - StringVar(&initArgs.authzGranter, "operator", "", "granter for the authorization , this should be operator address") - InitCmd.Flags(). - StringVar(&initArgs.authzHotkey, "hotkey", "hotkey", "hotkey for zetaclient this key is used for TSS and ZetaClient operations") - InitCmd.Flags(). - Int8Var(&initArgs.level, "log-level", int8(zerolog.InfoLevel), "log level (0:debug, 1:info, 2:warn, 3:error, 4:fatal, 5:panic , 6: NoLevel , 7: Disable)") - InitCmd.Flags().StringVar(&initArgs.logFormat, "log-format", "json", "log format (json, test)") - InitCmd.Flags().BoolVar(&initArgs.logSampler, "log-sampler", false, "set to to true to turn on log sampling") - InitCmd.Flags().BoolVar(&initArgs.p2pDiagnostic, "p2p-diagnostic", false, "enable p2p diagnostic") - InitCmd.Flags(). - Uint64Var(&initArgs.p2pDiagnosticTicker, "p2p-diagnostic-ticker", 30, "p2p diagnostic ticker (default: 0 means no ticker)") - InitCmd.Flags(). - Uint64Var(&initArgs.configUpdateTicker, "config-update-ticker", 5, "config update ticker (default: 0 means no ticker)") - InitCmd.Flags().StringVar(&initArgs.TssPath, "tss-path", "~/.tss", "path to tss location") - InitCmd.Flags(). - BoolVar(&initArgs.TestTssKeysign, "test-tss", false, "set to to true to run a check for TSS keysign on startup") - InitCmd.Flags(). - StringVar(&initArgs.KeyringBackend, "keyring-backend", string(config.KeyringBackendTest), "keyring backend to use (test, file)") - InitCmd.Flags(). - StringVar(&initArgs.RelayerKeyPath, "relayer-key-path", "~/.zetacored/relayer-keys", "path to relayer keys") -} - -func Initialize(_ *cobra.Command, _ []string) error { - err := setHomeDir() - if err != nil { - return err - } - - //Create new config struct - configData := config.New(true) - - //Validate Peer eg. /ip4/172.0.2.1/tcp/6668/p2p/16Uiu2HAmACG5DtqmQsHtXg4G2sLS65ttv84e7MrL4kapkjfmhxAp - if len(initArgs.peer) != 0 { - err := validatePeer(initArgs.peer) - if err != nil { - return err - } - } - - //Populate new struct with cli arguments - configData.Peer = initArgs.peer - configData.PublicIP = initArgs.publicIP - configData.PreParamsPath = initArgs.preParamsPath - configData.ChainID = initArgs.chainID - configData.ZetaCoreURL = initArgs.zetacoreURL - configData.AuthzHotkey = initArgs.authzHotkey - configData.AuthzGranter = initArgs.authzGranter - configData.LogLevel = initArgs.level - configData.LogFormat = initArgs.logFormat - configData.LogSampler = initArgs.logSampler - configData.P2PDiagnostic = initArgs.p2pDiagnostic - configData.TssPath = initArgs.TssPath - configData.P2PDiagnosticTicker = initArgs.p2pDiagnosticTicker - configData.ConfigUpdateTicker = initArgs.configUpdateTicker - configData.KeyringBackend = config.KeyringBackend(initArgs.KeyringBackend) - configData.RelayerKeyPath = initArgs.RelayerKeyPath - configData.ComplianceConfig = sample.ComplianceConfig() - - // Save config file - return config.Save(&configData, rootArgs.zetaCoreHome) -} diff --git a/cmd/zetaclientd/initconfig.go b/cmd/zetaclientd/initconfig.go new file mode 100644 index 0000000000..6619ce279a --- /dev/null +++ b/cmd/zetaclientd/initconfig.go @@ -0,0 +1,103 @@ +package main + +import ( + "cosmossdk.io/errors" + "github.com/rs/zerolog" + "github.com/spf13/cobra" + + "github.com/zeta-chain/node/testutil/sample" + "github.com/zeta-chain/node/zetaclient/config" +) + +// initializeConfigOptions is a set of CLI options for `init` command. +type initializeConfigOptions struct { + peer string + publicIP string + logFormat string + logSampler bool + preParamsPath string + chainID string + zetacoreURL string + authzGranter string + authzHotkey string + level int8 + configUpdateTicker uint64 + + p2pDiagnostic bool + p2pDiagnosticTicker uint64 + TSSPath string + TestTSSKeySign bool + KeyringBackend string + RelayerKeyPath string +} + +var initializeConfigOpts initializeConfigOptions + +func setupInitializeConfigOptions() { + f, cfg := InitializeConfigCmd.Flags(), &initializeConfigOpts + + const ( + usagePeer = "peer address e.g. /dns/tss1/tcp/6668/ipfs/16Uiu2HAmACG5DtqmQsH..." + usageHotKey = "hotkey for zetaclient this key is used for TSS and ZetaClient operations" + usageLogLevel = "log level (0:debug, 1:info, 2:warn, 3:error, 4:fatal, 5:panic)" + usageP2PDiag = "p2p diagnostic ticker (default: 0 means no ticker)" + usageTicker = "config update ticker (default: 0 means no ticker)" + usageKeyring = "keyring backend to use (test, file)" + ) + + f.StringVar(&cfg.peer, "peer", "", usagePeer) + f.StringVar(&cfg.publicIP, "public-ip", "", "public ip address") + f.StringVar(&cfg.preParamsPath, "pre-params", "~/preParams.json", "pre-params file path") + f.StringVar(&cfg.chainID, "chain-id", "athens_7001-1", "chain id") + f.StringVar(&cfg.zetacoreURL, "zetacore-url", "127.0.0.1", "zetacore node URL") + f.StringVar(&cfg.authzGranter, "operator", "", "granter for the authorization , this should be operator address") + f.StringVar(&cfg.authzHotkey, "hotkey", "hotkey", usageHotKey) + f.Int8Var(&cfg.level, "log-level", int8(zerolog.InfoLevel), usageLogLevel) + f.StringVar(&cfg.logFormat, "log-format", "json", "log format (json, test)") + f.BoolVar(&cfg.logSampler, "log-sampler", false, "set to to true to turn on log sampling") + f.BoolVar(&cfg.p2pDiagnostic, "p2p-diagnostic", false, "enable p2p diagnostic") + f.Uint64Var(&cfg.p2pDiagnosticTicker, "p2p-diagnostic-ticker", 30, usageP2PDiag) + f.Uint64Var(&cfg.configUpdateTicker, "config-update-ticker", 5, usageTicker) + f.StringVar(&cfg.TSSPath, "tss-path", "~/.tss", "path to tss location") + f.BoolVar(&cfg.TestTSSKeySign, "test-tss", false, "set to to true to run a check for TSS keysign on startup") + f.StringVar(&cfg.KeyringBackend, "keyring-backend", string(config.KeyringBackendTest), usageKeyring) + f.StringVar(&cfg.RelayerKeyPath, "relayer-key-path", "~/.zetacored/relayer-keys", "path to relayer keys") +} + +// InitializeConfig creates new config for zetaclientd and saves it to the config file. +func InitializeConfig(_ *cobra.Command, _ []string) error { + // Create new config struct + configData := config.New(true) + opts := &initializeConfigOpts + + // Validate Peer + // e.g. /ip4/172.0.2.1/tcp/6668/p2p/16Uiu2HAmACG5DtqmQsHtXg4G2sLS65ttv84e7MrL4kapkjfmhxAp + if opts.peer != "" { + if err := validatePeer(opts.peer); err != nil { + return errors.Wrap(err, "invalid peer address") + } + } + + // Populate new struct with cli arguments + configData.Peer = initializeConfigOpts.peer + configData.PublicIP = opts.publicIP + configData.PreParamsPath = opts.preParamsPath + configData.ChainID = opts.chainID + configData.ZetaCoreURL = opts.zetacoreURL + configData.AuthzHotkey = opts.authzHotkey + configData.AuthzGranter = opts.authzGranter + configData.LogLevel = opts.level + configData.LogFormat = opts.logFormat + configData.LogSampler = opts.logSampler + configData.P2PDiagnostic = opts.p2pDiagnostic + configData.TssPath = opts.TSSPath + configData.TestTssKeysign = opts.TestTSSKeySign + configData.P2PDiagnosticTicker = opts.p2pDiagnosticTicker + configData.ConfigUpdateTicker = opts.configUpdateTicker + configData.KeyringBackend = config.KeyringBackend(initializeConfigOpts.KeyringBackend) + configData.RelayerKeyPath = opts.RelayerKeyPath + configData.ComplianceConfig = sample.ComplianceConfig() + + // Save config file + return config.Save(&configData, globalOpts.ZetacoreHome) +} diff --git a/cmd/zetaclientd/main.go b/cmd/zetaclientd/main.go index 2ad829d352..b3113f4035 100644 --- a/cmd/zetaclientd/main.go +++ b/cmd/zetaclientd/main.go @@ -1,45 +1,120 @@ package main import ( - "math/rand" + "context" + "fmt" "os" - "time" - ecdsakeygen "github.com/bnb-chain/tss-lib/ecdsa/keygen" - "github.com/cosmos/cosmos-sdk/server" - svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" - "github.com/cosmos/cosmos-sdk/types" + tmcli "github.com/cometbft/cometbft/libs/cli" + "github.com/spf13/cobra" "github.com/zeta-chain/node/app" "github.com/zeta-chain/node/cmd" + "github.com/zeta-chain/node/pkg/constant" ) var ( - preParams *ecdsakeygen.LocalPreParams -) + RootCmd = &cobra.Command{ + Use: "zetaclientd", + Short: "zetaclient cli & server", + } + VersionCmd = &cobra.Command{ + Use: "version", + Short: "prints version", + Run: func(_ *cobra.Command, _ []string) { fmt.Print(constant.Version) }, + } -func main() { - if err := svrcmd.Execute(RootCmd, "", app.DefaultNodeHome); err != nil { - switch e := err.(type) { - case server.ErrorCode: - os.Exit(e.Code) + InitializeConfigCmd = &cobra.Command{ + Use: "init-config", + Aliases: []string{"init"}, + Short: "Initialize Zetaclient Configuration file", + RunE: InitializeConfig, + } + StartCmd = &cobra.Command{ + Use: "start", + Short: "Start ZetaClient Observer", + RunE: Start, + } + + TSSCmd = &cobra.Command{Use: "tss", Short: "TSS commands"} + TSSEncryptCmd = &cobra.Command{ + Use: "encrypt [file-path] [secret-key]", + Short: "Utility command to encrypt existing tss key-share file", + Args: cobra.ExactArgs(2), + RunE: TSSEncryptFile, + } + TSSGeneratePreParamsCmd = &cobra.Command{ + Use: "gen-pre-params [path]", + Short: "Generate pre parameters for TSS", + Args: cobra.ExactArgs(1), + RunE: TSSGeneratePreParams, + } - default: - os.Exit(1) - } + RelayerCmd = &cobra.Command{Use: "relayer", Short: "Relayer commands"} + RelayerImportKeyCmd = &cobra.Command{ + Use: "import-key --network= --private-key= --password= --relayer-key-path=", + Short: "Import a relayer private key", + RunE: RelayerImportKey, } + RelayerShowAddressCmd = &cobra.Command{ + Use: "show-address --network= --password= --relayer-key-path=", + Short: "Show relayer address", + RunE: RelayerShowAddress, + } + + InboundCmd = &cobra.Command{Use: "inbound", Short: "Inbound transactions"} + InboundGetBallotCmd = &cobra.Command{ + Use: "get-ballot [inboundHash] [chainID]", + Short: "Get the ballot status for the tx hash", + RunE: InboundGetBallot, + } +) + +// globalOptions defines the global options for all commands. +type globalOptions struct { + ZetacoreHome string } -func SetupConfigForTest() { - config := types.GetConfig() - config.SetBech32PrefixForAccount(cmd.Bech32PrefixAccAddr, cmd.Bech32PrefixAccPub) - config.SetBech32PrefixForValidator(cmd.Bech32PrefixValAddr, cmd.Bech32PrefixValPub) - config.SetBech32PrefixForConsensusNode(cmd.Bech32PrefixConsAddr, cmd.Bech32PrefixConsPub) - //config.SetCoinType(cmd.MetaChainCoinType) - config.SetFullFundraiserPath(cmd.ZetaChainHDPath) - types.SetCoinDenomRegex(func() string { - return cmd.DenomRegex - }) - - rand.Seed(time.Now().UnixNano()) +var globalOpts globalOptions + +func setupGlobalOptions() { + globals := RootCmd.PersistentFlags() + + globals.StringVar(&globalOpts.ZetacoreHome, tmcli.HomeFlag, app.DefaultNodeHome, "home path") + // add more options here (e.g. verbosity, etc...) +} + +func init() { + cmd.SetupCosmosConfig() + + // Setup options + setupGlobalOptions() + setupInitializeConfigOptions() + setupRelayerOptions() + setupInboundOptions() + + // Define commands + RootCmd.AddCommand(VersionCmd) + RootCmd.AddCommand(StartCmd) + RootCmd.AddCommand(InitializeConfigCmd) + + RootCmd.AddCommand(TSSCmd) + TSSCmd.AddCommand(TSSEncryptCmd) + TSSCmd.AddCommand(TSSGeneratePreParamsCmd) + + RootCmd.AddCommand(RelayerCmd) + RelayerCmd.AddCommand(RelayerImportKeyCmd) + RelayerCmd.AddCommand(RelayerShowAddressCmd) + + RootCmd.AddCommand(InboundCmd) + InboundCmd.AddCommand(InboundGetBallotCmd) +} + +func main() { + ctx := context.Background() + + if err := RootCmd.ExecuteContext(ctx); err != nil { + fmt.Printf("Error: %s. Exit code 1\n", err) + os.Exit(1) + } } diff --git a/cmd/zetaclientd/relayer.go b/cmd/zetaclientd/relayer.go new file mode 100644 index 0000000000..bd2596bceb --- /dev/null +++ b/cmd/zetaclientd/relayer.go @@ -0,0 +1,121 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + + "github.com/zeta-chain/node/app" + "github.com/zeta-chain/node/pkg/chains" + "github.com/zeta-chain/node/pkg/crypto" + zetaos "github.com/zeta-chain/node/pkg/os" + "github.com/zeta-chain/node/zetaclient/config" + "github.com/zeta-chain/node/zetaclient/keys" +) + +// relayerOptions is the struct that holds arguments for the relayer commands +type relayerOptions struct { + privateKey string + network int32 + password string + relayerKeyPath string +} + +var relayerOpts relayerOptions + +func setupRelayerOptions() { + f, cfg := RelayerCmd.PersistentFlags(), &relayerOpts + + // resolve default relayer key path + defaultKeyPath := fmt.Sprintf("%s/%s", app.DefaultNodeHome, config.DefaultRelayerDir) + + f.Int32Var(&cfg.network, "network", 7, "network id, (7:solana)") + f.StringVar(&cfg.password, "password", "", "the password to decrypt the relayer private key") + f.StringVar(&cfg.relayerKeyPath, "key-path", defaultKeyPath, "path to relayer keys") + + // import command in addition has the private key option + f = RelayerImportKeyCmd.Flags() + f.StringVar(&cfg.privateKey, "private-key", "", "the relayer private key to import") +} + +// RelayerShowAddress shows the relayer address +func RelayerShowAddress(_ *cobra.Command, _ []string) error { + // try loading the relayer key if present + network := chains.Network(relayerOpts.network) + relayerKey, err := keys.LoadRelayerKey(relayerOpts.relayerKeyPath, network, relayerOpts.password) + if err != nil { + return errors.Wrap(err, "failed to load relayer key") + } + + // relayer key does not exist, return error + if relayerKey == nil { + return fmt.Errorf( + "relayer key not found for network %d in path: %s", + relayerOpts.network, + relayerOpts.relayerKeyPath, + ) + } + + // resolve the relayer address + networkName, address, err := relayerKey.ResolveAddress(network) + if err != nil { + return errors.Wrap(err, "failed to resolve relayer address") + } + + fmt.Printf("relayer address (%s): %s\n", networkName, address) + + return nil +} + +// RelayerImportKey imports a relayer private key +func RelayerImportKey(_ *cobra.Command, _ []string) error { + // validate private key and password + switch { + case relayerOpts.privateKey == "": + return errors.New("must provide a private key") + case relayerOpts.password == "": + return errors.New("must provide a password") + case !keys.IsRelayerPrivateKeyValid(relayerOpts.privateKey, chains.Network(relayerOpts.network)): + return errors.New("invalid private key") + } + + // resolve the relayer key file path + fileName, err := keys.ResolveRelayerKeyFile(relayerOpts.relayerKeyPath, chains.Network(relayerOpts.network)) + if err != nil { + return errors.Wrap(err, "failed to resolve relayer key file path") + } + + // create path (owner `rwx` permissions) if it does not exist + keyPath := filepath.Dir(fileName) + if _, err := os.Stat(keyPath); os.IsNotExist(err) { + if err := os.MkdirAll(keyPath, 0o700); err != nil { + return errors.Wrapf(err, "failed to create relayer key path: %s", keyPath) + } + } + + // avoid overwriting existing key file + if zetaos.FileExists(fileName) { + return errors.Errorf( + "relayer key %s already exists, please backup and remove it before importing a new key", + fileName, + ) + } + + // encrypt the private key + ciphertext, err := crypto.EncryptAES256GCMBase64(relayerOpts.privateKey, relayerOpts.password) + if err != nil { + return errors.Wrap(err, "private key encryption failed") + } + + // create the relayer key file + err = keys.WriteRelayerKeyToFile(fileName, keys.RelayerKey{PrivateKey: ciphertext}) + if err != nil { + return errors.Wrapf(err, "failed to create relayer key file: %s", fileName) + } + fmt.Printf("successfully imported relayer key: %s\n", fileName) + + return nil +} diff --git a/cmd/zetaclientd/root.go b/cmd/zetaclientd/root.go deleted file mode 100644 index 479ea2afef..0000000000 --- a/cmd/zetaclientd/root.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - tmcli "github.com/cometbft/cometbft/libs/cli" - "github.com/spf13/cobra" -) - -var RootCmd = &cobra.Command{ - Use: "zetaclientd", - Short: "ZetaClient CLI", -} -var rootArgs = rootArguments{} - -type rootArguments struct { - zetaCoreHome string -} - -func setHomeDir() error { - var err error - rootArgs.zetaCoreHome, err = RootCmd.Flags().GetString(tmcli.HomeFlag) - return err -} diff --git a/cmd/zetaclientd/start.go b/cmd/zetaclientd/start.go index f86a5fa2ee..903e6d1735 100644 --- a/cmd/zetaclientd/start.go +++ b/cmd/zetaclientd/start.go @@ -13,6 +13,7 @@ import ( "syscall" "time" + ecdsakeygen "github.com/bnb-chain/tss-lib/ecdsa/keygen" "github.com/cometbft/cometbft/crypto/secp256k1" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/p2p/protocol/ping" @@ -37,23 +38,12 @@ import ( "github.com/zeta-chain/node/zetaclient/zetacore" ) -var StartCmd = &cobra.Command{ - Use: "start", - Short: "Start ZetaClient Observer", - RunE: start, -} - -func init() { - RootCmd.AddCommand(StartCmd) -} - -func start(_ *cobra.Command, _ []string) error { - if err := setHomeDir(); err != nil { - return err - } - - SetupConfigForTest() +// todo revamp +// https://github.com/zeta-chain/node/issues/3119 +// https://github.com/zeta-chain/node/issues/3112 +var preParams *ecdsakeygen.LocalPreParams +func Start(_ *cobra.Command, _ []string) error { // Prompt for Hotkey, TSS key-share and relayer key passwords titles := []string{"HotKey", "TSS", "Solana Relayer Key"} passwords, err := zetaos.PromptPasswords(titles) @@ -66,7 +56,7 @@ func start(_ *cobra.Command, _ []string) error { } //Load Config file given path - cfg, err := config.Load(rootArgs.zetaCoreHome) + cfg, err := config.Load(globalOpts.ZetacoreHome) if err != nil { return err } @@ -77,7 +67,7 @@ func start(_ *cobra.Command, _ []string) error { } // Wait until zetacore has started - if len(cfg.Peer) != 0 { + if cfg.Peer != "" { if err := validatePeer(cfg.Peer); err != nil { return errors.Wrap(err, "unable to validate peer") } @@ -104,10 +94,9 @@ func start(_ *cobra.Command, _ []string) error { // CreateZetacoreClient: zetacore client is used for all communication to zetacore , which this client connects to. // Zetacore accumulates votes , and provides a centralized source of truth for all clients - zetacoreClient, err := CreateZetacoreClient(cfg, hotkeyPass, masterLogger) + zetacoreClient, err := createZetacoreClient(cfg, hotkeyPass, masterLogger) if err != nil { - startLogger.Error().Err(err).Msg("CreateZetacoreClient error") - return err + return errors.Wrap(err, "unable to create zetacore client") } // Wait until zetacore is ready to create blocks @@ -145,16 +134,15 @@ func start(_ *cobra.Command, _ []string) error { // This is to ensure that the user does not need to keep their operator key online , and can use a cold key to sign votes signerAddress, err := zetacoreClient.GetKeys().GetAddress() if err != nil { - startLogger.Error().Err(err).Msg("error getting signer address") - return err + return errors.Wrap(err, "error getting signer address") } - CreateAuthzSigner(zetacoreClient.GetKeys().GetOperatorAddress().String(), signerAddress) - startLogger.Debug().Msgf("CreateAuthzSigner is ready") + + createAuthzSigner(zetacoreClient.GetKeys().GetOperatorAddress().String(), signerAddress) + startLogger.Debug().Msgf("createAuthzSigner is ready") // Initialize core parameters from zetacore if err = zetacoreClient.UpdateAppContext(ctx, appContext, startLogger); err != nil { - startLogger.Error().Err(err).Msg("Error getting core parameters") - return err + return errors.Wrap(err, "unable to update app context") } startLogger.Info().Msgf("Config is updated from zetacore\n %s", cfg.StringMasked()) @@ -266,12 +254,12 @@ func start(_ *cobra.Command, _ []string) error { // Generate a new TSS if keygen is set and add it into the tss server // If TSS has already been generated, and keygen was successful ; we use the existing TSS - err = GenerateTSS(ctx, masterLogger, zetacoreClient, server) + err = mc.Generate(ctx, masterLogger, zetacoreClient, server) if err != nil { return err } - tss, err := mc.NewTSS( + tss, err := mc.New( ctx, zetacoreClient, tssHistoricalList, @@ -283,7 +271,7 @@ func start(_ *cobra.Command, _ []string) error { return err } if cfg.TestTssKeysign { - err = TestTSS(tss.CurrentPubkey, *tss.Server, masterLogger) + err = mc.TestTSS(tss.CurrentPubkey, *tss.Server, masterLogger) if err != nil { startLogger.Error().Err(err).Msgf("TestTSS error : %s", tss.CurrentPubkey) } diff --git a/cmd/zetaclientd/start_utils.go b/cmd/zetaclientd/start_utils.go deleted file mode 100644 index df80814bb8..0000000000 --- a/cmd/zetaclientd/start_utils.go +++ /dev/null @@ -1,53 +0,0 @@ -package main - -import ( - "fmt" - "net" - "strings" - "time" - - "github.com/pkg/errors" - "github.com/rs/zerolog" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - "github.com/zeta-chain/node/zetaclient/config" -) - -func waitForZetaCore(config config.Config, logger zerolog.Logger) { - // wait until zetacore is up - logger.Debug().Msg("Waiting for zetacore to open 9090 port...") - for { - _, err := grpc.Dial( - fmt.Sprintf("%s:9090", config.ZetaCoreURL), - grpc.WithTransportCredentials(insecure.NewCredentials()), - ) - if err != nil { - logger.Warn().Err(err).Msg("grpc dial fail") - time.Sleep(5 * time.Second) - } else { - break - } - } -} - -func validatePeer(seedPeer string) error { - parsedPeer := strings.Split(seedPeer, "/") - - if len(parsedPeer) < 7 { - return errors.New("seed peer missing IP or ID or both, seed: " + seedPeer) - } - - seedIP := parsedPeer[2] - seedID := parsedPeer[6] - - if net.ParseIP(seedIP) == nil { - return errors.New("invalid seed IP address format, seed: " + seedPeer) - } - - if len(seedID) == 0 { - return errors.New("seed id is empty, seed: " + seedPeer) - } - - return nil -} diff --git a/cmd/zetaclientd/tss.go b/cmd/zetaclientd/tss.go new file mode 100644 index 0000000000..cf16131100 --- /dev/null +++ b/cmd/zetaclientd/tss.go @@ -0,0 +1,69 @@ +package main + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "time" + + "github.com/bnb-chain/tss-lib/ecdsa/keygen" + "github.com/pkg/errors" + "github.com/spf13/cobra" + + "github.com/zeta-chain/node/pkg/crypto" +) + +// TSSEncryptFile encrypts the given file with the given secret key +func TSSEncryptFile(_ *cobra.Command, args []string) error { + var ( + filePath = filepath.Clean(args[0]) + password = args[1] + ) + + // #nosec G304 -- this is a config file + data, err := os.ReadFile(filePath) + if err != nil { + return err + } + + if !json.Valid(data) { + return fmt.Errorf("file %s is not a valid json, may already be encrypted", filePath) + } + + // encrypt the data + cipherText, err := crypto.EncryptAES256GCM(data, password) + if err != nil { + return errors.Wrap(err, "failed to encrypt data") + } + + if err := os.WriteFile(filePath, cipherText, 0o600); err != nil { + return errors.Wrap(err, "failed to write encrypted data to file") + } + + fmt.Printf("File %s successfully encrypted\n", filePath) + + return nil +} + +func TSSGeneratePreParams(_ *cobra.Command, args []string) error { + startTime := time.Now() + preParams, err := keygen.GeneratePreParams(time.Second * 300) + if err != nil { + return err + } + + file, err := os.OpenFile(args[0], os.O_RDWR|os.O_CREATE, 0600) + if err != nil { + return err + } + defer file.Close() + + if err = json.NewEncoder(file).Encode(preParams); err != nil { + return err + } + + fmt.Printf("Generated new pre-parameters in %s\n", time.Since(startTime).String()) + + return nil +} diff --git a/cmd/zetaclientd/utils.go b/cmd/zetaclientd/utils.go index 35fa41f950..011a1bc0ab 100644 --- a/cmd/zetaclientd/utils.go +++ b/cmd/zetaclientd/utils.go @@ -1,8 +1,16 @@ package main import ( + "fmt" + "net" + "strings" + "time" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pkg/errors" "github.com/rs/zerolog" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" "github.com/zeta-chain/node/zetaclient/authz" "github.com/zeta-chain/node/zetaclient/config" @@ -10,31 +18,76 @@ import ( "github.com/zeta-chain/node/zetaclient/zetacore" ) -func CreateAuthzSigner(granter string, grantee sdk.AccAddress) { +func createAuthzSigner(granter string, grantee sdk.AccAddress) { authz.SetupAuthZSignerList(granter, grantee) } -func CreateZetacoreClient(cfg config.Config, hotkeyPassword string, logger zerolog.Logger) (*zetacore.Client, error) { +func createZetacoreClient(cfg config.Config, hotkeyPassword string, logger zerolog.Logger) (*zetacore.Client, error) { hotKey := cfg.AuthzHotkey chainIP := cfg.ZetaCoreURL kb, _, err := keys.GetKeyringKeybase(cfg, hotkeyPassword) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to get keyring base") } - granterAddreess, err := sdk.AccAddressFromBech32(cfg.AuthzGranter) + granterAddress, err := sdk.AccAddressFromBech32(cfg.AuthzGranter) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to get granter address") } - k := keys.NewKeysWithKeybase(kb, granterAddreess, cfg.AuthzHotkey, hotkeyPassword) + k := keys.NewKeysWithKeybase(kb, granterAddress, cfg.AuthzHotkey, hotkeyPassword) client, err := zetacore.NewClient(k, chainIP, hotKey, cfg.ChainID, logger) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to create zetacore client") } return client, nil } + +func waitForZetaCore(config config.Config, logger zerolog.Logger) { + const ( + port = 9090 + retry = 5 * time.Second + ) + + var ( + url = fmt.Sprintf("%s:%d", config.ZetaCoreURL, port) + opt = grpc.WithTransportCredentials(insecure.NewCredentials()) + ) + + // wait until zetacore is up + logger.Debug().Msgf("Waiting for zetacore to open %d port...", port) + + for { + if _, err := grpc.Dial(url, opt); err != nil { + logger.Warn().Err(err).Msg("grpc dial fail") + time.Sleep(retry) + } else { + break + } + } +} + +func validatePeer(seedPeer string) error { + parsedPeer := strings.Split(seedPeer, "/") + + if len(parsedPeer) < 7 { + return errors.New("seed peer missing IP or ID or both, seed: " + seedPeer) + } + + seedIP := parsedPeer[2] + seedID := parsedPeer[6] + + if net.ParseIP(seedIP) == nil { + return errors.New("invalid seed IP address format, seed: " + seedPeer) + } + + if len(seedID) == 0 { + return errors.New("seed id is empty, seed: " + seedPeer) + } + + return nil +} diff --git a/cmd/zetaclientd/version.go b/cmd/zetaclientd/version.go deleted file mode 100644 index cadba46095..0000000000 --- a/cmd/zetaclientd/version.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/zeta-chain/node/pkg/constant" -) - -var VersionCmd = &cobra.Command{ - Use: "version", - Short: "version description from git describe --tags", - RunE: Version, -} - -func Version(_ *cobra.Command, _ []string) error { - fmt.Print(constant.Version) - return nil -} diff --git a/contrib/localnet/scripts/start-zetaclientd.sh b/contrib/localnet/scripts/start-zetaclientd.sh index e403e2d599..93fa5c2af6 100755 --- a/contrib/localnet/scripts/start-zetaclientd.sh +++ b/contrib/localnet/scripts/start-zetaclientd.sh @@ -20,7 +20,7 @@ import_relayer_key() { # import solana (network=7) relayer private key privkey_solana=$(yq -r ".observer_relayer_accounts.relayer_accounts[${num}].solana_private_key" /root/config.yml) - zetaclientd import-relayer-key --network=7 --private-key="$privkey_solana" --password=pass_relayerkey + zetaclientd relayer import-key --network=7 --private-key="$privkey_solana" --password=pass_relayerkey } PREPARAMS_PATH="/root/preparams/${HOSTNAME}.json" diff --git a/zetaclient/config/types.go b/zetaclient/config/types.go index 6b666a8081..d3a1e4b3a0 100644 --- a/zetaclient/config/types.go +++ b/zetaclient/config/types.go @@ -23,8 +23,10 @@ const ( // KeyringBackendFile is the file Cosmos keyring backend KeyringBackendFile KeyringBackend = "file" + DefaultRelayerDir = "relayer-keys" + // DefaultRelayerKeyPath is the default path that relayer keys are stored - DefaultRelayerKeyPath = "~/.zetacored/relayer-keys" + DefaultRelayerKeyPath = "~/.zetacored/" + DefaultRelayerDir ) // ClientConfiguration is a subset of zetaclient config that is used by zetacore client diff --git a/cmd/zetaclientd/keygen_tss.go b/zetaclient/tss/generate.go similarity index 97% rename from cmd/zetaclientd/keygen_tss.go rename to zetaclient/tss/generate.go index 9928a9436c..5334212332 100644 --- a/cmd/zetaclientd/keygen_tss.go +++ b/zetaclient/tss/generate.go @@ -1,4 +1,4 @@ -package main +package tss import ( "context" @@ -19,20 +19,20 @@ import ( "github.com/zeta-chain/node/zetaclient/chains/interfaces" zctx "github.com/zeta-chain/node/zetaclient/context" "github.com/zeta-chain/node/zetaclient/metrics" - mc "github.com/zeta-chain/node/zetaclient/tss" "github.com/zeta-chain/node/zetaclient/zetacore" ) -// GenerateTSS generates a new TSS if keygen is set. +// Generate generates a new TSS if keygen is set. // If a TSS was generated successfully in the past,and the keygen was successful, the function will return without doing anything. // If a keygen has been set the functions will wait for the correct block to arrive and generate a new TSS. // In case of a successful keygen a TSS success vote is broadcasted to zetacore and the newly generate TSS is tested. The generated keyshares are stored in the correct directory // In case of a failed keygen a TSS failed vote is broadcasted to zetacore. -func GenerateTSS( +func Generate( ctx context.Context, logger zerolog.Logger, zetaCoreClient *zetacore.Client, - keygenTssServer *tss.TssServer) error { + keygenTssServer *tss.TssServer, +) error { keygenLogger := logger.With().Str("module", "keygen").Logger() app, err := zctx.FromContext(ctx) if err != nil { @@ -176,7 +176,7 @@ func TestTSS(pubkey string, tssServer tss.TssServer, logger zerolog.Logger) erro keygenLogger := logger.With().Str("module", "test-keygen").Logger() keygenLogger.Info().Msgf("KeyGen success ! Doing a Key-sign test") // KeySign can fail even if TSS keygen is successful, just logging the error here to break out of outer loop and report TSS - err := mc.TestKeysign(pubkey, tssServer) + err := TestKeysign(pubkey, tssServer) if err != nil { return err } diff --git a/zetaclient/tss/tss_signer.go b/zetaclient/tss/tss_signer.go index e3df81d7ad..83ff502f4a 100644 --- a/zetaclient/tss/tss_signer.go +++ b/zetaclient/tss/tss_signer.go @@ -1,4 +1,6 @@ // Package tss provides the TSS signer functionalities for the zetaclient to sign transactions on external chains +// TODO revamp the whole package +// https://github.com/zeta-chain/node/issues/3119 package tss import ( @@ -85,8 +87,8 @@ type TSS struct { KeysignsTracker *ConcurrentKeysignsTracker } -// NewTSS creates a new TSS instance which can be used to sign transactions -func NewTSS( +// New TSS constructor +func New( ctx context.Context, client interfaces.ZetacoreClient, tssHistoricalList []observertypes.TSS,