diff --git a/cmd/root.go b/cmd/root.go index d45b2636..7a78d616 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,16 +3,19 @@ package cmd import ( "encoding/json" "fmt" - "io/ioutil" + "io" "os" "path/filepath" "github.com/0chain/gosdk/core/conf" "github.com/0chain/gosdk/core/logger" + "github.com/0chain/gosdk/core/sys" "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/0chain/gosdk/zboxcore/blockchain" + "github.com/0chain/gosdk/zboxcore/client" "github.com/0chain/zboxcli/util" "github.com/0chain/gosdk/core/zcncrypto" @@ -24,13 +27,15 @@ import ( var cfgFile string var networkFile string var walletFile string +var walletFilePath string var walletClientID string var walletClientKey string var cDir string var nonce int64 -var txFee float64 +var gTxnFee float64 var bSilent bool var allocUnderRepair bool +var gConfig *viper.Viper var walletJSON string @@ -56,7 +61,7 @@ func init() { rootCmd.PersistentFlags().Int64Var(&nonce, "withNonce", 0, "nonce that will be used in transaction (default is 0)") rootCmd.PersistentFlags().StringVar(&cDir, "configDir", "", "configuration directory (default is $HOME/.zcn)") rootCmd.PersistentFlags().BoolVar(&bSilent, "silent", false, "(default false) Do not show interactive sdk logs (shown by default)") - rootCmd.PersistentFlags().Float64Var(&txFee, "fee", 0, "transaction fee for the given transaction (if unset, it will be set to blockchain min fee)") + rootCmd.PersistentFlags().Float64Var(&gTxnFee, "fee", 0, "transaction fee for the given transaction (if unset, it will be set to blockchain min fee)") } func Execute() { @@ -68,18 +73,24 @@ func Execute() { } func initConfig() { - - configDir := util.SetConfigDir(cDir) - if cfgFile == "" { cfgFile = "config.yaml" } - cfg, err := conf.LoadConfigFile(filepath.Join(configDir, cfgFile)) + + var ( + configDir = util.SetConfigDir(cDir) + cfg conf.Config + err error + ) + + cfg, err = conf.LoadConfigFile(filepath.Join(configDir, cfgFile)) if err != nil { fmt.Println("Can't read config:", err) os.Exit(1) } + gConfig = cfg.V + if networkFile == "" { networkFile = "network.yaml" } @@ -101,83 +112,29 @@ func initConfig() { }) } + clientWallet = loadWallet(configDir) + if cfg.ZauthServer != "" { + sys.SetAuthorize(zcncore.ZauthSignTxn(cfg.ZauthServer)) + sys.AuthCommon = zcncore.ZauthAuthCommon(cfg.ZauthServer) + sys.SignWithAuth = zcncore.ZauthSignMsg(cfg.ZauthServer) + client.SetClient(clientWallet, cfg.SignatureScheme, getTxnFee()) + if err := zcncore.SetWallet(*clientWallet, clientWallet.IsSplit); err != nil { + fmt.Println("Error setting wallet", err) + os.Exit(1) + } + } + err = zcncore.InitZCNSDK(cfg.BlockWorker, cfg.SignatureScheme, zcncore.WithChainID(cfg.ChainID), zcncore.WithMinSubmit(cfg.MinSubmit), zcncore.WithMinConfirmation(cfg.MinConfirmation), - zcncore.WithConfirmationChainLength(cfg.ConfirmationChainLength)) + zcncore.WithConfirmationChainLength(cfg.ConfirmationChainLength), + zcncore.WithIsSplitWallet(clientWallet.IsSplit)) if err != nil { fmt.Println("Error initializing core SDK.", err) os.Exit(1) } - // is freshly created wallet? - //var fresh bool - - wallet := &zcncrypto.Wallet{} - if (&walletClientID != nil) && (len(walletClientID) > 0) && (&walletClientKey != nil) && (len(walletClientKey) > 0) { - wallet.ClientID = walletClientID - wallet.ClientKey = walletClientKey - var clientBytes []byte - - clientBytes, err = json.Marshal(wallet) - walletJSON = string(clientBytes) - if err != nil { - fmt.Println("Invalid wallet data passed:" + walletClientID + " " + walletClientKey) - os.Exit(1) - } - clientWallet = wallet - //fresh = false - } else { - var walletFilePath string - if &walletFile != nil && len(walletFile) > 0 { - if filepath.IsAbs(walletFile) { - walletFilePath = walletFile - } else { - walletFilePath = configDir + string(os.PathSeparator) + walletFile - } - } else { - walletFilePath = configDir + string(os.PathSeparator) + "wallet.json" - } - - if _, err = os.Stat(walletFilePath); os.IsNotExist(err) { - wallet, err := zcncore.CreateWalletOffline() - if err != nil { - fmt.Println(err.Error()) - os.Exit(1) - } - fmt.Println("ZCN wallet created") - walletJSON = wallet - file, err := os.Create(walletFilePath) - if err != nil { - fmt.Println(err.Error()) - os.Exit(1) - } - defer file.Close() - fmt.Fprint(file, walletJSON) - } else { - f, err := os.Open(walletFilePath) - if err != nil { - fmt.Println("Error opening the wallet", err) - os.Exit(1) - } - clientBytes, err := ioutil.ReadAll(f) - if err != nil { - fmt.Println("Error reading the wallet", err) - os.Exit(1) - } - walletJSON = string(clientBytes) - } - //minerjson, _ := json.Marshal(miners) - //sharderjson, _ := json.Marshal(sharders) - err = json.Unmarshal([]byte(walletJSON), wallet) - clientWallet = wallet - if err != nil { - fmt.Println("Invalid wallet at path:" + walletFilePath) - os.Exit(1) - } - } - //init the storage sdk with the known miners, sharders and client wallet info if err = sdk.InitStorageSDK( walletJSON, @@ -186,7 +143,7 @@ func initConfig() { cfg.SignatureScheme, cfg.PreferredBlobbers, nonce, - zcncore.ConvertToValue(txFee), + zcncore.ConvertToValue(gTxnFee), ); err != nil { fmt.Println("Error in sdk init", err) os.Exit(1) @@ -204,3 +161,73 @@ func initConfig() { sdk.SetNumBlockDownloads(10) } + +func loadWallet(configDir string) *zcncrypto.Wallet { + // is freshly created wallet? + //var fresh bool + wallet := &zcncrypto.Wallet{} + if (&walletClientID != nil) && (len(walletClientID) > 0) && (&walletClientKey != nil) && (len(walletClientKey) > 0) { + wallet.ClientID = walletClientID + wallet.ClientKey = walletClientKey + var clientBytes []byte + + clientBytes, err := json.Marshal(wallet) + walletJSON = string(clientBytes) + if err != nil { + fmt.Println("Invalid wallet data passed:" + walletClientID + " " + walletClientKey) + os.Exit(1) + } + return wallet + } + + if &walletFile != nil && len(walletFile) > 0 { + if filepath.IsAbs(walletFile) { + walletFilePath = walletFile + } else { + walletFilePath = configDir + string(os.PathSeparator) + walletFile + } + } else { + walletFilePath = configDir + string(os.PathSeparator) + "wallet.json" + } + + if _, err := os.Stat(walletFilePath); os.IsNotExist(err) { + wallet, err := zcncore.CreateWalletOffline() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + fmt.Println("ZCN wallet created") + walletJSON = wallet + file, err := os.Create(walletFilePath) + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + defer file.Close() + fmt.Fprint(file, walletJSON) + } else { + f, err := os.Open(walletFilePath) + if err != nil { + fmt.Println("Error opening the wallet", err) + os.Exit(1) + } + clientBytes, err := io.ReadAll(f) + if err != nil { + fmt.Println("Error reading the wallet", err) + os.Exit(1) + } + walletJSON = string(clientBytes) + } + //minerjson, _ := json.Marshal(miners) + //sharderjson, _ := json.Marshal(sharders) + err := json.Unmarshal([]byte(walletJSON), wallet) + if err != nil { + fmt.Println("Invalid wallet at path:" + walletFilePath) + os.Exit(1) + } + return wallet +} + +func getTxnFee() uint64 { + return zcncore.ConvertToValue(gTxnFee) +} diff --git a/cmd/zauth.go b/cmd/zauth.go new file mode 100644 index 00000000..d8dc6bb1 --- /dev/null +++ b/cmd/zauth.go @@ -0,0 +1,72 @@ +package cmd + +import ( + "log" + + "github.com/0chain/gosdk/zcncore" + "github.com/spf13/cobra" +) + +var zauthCmd = &cobra.Command{ + Use: "zauth", + Short: "Enable zauth", + Long: `Enable zauth to sign transactions and messages, setup split keys and configure the zauth service.`, + Run: func(cmd *cobra.Command, args []string) { + // Add your code here + serverAddr, err := cmd.Flags().GetString("server") + if err != nil { + log.Fatalf("Could not find zauth server address") + } + + token, err := cmd.Flags().GetString("token") + if err != nil { + log.Fatalf("Could not find zauth access token") + } + + // update or setup the zauth server address + gConfig.Set("zauth.server", serverAddr) + if err := gConfig.WriteConfig(); err != nil { + log.Fatalf("Could not save config: %v", err) + } + + if clientWallet == nil { + log.Fatalf("Wallet is initialized yet") + } + + if clientWallet.IsSplit { + log.Fatalln("Wallet is already split") + } + + sw, err := zcncore.SplitKeysWallet(clientWallet.Keys[0].PrivateKey, 2) + if err != nil { + log.Fatalf("Failed to split keys: %v", err) + } + + if err := zcncore.CallZauthSetup(serverAddr, token, zcncore.SplitWallet{ + ClientID: sw.ClientID, + ClientKey: sw.ClientKey, + PublicKey: sw.Keys[1].PublicKey, + PrivateKey: sw.Keys[1].PrivateKey, + PeerPublicKey: sw.Keys[0].PublicKey, + }); err != nil { + log.Fatalf("Failed to setup zauth server: %v", err) + } + + // remove the keys[1] + sw.PeerPublicKey = sw.Keys[1].PublicKey + sw.Keys = sw.Keys[:1] + clientWallet.SetSplitKeys(sw) + if err := clientWallet.SaveTo(walletFilePath); err != nil { + log.Fatalf("Failed to save wallet: %v", err) + } + + log.Printf("Setup zauth server successfully") + }, +} + +func init() { + rootCmd.AddCommand(zauthCmd) + zauthCmd.PersistentFlags().String("server", "s", "The zauth server address") + zauthCmd.PersistentFlags().String("token", "t", "The /setup access token") + zauthCmd.MarkFlagRequired("server") +} diff --git a/go.mod b/go.mod index 736119a7..27a236cf 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/0chain/zboxcli go 1.21 +toolchain go1.21.6 + require ( github.com/0chain/errors v1.0.3 github.com/0chain/gosdk v1.14.0-RC1.0.20240414202040-32b307adbe91 @@ -9,6 +11,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/cobra v1.6.0 github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.15.0 gopkg.in/cheggaaa/pb.v1 v1.0.28 ) @@ -54,7 +57,6 @@ require ( github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/viper v1.15.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/tinylib/msgp v1.1.6 // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect @@ -79,4 +81,4 @@ require ( ) // temporary, for development -// replace github.com/0chain/gosdk => ../gosdk +replace github.com/0chain/gosdk => ../gosdk diff --git a/go.sum b/go.sum index 89439ecd..8cbd946e 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,6 @@ github.com/0chain/common v0.0.6-0.20230127095721-8df4d1d72565 h1:z+DtCR8mBsjPnEs github.com/0chain/common v0.0.6-0.20230127095721-8df4d1d72565/go.mod h1:UyDC8Qyl5z9lGkCnf9RHJPMektnFX8XtCJZHXCCVj8E= github.com/0chain/errors v1.0.3 h1:QQZPFxTfnMcRdt32DXbzRQIfGWmBsKoEdszKQDb0rRM= github.com/0chain/errors v1.0.3/go.mod h1:xymD6nVgrbgttWwkpSCfLLEJbFO6iHGQwk/yeSuYkIc= -github.com/0chain/gosdk v1.14.0-RC1.0.20240414202040-32b307adbe91 h1:rD4PsszAOb/TFeJwmz8pUmoQP54tbZOiE0AiQR/8yFk= -github.com/0chain/gosdk v1.14.0-RC1.0.20240414202040-32b307adbe91/go.mod h1:tgAiVAuIy+Vs1tGfKCPEuuWWARwNQBEw32y950LrqrU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Luzifer/go-openssl/v3 v3.1.0 h1:QqKqo6kYXGGUsvtUoCpRZm8lHw+jDfhbzr36gVj+/gw=