Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/operator_cli_build.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
permissions:
contents: read
name: Operator CLI Build
on:
push:
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,12 @@ build: build-oprcli ## Build the oprcli binary
.PHONY: build-oprcli
build-oprcli: check-go ## Build oprcli binary
$(info $(M) Building oprcli binary...)
$Q $(GO) build -o $(BASE_DIR)/bin/oprcli $(SRC_DIR)/main.go
$Q $(GO) build -o $(BASE_DIR)/bin/oprcli $(SRC_DIR)/cmd/main.go

.PHONY: build-oprcli-%
build-oprcli-%: check-go ## Build oprcli binary for a specific platform
$(info $(M) Building oprcli binary for $*...)
$Q GOOS=linux GOARCH=$* $(GO) build -o $(BASE_DIR)/bin/oprcli-$* $(SRC_DIR)/main.go
$Q GOOS=linux GOARCH=$* $(GO) build -o $(BASE_DIR)/bin/oprcli-$* $(SRC_DIR)/cmd/main.go

# --- Docker ---
.PHONY: docker-build
Expand Down
6 changes: 3 additions & 3 deletions build/.goreleaser-operatorcli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ builds:

# Path to the main.go file or the directory containing the main package.
# You can specify multiple paths if your project consists of multiple binaries.
main: ./main.go
main: ./cmd/main.go

# Target platforms
goos:
Expand Down Expand Up @@ -37,10 +37,10 @@ dockers:
- "build"
- "cmd"
- "contracts"
- "internal"
- "go.mod"
- "go.sum"
- "Makefile"
- "main.go"
goos: linux
goarch: amd64
build_flag_templates:
Expand All @@ -59,10 +59,10 @@ dockers:
- "build"
- "cmd"
- "contracts"
- "internal"
- "go.mod"
- "go.sum"
- "Makefile"
- "main.go"
goos: linux
goarch: arm64
build_flag_templates:
Expand Down
1 change: 1 addition & 0 deletions cmd/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v2.0.1
82 changes: 82 additions & 0 deletions cmd/commands/alias_encrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package commands

import (
"context"
"fmt"

"github.com/eodata/operator-cli/cmd/flags"
"github.com/eodata/operator-cli/internal/keystore"
"github.com/ethereum/go-ethereum/crypto"
"github.com/urfave/cli/v3"
)

func NewAliasEcdsaEncryptCommand(ctx context.Context, version string) *cli.Command {
return &cli.Command{
Name: "alias-ecdsa-encrypt",
Description: "Encrypt the ecdsa private key used as operator alias",
Version: version,
HideVersion: true,
Action: runAliasEcdsaEncrypt,
Flags: []cli.Flag{
flags.EcdsaPrivateKeyFlag,
flags.PassphraseFlag,
flags.EcdsaPassphraseFlag,
flags.KeyStorePathFlag,
flags.GenerateKeyPairFlag,
},
}
}

func runAliasEcdsaEncrypt(ctx context.Context, c *cli.Command) error {
logger := flags.Logger

var passphrase string

if c.IsSet(flags.PassphraseFlag.Name) {
passphrase = c.String(flags.PassphraseFlag.Name)
}

if c.IsSet(flags.EcdsaPassphraseFlag.Name) {
if passphrase != "" {
return fmt.Errorf("either common passphrase or specific passphrases should be set")
}
passphrase = c.String(flags.EcdsaPassphraseFlag.Name)
}

if passphrase == "" {
return fmt.Errorf("either common passphrase or specific passphrases should be set")
}

keystorePath := c.String(flags.KeyStorePathFlag.Name)

ecdsaPair, err := crypto.HexToECDSA(c.String(flags.EcdsaPrivateKeyFlag.Name))
if err != nil {
return fmt.Errorf("invalid ECDSA private key %v", err)
}
address := crypto.PubkeyToAddress(ecdsaPair.PublicKey)

_, err = keystore.GetECDSAPrivateKey(passphrase, keystorePath, address.Hex())
if err == nil && !c.Bool(flags.OverrideFlag.Name) {
logger.Info("alias ECDSA private key already exists", "address", address.Hex())
return nil
}

if c.Bool(flags.GenerateKeyPairFlag.Name) {
ecdsaPair, err = keystore.GenerateEcdsaKeyPair()
if err != nil {
return fmt.Errorf("error generating ECDSA key %v", err)
}
}
address = crypto.PubkeyToAddress(ecdsaPair.PublicKey)

if err = keystore.SaveECDSAPrivateKey(passphrase, keystorePath, address.Hex(), ecdsaPair); err != nil {
return fmt.Errorf(
"error writing the alias ecdsa private key to %s file %v",
fmt.Sprintf(keystore.EcdsaEncryptedWallet, address.Hex()),
err,
)
}
logger.Info("alias ecdsa address ", "address", address.Hex())

return nil
}
82 changes: 82 additions & 0 deletions cmd/commands/bls_encrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package commands

import (
"context"
"fmt"

eigensdkbls "github.com/Layr-Labs/eigensdk-go/crypto/bls"
"github.com/eodata/operator-cli/cmd/flags"
"github.com/eodata/operator-cli/internal/keystore"
"github.com/urfave/cli/v3"
)

func NewBlsEncryptCommand(ctx context.Context, version string) *cli.Command {
return &cli.Command{
Name: "bls-encrypt",
Description: "Encrypt the bls private key used as operator alias",
Version: version,
HideVersion: true,
Action: runBlsEncrypt,
Flags: []cli.Flag{
flags.BlsPrivateKeyFlag,
flags.PassphraseFlag,
flags.BlsPassphraseFlag,
flags.KeyStorePathFlag,
flags.OverrideFlag,
flags.GenerateKeyPairFlag,
},
}
}

func runBlsEncrypt(ctx context.Context, c *cli.Command) error {
logger := flags.Logger

var passphrase string
var blsKeyPair *eigensdkbls.KeyPair
var err error

if c.IsSet(flags.PassphraseFlag.Name) {
passphrase = c.String(flags.PassphraseFlag.Name)
}

if c.IsSet(flags.BlsPassphraseFlag.Name) {
if passphrase != "" {
return fmt.Errorf("either common passphrase or specific passphrases should be set")
}
passphrase = c.String(flags.BlsPassphraseFlag.Name)
}

if passphrase == "" {
return fmt.Errorf("either common passphrase or specific passphrases should be set")
}

keystorePath := c.String(flags.KeyStorePathFlag.Name)

blsKeyPair, err = keystore.GetBLSPrivateKey(passphrase, keystorePath)
if err == nil && !c.Bool(flags.OverrideFlag.Name) {
logger.Info(
"BLS private key already exists, override flag not set",
"G1", blsKeyPair.GetPubKeyG1().String(),
"G2", blsKeyPair.GetPubKeyG2().String(),
)
return nil
}

if c.Bool(flags.GenerateKeyPairFlag.Name) {
blsKeyPair, err = keystore.GenerateBlsKeyPair()
if err != nil {
return fmt.Errorf("error generating BLS key %v", err)
}
}

if err = keystore.SaveBLSPrivateKey(passphrase, keystorePath, blsKeyPair); err != nil {
return fmt.Errorf("error writing the BLS private key to %s file %v", keystore.BlsEncryptedWallet, err)
}
logger.Info(
"BLS private key saved",
"G1", blsKeyPair.GetPubKeyG1().String(),
"G2", blsKeyPair.GetPubKeyG2().String(),
)

return nil
}
99 changes: 99 additions & 0 deletions cmd/commands/decrypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package commands

import (
"context"
"encoding/hex"
"fmt"

"github.com/eodata/operator-cli/cmd/flags"
"github.com/eodata/operator-cli/internal/keystore"
"github.com/ethereum/go-ethereum/crypto"
"github.com/urfave/cli/v3"
)

func NewDecryptCommand(ctx context.Context, version string) *cli.Command {
return &cli.Command{
Name: "decrypt",
Description: "Decrypt the ecdsa and bls private keys",
Version: version,
HideVersion: true,
Action: runDecrypt,
Flags: []cli.Flag{
flags.PassphraseFlag,
flags.EcdsaPassphraseFlag,
flags.BlsPassphraseFlag,
flags.KeyStorePathFlag,
},
}
}

func runDecrypt(ctx context.Context, c *cli.Command) error {
logger := flags.Logger

var ecdsaPassphrase string
var blsPassphrase string

if c.IsSet(flags.PassphraseFlag.Name) {
ecdsaPassphrase = c.String(flags.PassphraseFlag.Name)
blsPassphrase = c.String(flags.PassphraseFlag.Name)
}

if c.IsSet(flags.EcdsaPassphraseFlag.Name) {
if ecdsaPassphrase != "" {
return fmt.Errorf("either common passphrase or ecdsa passphrases should be set")
}
ecdsaPassphrase = c.String(flags.EcdsaPassphraseFlag.Name)
}

if c.IsSet(flags.BlsPassphraseFlag.Name) {
if blsPassphrase != "" {
return fmt.Errorf("either common passphrase or bls passphrases should be set")
}
blsPassphrase = c.String(flags.BlsPassphraseFlag.Name)
}

keystorePath := c.String(flags.KeyStorePathFlag.Name)

senderEcdsaKeyPair, err := keystore.GetECDSAPrivateKey(ecdsaPassphrase, keystorePath, "")
if err != nil {
return fmt.Errorf("error reading the sender ECDSA private key %v", err)
}

logger.Info(
"sender ecdsa info",
"address", crypto.PubkeyToAddress(senderEcdsaKeyPair.PublicKey),
"private key", hex.EncodeToString(senderEcdsaKeyPair.D.Bytes()),
)

blsKeyPair, err := keystore.GetBLSPrivateKey(blsPassphrase, keystorePath)
if err != nil {
return fmt.Errorf("error reading the BLS private key %v", err)
}

logger.Info(
"BLS info",
"G1", blsKeyPair.GetPubKeyG1().String(),
"G2", blsKeyPair.GetPubKeyG2().String(),
"private key", blsKeyPair.PrivKey.String(),
)

ecdsaAddresses, err := keystore.ListEcdsaAddresses(keystorePath)
if err != nil {
return fmt.Errorf("error listing the ECDSA keys %v", err)
}

for _, ecdsaAddress := range ecdsaAddresses {
ecdsaKeyPair, err := keystore.GetECDSAPrivateKey(ecdsaPassphrase, keystorePath, ecdsaAddress)
if err != nil {
return fmt.Errorf("error reading the ECDSA private key of %s %v", ecdsaAddress, err)
}

logger.Info(
"ECDSA info",
"address", crypto.PubkeyToAddress(ecdsaKeyPair.PublicKey),
"private key", hex.EncodeToString(ecdsaKeyPair.D.Bytes()),
)
}

return nil
}
2 changes: 1 addition & 1 deletion cmd/deregister.go → cmd/commands/deregister.g
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cmd
package commands

import (
"context"
Expand Down
2 changes: 1 addition & 1 deletion cmd/print_status.go → cmd/commands/print_status.g
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cmd
package commands

import (
"context"
Expand Down
Loading