-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add export key command * fix lint * make it less comlicated * add test for filename * fix lint
- Loading branch information
1 parent
9a4201b
commit b77e55e
Showing
4 changed files
with
197 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package keys | ||
|
||
import ( | ||
"encoding/hex" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils" | ||
"github.com/Layr-Labs/eigensdk-go/crypto/bls" | ||
"github.com/Layr-Labs/eigensdk-go/crypto/ecdsa" | ||
"github.com/urfave/cli/v2" | ||
) | ||
|
||
func ExportCmd(p utils.Prompter) *cli.Command { | ||
exportCmd := &cli.Command{ | ||
Name: "export", | ||
Usage: "Used to export existing keys from local keystore", | ||
UsageText: "export --key-type <key-type> [flags] [keyname]", | ||
Description: `Used to export ecdsa and bls key from local keystore | ||
keyname - This will be the name of the key to be imported. If the path of keys is | ||
different from default path created by "create"/"import" command, then provide the | ||
full path using --key-path flag. | ||
If both keyname is provided and --key-path flag is provided, then keyname will be used. | ||
use --key-type ecdsa/bls to export ecdsa/bls key. | ||
- ecdsa - exported key should be plaintext hex encoded private key | ||
- bls - exported key should be plaintext bls private key | ||
It will prompt for password to encrypt the key. | ||
This command will import keys from $HOME/.eigenlayer/operator_keys/ location | ||
But if you want it to export from a different location, use --key-path flag`, | ||
|
||
Flags: []cli.Flag{ | ||
&KeyTypeFlag, | ||
&KeyPathFlag, | ||
}, | ||
Action: func(c *cli.Context) error { | ||
keyType := c.String(KeyTypeFlag.Name) | ||
|
||
keyName := c.Args().Get(0) | ||
if err := validateKeyName(keyName); err != nil { | ||
return err | ||
} | ||
|
||
keyPath := c.String(KeyPathFlag.Name) | ||
if len(keyPath) == 0 && len(keyName) == 0 { | ||
return errors.New("one of keyname or --key-path is required") | ||
} | ||
|
||
if len(keyPath) > 0 && len(keyName) > 0 { | ||
return errors.New("keyname and --key-path both are provided. Please provide only one") | ||
} | ||
|
||
filePath, err := getKeyPath(keyPath, keyName, keyType) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
confirm, err := p.Confirm("This will show your private key. Are you sure you want to export?") | ||
if err != nil { | ||
return err | ||
} | ||
if !confirm { | ||
return nil | ||
} | ||
|
||
password, err := p.InputHiddenString("Enter password to decrypt the key", "", func(s string) error { | ||
return nil | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Println("exporting key from: ", filePath) | ||
|
||
privateKey, err := getPrivateKey(keyType, filePath, password) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Println("Private key: ", privateKey) | ||
return nil | ||
}, | ||
} | ||
|
||
return exportCmd | ||
} | ||
|
||
func getPrivateKey(keyType string, filePath string, password string) (string, error) { | ||
switch keyType { | ||
case KeyTypeECDSA: | ||
key, err := ecdsa.ReadKey(filePath, password) | ||
if err != nil { | ||
return "", err | ||
} | ||
return hex.EncodeToString(key.D.Bytes()), nil | ||
case KeyTypeBLS: | ||
key, err := bls.ReadPrivateKeyFromFile(filePath, password) | ||
if err != nil { | ||
return "", err | ||
} | ||
return key.PrivKey.String(), nil | ||
default: | ||
return "", ErrInvalidKeyType | ||
} | ||
} | ||
|
||
func getKeyPath(keyPath string, keyName string, keyType string) (string, error) { | ||
homePath, err := os.UserHomeDir() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
var filePath string | ||
if len(keyName) > 0 { | ||
switch keyType { | ||
case KeyTypeECDSA: | ||
filePath = filepath.Join(homePath, OperatorKeystoreSubFolder, keyName+".ecdsa.key.json") | ||
case KeyTypeBLS: | ||
filePath = filepath.Join(homePath, OperatorKeystoreSubFolder, keyName+".bls.key.json") | ||
default: | ||
return "", ErrInvalidKeyType | ||
} | ||
|
||
} else { | ||
filePath = filepath.Clean(keyPath) | ||
} | ||
|
||
return filePath, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package keys | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestGetKeyPath(t *testing.T) { | ||
homePath, err := os.UserHomeDir() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
tests := []struct { | ||
name string | ||
keyType string | ||
keyPath string | ||
keyName string | ||
err error | ||
expectedPath string | ||
}{ | ||
{ | ||
name: "correct key path using keyname", | ||
keyType: KeyTypeECDSA, | ||
keyName: "test", | ||
err: nil, | ||
expectedPath: filepath.Join(homePath, OperatorKeystoreSubFolder, "test.ecdsa.key.json"), | ||
}, | ||
{ | ||
name: "correct key path using keypath", | ||
keyType: KeyTypeECDSA, | ||
keyPath: filepath.Join(homePath, "x.json"), | ||
err: nil, | ||
expectedPath: filepath.Join(homePath, "x.json"), | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
path, err := getKeyPath(tt.keyPath, tt.keyName, tt.keyType) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if tt.err != nil { | ||
assert.EqualError(t, err, tt.err.Error()) | ||
} else { | ||
assert.Equal(t, tt.expectedPath, path) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters