Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI auth support #611

Open
wants to merge 4 commits into
base: sprint-1.14
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
179 changes: 103 additions & 76 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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

Expand All @@ -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() {
Expand All @@ -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"
}
Expand All @@ -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,
Expand All @@ -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)
Expand All @@ -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)
}
72 changes: 72 additions & 0 deletions cmd/zauth.go
Original file line number Diff line number Diff line change
@@ -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")
}
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ 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
github.com/icza/bitio v1.1.0
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
)

Expand Down Expand Up @@ -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
Expand All @@ -79,4 +81,4 @@ require (
)

// temporary, for development
// replace github.com/0chain/gosdk => ../gosdk
replace github.com/0chain/gosdk => ../gosdk
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down