Skip to content

Commit

Permalink
cmd/geth: standardize the action of importing bls account
Browse files Browse the repository at this point in the history
  • Loading branch information
buddh0 committed Nov 30, 2023
1 parent 1edb34f commit 9d0a116
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 70 deletions.
116 changes: 49 additions & 67 deletions cmd/geth/blsaccountcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (

"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/signer/core"
)

Expand All @@ -35,19 +36,16 @@ const (
)

var (
au = aurora.NewAurora(true)
privateKeyFlag = &cli.StringFlag{
Name: "private-key",
Usage: "Hex string for the BLS12-381 private key you wish encrypt into a keystore file",
Value: "",
}
au = aurora.NewAurora(true)
showPrivateKeyFlag = &cli.BoolFlag{
Name: "show-private-key",
Usage: "Show the BLS12-381 private key you will encrypt into a keystore file",
Name: "show-private-key",
Usage: "Show the BLS12-381 private key you will encrypt into a keystore file",
Category: flags.AccountCategory,
}
BLSAccountPasswordFileFlag = &cli.StringFlag{
Name: "blsaccountpassword",
Usage: "File path for the BLS account password, which contains the password to encrypt private key into keystore file for managing votes in fast_finality feature",
bLSAccountPasswordFileFlag = &cli.StringFlag{
Name: "blsaccountpassword",
Usage: "File path for the BLS account password, which contains the password to encrypt private key into keystore file for managing votes in fast_finality feature",
Category: flags.AccountCategory,
}
)

Expand Down Expand Up @@ -130,10 +128,9 @@ Make sure you backup your BLS keys regularly.`,
Category: "BLS ACCOUNT COMMANDS",
Flags: []cli.Flag{
utils.DataDirFlag,
privateKeyFlag,
showPrivateKeyFlag,
utils.BLSPasswordFileFlag,
BLSAccountPasswordFileFlag,
bLSAccountPasswordFileFlag,
},
Description: `
geth bls account new
Expand All @@ -149,17 +146,17 @@ You must remember this password to unlock your account in the future.`,
Name: "import",
Usage: "Import a BLS account",
Action: blsAccountImport,
ArgsUsage: "<keystore file>",
ArgsUsage: "<keyFile>",
Category: "BLS ACCOUNT COMMANDS",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.BLSPasswordFileFlag,
BLSAccountPasswordFileFlag,
bLSAccountPasswordFileFlag,
},
Description: `
geth bls account import <keyFile>
Import a encrypted BLS account from keystore file <keyFile> into the BLS wallet.
Import a encrypted BLS account or a BLS12-381 private key from file <keyFile> into the BLS wallet.
If the BLS wallet not created yet, it will try to create BLS wallet first.`,
},
Expand Down Expand Up @@ -219,8 +216,7 @@ func blsWalletCreate(ctx *cli.Context) error {
utils.Fatalf("BLS wallet already exists in <DATADIR>/bls/wallet.")
}

password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, GetBLSPassword(ctx))

password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
opts := []accounts.Option{}
opts = append(opts, accounts.WithWalletDir(dir))
opts = append(opts, accounts.WithWalletPassword(password))
Expand Down Expand Up @@ -249,8 +245,7 @@ func openOrCreateBLSWallet(ctx *cli.Context, cfg *gethConfig) (*wallet.Wallet, e
}
if !dirExists {
fmt.Println("BLS wallet not exists, creating BLS wallet...")
password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, GetBLSPassword(ctx))

password := utils.GetPassPhraseWithList("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
opts := []accounts.Option{}
opts = append(opts, accounts.WithWalletDir(walletDir))
opts = append(opts, accounts.WithWalletPassword(password))
Expand All @@ -269,7 +264,7 @@ func openOrCreateBLSWallet(ctx *cli.Context, cfg *gethConfig) (*wallet.Wallet, e
return w, nil
}

walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, GetBLSPassword(ctx))
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
w, err = wallet.OpenWallet(context.Background(), &wallet.Config{
WalletDir: walletDir,
WalletPassword: walletPassword,
Expand Down Expand Up @@ -309,27 +304,14 @@ func blsAccountCreate(ctx *cli.Context) error {
if err := os.MkdirAll(keystoreDir, 0755); err != nil {
utils.Fatalf("Could not access keystore dir: %v.", err)
}
accountPassword := utils.GetPassPhraseWithList("Your new BLS account will be encrypted with a password. Please give a password. Do not forget this password.", true, 0, GetBLSAccountPassword(ctx))
accountPassword := utils.GetPassPhraseWithList("Your new BLS account will be encrypted with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordListFromPath(ctx.String(bLSAccountPasswordFileFlag.Name)))
if err := core.ValidatePasswordFormat(accountPassword); err != nil {
utils.Fatalf("Password invalid: %v.", err)
}

encryptor := keystorev4.New()
secretKey, err := bls.RandKey()
privateKeyString := ctx.String(privateKeyFlag.Name)
if privateKeyString != "" {
if len(privateKeyString) > 2 && strings.Contains(privateKeyString, "0x") {
privateKeyString = privateKeyString[2:] // Strip the 0x prefix, if any.
}
bytesValue, err := hex.DecodeString(privateKeyString)
if err != nil {
utils.Fatalf("could not decode as hex string: %s", privateKeyString)
}
secretKey, err = bls.SecretKeyFromBytes(bytesValue)
if err != nil {
utils.Fatalf("not a valid BLS12-381 private key")
}
} else if err != nil {
if err != nil {
utils.Fatalf("Could not generate BLS secret key: %v.", err)
}

Expand Down Expand Up @@ -387,13 +369,35 @@ func blsAccountImport(ctx *cli.Context) error {
if len(keyfile) == 0 {
utils.Fatalf("The keystore file must be given as argument.")
}
keyJSON, err := os.ReadFile(keyfile)
keyInfo, err := os.ReadFile(keyfile)
if err != nil {
utils.Fatalf("Could not read keystore file: %v", err)
}
keystore := &keymanager.Keystore{}
if err := json.Unmarshal(keyJSON, keystore); err != nil {
utils.Fatalf("Could not decode keystore file: %v.", err)
var accountPassword string
if err := json.Unmarshal(keyInfo, keystore); err != nil {
secretKey, err := bls.SecretKeyFromBytes(common.FromHex(strings.TrimRight(string(keyInfo), "\r\n")))
if err != nil {
utils.Fatalf("keyFile is neither a keystore file or include a valid BLS12-381 private key: %v.", err)
}
pubKeyBytes := secretKey.PublicKey().Marshal()
encryptor := keystorev4.New()
accountPassword = "1234567890" // no security issue, it's only used to create keystore in memory from secretKey.
cryptoFields, err := encryptor.Encrypt(secretKey.Marshal(), accountPassword)
if err != nil {
utils.Fatalf("Could not encrypt secret key: %v.", err)
}
id, err := uuid.NewRandom()
if err != nil {
utils.Fatalf("Could not generate uuid: %v.", err)
}
keystore = &keymanager.Keystore{
Crypto: cryptoFields,
ID: id.String(),
Pubkey: fmt.Sprintf("%x", pubKeyBytes),
Version: encryptor.Version(),
Name: encryptor.Name(),
}
}
if keystore.Pubkey == "" {
utils.Fatalf(" Missing public key, wrong keystore file.")
Expand Down Expand Up @@ -421,13 +425,15 @@ func blsAccountImport(ctx *cli.Context) error {
utils.Fatalf("The BLS keymanager cannot import keystores")
}

password := utils.GetPassPhraseWithList("Enter the password for your imported account.", false, 0, GetBLSAccountPassword(ctx))
if accountPassword == "" {
accountPassword = utils.GetPassPhraseWithList("Enter the password for your imported account.", false, 0, utils.MakePasswordListFromPath(ctx.String(bLSAccountPasswordFileFlag.Name)))
}

fmt.Println("Importing BLS account, this may take a while...")
statuses, err := accounts.ImportAccounts(context.Background(), &accounts.ImportAccountsConfig{
Importer: k,
Keystores: []*keymanager.Keystore{keystore},
AccountPassword: password,
AccountPassword: accountPassword,
})
if err != nil {
utils.Fatalf("Import BLS account failed: %v.", err)
Expand Down Expand Up @@ -458,7 +464,7 @@ func blsAccountList(ctx *cli.Context) error {
utils.Fatalf("BLS wallet not exists.")
}

walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, GetBLSPassword(ctx))
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
WalletDir: walletDir,
WalletPassword: walletPassword,
Expand Down Expand Up @@ -537,7 +543,7 @@ func blsAccountDelete(ctx *cli.Context) error {
utils.Fatalf("BLS wallet not exists.")
}

walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, GetBLSPassword(ctx))
walletPassword := utils.GetPassPhraseWithList("Enter the password for your BLS wallet.", false, 0, utils.MakePasswordListFromPath(ctx.String(utils.BLSPasswordFileFlag.Name)))
w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
WalletDir: walletDir,
WalletPassword: walletPassword,
Expand Down Expand Up @@ -598,27 +604,3 @@ func blsAccountDelete(ctx *cli.Context) error {

return nil
}

func GetBLSPassword(ctx *cli.Context) []string {
path := ctx.String(utils.BLSPasswordFileFlag.Name)
if path == "" {
return nil
}
text, err := os.ReadFile(path)
if err != nil {
utils.Fatalf("Failed to read wallet password file: %v", err)
}
return []string{string(text)}
}

func GetBLSAccountPassword(ctx *cli.Context) []string {
path := ctx.String(BLSAccountPasswordFileFlag.Name)
if path == "" {
return nil
}
text, err := os.ReadFile(path)
if err != nil {
utils.Fatalf("Failed to read account password file: %v", err)
}
return []string{string(text)}
}
33 changes: 33 additions & 0 deletions cmd/geth/testdata/bls-account-usage-demo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash

echo "0. prepare---------------------------------------------------------------------------------\n\n"
echo 123abc >bls-password.txt
echo 123abc7890 > bls-account-password.txt
basedir=$(cd `dirname $0`; pwd)
workspace=${basedir}/../../../

echo "1. create a bls account--------------------------------------------------------------------\n\n"
${workspace}/build/bin/geth bls account new --blsaccountpassword ./bls-account-password.txt --blspassword ./bls-password.txt --datadir ./bls
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls

echo "2. import a bls account by passing file including a private key-----------------------------\n\n"
secretKey=`${workspace}/build/bin/geth bls account new --show-private-key --blsaccountpassword ./bls-account-password.txt --blspassword ./bls-password.txt --datadir ./bls1 | grep private | awk '{print $NF}'`
echo ${secretKey} > ./bls1/secretKey
${workspace}/build/bin/geth bls account import --blspassword ./bls-password.txt --datadir ./bls ./bls1/secretKey
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls

echo "3. delete the imported account above--------------------------------------------------------\n\n"
publicKey=`${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls |grep public | tail -1 | awk '{print $NF}'`
${workspace}/build/bin/geth bls account delete --blspassword ./bls-password.txt --datadir ./bls ${publicKey}
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls

echo "4. import a bls account by passing a keystore file------------------------------------------\n\n"
keystoreFile=`ls bls1/bls/keystore`
${workspace}/build/bin/geth bls account import --blsaccountpassword ./bls-account-password.txt --blspassword ./bls-password.txt --datadir ./bls ./bls1/bls/keystore/${keystoreFile}
${workspace}/build/bin/geth bls account list --blspassword ./bls-password.txt --datadir ./bls

echo "5. clearup----------------------------------------------------------------------------------\n\n"
rm -rf bls
rm -rf bls1
rm -rf bls-password.txt
rm -rf bls-account-password.txt
9 changes: 6 additions & 3 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1093,13 +1093,13 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
BLSPasswordFileFlag = &cli.StringFlag{
Name: "blspassword",
Usage: "File path for the BLS password, which contains the password to unlock BLS wallet for managing votes in fast_finality feature",
Category: flags.FastFinalityCategory,
Category: flags.AccountCategory,
}

BLSWalletDirFlag = &flags.DirectoryFlag{
Name: "blswallet",
Usage: "Path for the blsWallet dir in fast finality feature (default = inside the datadir)",
Category: flags.FastFinalityCategory,
Category: flags.AccountCategory,
}

VoteJournalDirFlag = &flags.DirectoryFlag{
Expand Down Expand Up @@ -1462,7 +1462,10 @@ func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {

// MakePasswordList reads password lines from the file specified by the global --password flag.
func MakePasswordList(ctx *cli.Context) []string {
path := ctx.Path(PasswordFileFlag.Name)
return MakePasswordListFromPath(ctx.Path(PasswordFileFlag.Name))
}

func MakePasswordListFromPath(path string) []string {
if path == "" {
return nil
}
Expand Down

0 comments on commit 9d0a116

Please sign in to comment.