Skip to content
Draft
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 cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func init() {
RootCmd.AddCommand(initiator.StartResigning)
RootCmd.AddCommand(initiator.GenerateReshareMsg)
RootCmd.AddCommand(initiator.StartReshare)
RootCmd.AddCommand(initiator.StartServer)
}

// RootCmd represents the root command of DKG-tool CLI
Expand All @@ -40,6 +41,7 @@ func Execute(appName, version string) {
initiator.StartResigning.Version = version
initiator.GenerateReshareMsg.Version = version
initiator.StartReshare.Version = version
initiator.StartServer.Version = version
operator.StartDKGOperator.Version = version
if err := RootCmd.Execute(); err != nil {
log.Fatal("failed to execute root command", zap.Error(err))
Expand Down
19 changes: 19 additions & 0 deletions cli/flags/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ func SetInitFlags(cmd *cobra.Command) {
SetTLSInsecureFlag(cmd)
}

func SetInitServerFlags(cmd *cobra.Command) {
SetBaseFlags(cmd)
SetPortFlag(cmd)
}

// BindInitiatorBaseFlags binds flags to yaml config parameters
func BindInitiatorBaseFlags(cmd *cobra.Command) error {
var err error
Expand Down Expand Up @@ -174,6 +179,20 @@ func BindInitFlags(cmd *cobra.Command) error {
return nil
}

func BindInitServerFlags(cmd *cobra.Command) error {
if err := BindBaseFlags(cmd); err != nil {
return err
}
if err := viper.BindPFlag("port", cmd.PersistentFlags().Lookup("port")); err != nil {
return err
}
Port = viper.GetUint64("port")
if Port == 0 {
return fmt.Errorf("😥 Wrong port provided")
}
return nil
}

// SetViperConfig reads a yaml config file if provided
func SetViperConfig(cmd *cobra.Command) error {
if err := viper.BindPFlag("configPath", cmd.PersistentFlags().Lookup("configPath")); err != nil {
Expand Down
8 changes: 4 additions & 4 deletions cli/flags/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func SetOperatorFlags(cmd *cobra.Command) {
SetBaseFlags(cmd)
PrivateKeyFlag(cmd)
PrivateKeyPassFlag(cmd)
OperatorPortFlag(cmd)
SetPortFlag(cmd)
OperatorIDFlag(cmd)
SetServerTLSCertPath(cmd)
SetServerTLSKeyPath(cmd)
Expand Down Expand Up @@ -111,9 +111,9 @@ func PrivateKeyPassFlag(c *cobra.Command) {
AddPersistentStringFlag(c, privKeyPassword, "", "Password to decrypt initiator`s Private Key file", false)
}

// OperatorPortFlag adds operator listening port flag to the command
func OperatorPortFlag(c *cobra.Command) {
AddPersistentIntFlag(c, operatorPort, 3030, "Operator Private Key hex", false)
// SetPortFlag adds operator listening port flag to the command
func SetPortFlag(c *cobra.Command) {
AddPersistentIntFlag(c, operatorPort, 3030, "Port to listen", false)
}

// OperatorIDFlag add operator ID flag to the command
Expand Down
121 changes: 50 additions & 71 deletions cli/initiator/initiator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,22 @@ package initiator

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

e2m_core "github.com/bloxapp/eth2-key-manager/core"
"github.com/sourcegraph/conc/pool"
"github.com/spf13/cobra"
"go.uber.org/zap"

spec "github.com/ssvlabs/dkg-spec"
"github.com/ssvlabs/ssv-dkg/cli/flags"
cli_utils "github.com/ssvlabs/ssv-dkg/cli/utils"
"github.com/ssvlabs/ssv-dkg/pkgs/initiator"
"github.com/ssvlabs/ssv-dkg/pkgs/wire"
)

const (
// maxConcurrency is the maximum number of DKG inits to run concurrently.
maxConcurrency = 20
"github.com/ssvlabs/ssv-dkg/pkgs/initiator/server"
)

func init() {
flags.SetInitFlags(StartDKG)
flags.SetInitServerFlags(StartServer)
}

var StartDKG = &cobra.Command{
Expand Down Expand Up @@ -69,74 +62,60 @@ var StartDKG = &cobra.Command{
}
// start the ceremony
ctx := context.Background()
pool := pool.NewWithResults[*Result]().WithContext(ctx).WithFirstError().WithMaxGoroutines(maxConcurrency)
for i := 0; i < int(flags.Validators); i++ {
i := i
pool.Go(func(ctx context.Context) (*Result, error) {
// Create new DKG initiator
dkgInitiator, err := initiator.New(opMap.Clone(), logger, cmd.Version, flags.ClientCACertPath, flags.TLSInsecure)
if err != nil {
return nil, err
}
// Create a new ID.
id := spec.NewID()
nonce := flags.Nonce + uint64(i)
// Perform the ceremony.
depositData, keyShares, proofs, err := dkgInitiator.StartDKG(id, flags.WithdrawAddress.Bytes(), operatorIDs, ethNetwork, flags.OwnerAddress, nonce, flags.Amount)
if err != nil {
return nil, err
}
logger.Debug("DKG ceremony completed",
zap.String("id", hex.EncodeToString(id[:])),
zap.Uint64("nonce", nonce),
zap.String("pubkey", depositData.PubKey),
)
return &Result{
id: id,
depositData: depositData,
keyShares: keyShares,
nonce: nonce,
proof: proofs,
}, nil
})
}
results, err := pool.Wait()
if err != nil {
logger.Fatal("😥 Failed to initiate DKG ceremony: ", zap.Error(err))
}
var depositDataArr []*wire.DepositDataCLI
var keySharesArr []*wire.KeySharesCLI
var proofs [][]*wire.SignedProof
for _, res := range results {
depositDataArr = append(depositDataArr, res.depositData)
keySharesArr = append(keySharesArr, res.keyShares)
proofs = append(proofs, res.proof)
}
// Save results
logger.Info("🎯 All data is validated.")
if err := cli_utils.WriteResults(
initiator.StartInitCeremony(
ctx,
logger,
depositDataArr,
keySharesArr,
proofs,
false,
int(flags.Validators),
opMap,
operatorIDs,
flags.OwnerAddress,
flags.Nonce,
flags.WithdrawAddress,
flags.Nonce,
flags.Amount,
uint64(flags.Validators),
ethNetwork,
flags.ClientCACertPath,
flags.TLSInsecure,
flags.OutputPath,
); err != nil {
logger.Fatal("Could not save results", zap.Error(err))
}
logger.Info("🚀 DKG ceremony completed")
cmd.Version)
return nil
},
}

type Result struct {
id [24]byte
nonce uint64
depositData *wire.DepositDataCLI
keyShares *wire.KeySharesCLI
proof []*wire.SignedProof
var StartServer = &cobra.Command{
Use: "initiator_server",
Short: "Starts server to accept commands by http",
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Println(`
█████╗ ██╗ ██╗ ██████╗ ██╗███╗ ██╗██╗████████╗██╗ █████╗ ████████╗ ██████╗ ██████╗
██╔══██╗██║ ██╔╝██╔════╝ ██║████╗ ██║██║╚══██╔══╝██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗
██║ ██║█████╔╝ ██║ ███╗ ██║██╔██╗ ██║██║ ██║ ██║███████║ ██║ ██║ ██║██████╔╝
██║ ██║██╔═██╗ ██║ ██║ ██║██║╚██╗██║██║ ██║ ██║██╔══██║ ██║ ██║ ██║██╔══██╗
██████╔╝██║ ██╗╚██████╔╝ ██║██║ ╚████║██║ ██║ ██║██║ ██║ ██║ ╚██████╔╝██║ ██║
╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝`)
if err := flags.SetViperConfig(cmd); err != nil {
return err
}
if err := flags.BindInitServerFlags(cmd); err != nil {
return err
}
logger, err := cli_utils.SetGlobalLogger(cmd, "dkg-initiator-server", flags.LogFilePath, flags.LogLevel, flags.LogFormat, flags.LogLevelFormat)
if err != nil {
return err
}
defer func() {
if err := cli_utils.Sync(logger); err != nil {
log.Printf("Failed to sync logger: %v", err)
}
}()
logger.Info("🪛 Initiator`s", zap.String("Version", cmd.Version))
srv, err := server.New(logger, cmd.Version, flags.OutputPath)
if err != nil {
logger.Fatal("😥 failed to create initiator server: ", zap.Error(err))
}
logger.Info("🚀 Starting DKG initiator server", zap.Uint64("at port", flags.Port))
if err := srv.Start(uint16(flags.Port)); err != nil {
logger.Fatal("error starting server", zap.Error(err))
}
return nil
},
}
2 changes: 1 addition & 1 deletion cli/operator/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ var StartDKGOperator = &cobra.Command{
}
logger.Info("🚀 Starting DKG operator", zap.Uint64("at port", flags.Port))
if err := srv.Start(uint16(flags.Port), flags.ServerTLSCertPath, flags.ServerTLSKeyPath); err != nil {
log.Fatalf("Error in operator %v", err)
logger.Fatal("error starting server at operator", zap.Error(err))
}
return nil
},
Expand Down
15 changes: 13 additions & 2 deletions cli/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (

spec "github.com/ssvlabs/dkg-spec"
"github.com/ssvlabs/ssv-dkg/pkgs/crypto"
"github.com/ssvlabs/ssv-dkg/pkgs/initiator"
"github.com/ssvlabs/ssv-dkg/pkgs/utils"
"github.com/ssvlabs/ssv-dkg/pkgs/validator"
"github.com/ssvlabs/ssv-dkg/pkgs/wire"
Expand Down Expand Up @@ -241,7 +240,7 @@ func WriteAggregatedInitResults(dir string, depositDataArr []*wire.DepositDataCL
}
keysharesFinalPath := fmt.Sprintf("%s/keyshares.json", dir)
logger.Info("💾 Writing keyshares payload to file", zap.String("path", keysharesFinalPath))
aggrKeySharesArr, err := initiator.GenerateAggregatesKeyshares(keySharesArr)
aggrKeySharesArr, err := GenerateAggregatesKeyshares(keySharesArr)
if err != nil {
return err
}
Expand Down Expand Up @@ -413,3 +412,15 @@ func SetGlobalLogger(cmd *cobra.Command, name, logFilePath, logLevel, logFormat,
logger := zap.L().Named(name)
return logger, nil
}

func GenerateAggregatesKeyshares(keySharesArr []*wire.KeySharesCLI) (*wire.KeySharesCLI, error) {
var data []*wire.Data
for _, keyShares := range keySharesArr {
data = append(data, keyShares.Shares...)
}
ks := &wire.KeySharesCLI{}
ks.Version = "v1.2.0"
ks.Shares = data
ks.CreatedAt = time.Now().UTC()
return ks, nil
}
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -296,5 +296,18 @@ services:
volumes:
- ./examples:/data

initiator_server:
image: ssv-dkg:latest
networks:
- shared_network
command:
[
"initiator_server",
"--configPath",
"/data/config/initiator_server.example.yaml",
]
volumes:
- ./examples:/data

networks:
shared_network:
6 changes: 6 additions & 0 deletions examples/config/initiator_server.example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
port: 8080
outputPath: /data/initiator/output
logLevel: info
logFormat: json
logLevelFormat: capitalColor
logFilePath: /data/initiator/output/initiator_debug.log
90 changes: 90 additions & 0 deletions pkgs/initiator/ceremony.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package initiator

import (
"context"
"encoding/hex"

e2m_core "github.com/bloxapp/eth2-key-manager/core"
"github.com/ethereum/go-ethereum/common"
"github.com/sourcegraph/conc/pool"
spec "github.com/ssvlabs/dkg-spec"
cli_utils "github.com/ssvlabs/ssv-dkg/cli/utils"
"github.com/ssvlabs/ssv-dkg/pkgs/wire"
"go.uber.org/zap"
)

const (
// maxConcurrency is the maximum number of DKG inits to run concurrently.
maxConcurrency = 20
)

type Result struct {
id [24]byte
nonce uint64
depositData *wire.DepositDataCLI
keyShares *wire.KeySharesCLI
proof []*wire.SignedProof
}

func StartInitCeremony(ctx context.Context, logger *zap.Logger, opMap wire.OperatorsCLI, operatorIDs []uint64, ownerAddress, withdrawAddress common.Address, nonce, amount, validators uint64, ethNetwork e2m_core.Network, clientCACertPath []string, tlsInsecure bool, outputPath, ver string) {
pool := pool.NewWithResults[*Result]().WithContext(ctx).WithFirstError().WithMaxGoroutines(maxConcurrency)
for i := 0; i < int(validators); i++ {
i := i
pool.Go(func(ctx context.Context) (*Result, error) {
// Create new DKG initiator
dkgInitiator, err := New(opMap.Clone(), logger, ver, clientCACertPath, tlsInsecure)
if err != nil {
return nil, err
}
// Create a new ID.
id := spec.NewID()
nonce := nonce + uint64(i)
// Perform the ceremony.
depositData, keyShares, proofs, err := dkgInitiator.StartDKG(id, withdrawAddress.Bytes(), operatorIDs, ethNetwork, ownerAddress, nonce, amount)
if err != nil {
return nil, err
}
logger.Debug("DKG ceremony completed",
zap.String("id", hex.EncodeToString(id[:])),
zap.Uint64("nonce", nonce),
zap.String("pubkey", depositData.PubKey),
)
return &Result{
id: id,
depositData: depositData,
keyShares: keyShares,
nonce: nonce,
proof: proofs,
}, nil
})
}
results, err := pool.Wait()
if err != nil {
logger.Fatal("😥 Failed to initiate DKG ceremony: ", zap.Error(err))
}
var depositDataArr []*wire.DepositDataCLI
var keySharesArr []*wire.KeySharesCLI
var proofs [][]*wire.SignedProof
for _, res := range results {
depositDataArr = append(depositDataArr, res.depositData)
keySharesArr = append(keySharesArr, res.keyShares)
proofs = append(proofs, res.proof)
}
// Save results
logger.Info("🎯 All data is validated.")
if err := cli_utils.WriteResults(
logger,
depositDataArr,
keySharesArr,
proofs,
false,
int(validators),
ownerAddress,
nonce,
withdrawAddress,
outputPath,
); err != nil {
logger.Fatal("Could not save results", zap.Error(err))
}
logger.Info("🚀 DKG ceremony completed")
}
Loading