diff --git a/cmd/combine.go b/cmd/combine.go deleted file mode 100644 index 1deab5c..0000000 --- a/cmd/combine.go +++ /dev/null @@ -1,27 +0,0 @@ -package cmd - -import ( - "github.com/p2p-org/dkc/cmd/combine" - "github.com/p2p-org/dkc/utils" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var combineCmd = &cobra.Command{ - Use: "combine", - Short: "Combine distributed wallets to keystore", - Long: `Allow to combine distributed wallets to keystore`, - Run: func(cmd *cobra.Command, args []string) { - utils.Log.Info().Msgf("starting DKC-%s", viper.Get("version")) - utils.Log.Info().Msgf("using config file: %s", viper.ConfigFileUsed()) - utils.LogCombine.Info().Msg("starting combine function") - err := combine.Run() - if err != nil { - utils.LogCombine.Fatal().Err(nil).Send() - } - }, -} - -func init() { - rootCmd.AddCommand(combineCmd) -} diff --git a/cmd/combine/run.go b/cmd/combine/run.go deleted file mode 100644 index 6692bc0..0000000 --- a/cmd/combine/run.go +++ /dev/null @@ -1,41 +0,0 @@ -package combine - -import "github.com/p2p-org/dkc/utils" - -func Run() error { - utils.LogCombine.Info().Msg("validating config") - combineRuntime, err := newCombineRuntime() - if err != nil { - utils.LogCombine.Err(err).Send() - return err - } - - err = combineRuntime.validate() - if err != nil { - utils.LogSplit.Err(err).Send() - return err - } - - utils.LogCombine.Info().Msg("creating wallets") - err = combineRuntime.createWalletAndStore() - if err != nil { - utils.LogCombine.Err(err).Send() - return err - } - - utils.LogCombine.Info().Msg("updating stores") - err = combineRuntime.storeUpdater() - if err != nil { - utils.LogCombine.Err(err).Send() - return err - } - - utils.LogCombine.Info().Msg("checking signatures") - err = combineRuntime.checkSignature() - if err != nil { - utils.LogCombine.Err(err).Send() - return err - } - - return nil -} diff --git a/cmd/convert.go b/cmd/convert.go new file mode 100644 index 0000000..b0c8056 --- /dev/null +++ b/cmd/convert.go @@ -0,0 +1,27 @@ +package cmd + +import ( + "github.com/p2p-org/dkc/cmd/convert" + "github.com/p2p-org/dkc/utils" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var convertCmd = &cobra.Command{ + Use: "convert", + Short: "Convert wallets from different types", + Long: `Allow to convert wallets between different types. Supported types are: nd, hd, distributed`, + Run: func(cmd *cobra.Command, args []string) { + utils.Log.Info().Msgf("starting DKC-%s", viper.Get("version")) + utils.Log.Info().Msgf("using config file: %s", viper.ConfigFileUsed()) + utils.LogConvert.Info().Msg("starting convert function") + err := convert.Run() + if err != nil { + utils.LogConvert.Fatal().Err(nil).Send() + } + }, +} + +func init() { + rootCmd.AddCommand(convertCmd) +} diff --git a/cmd/convert/convert.go b/cmd/convert/convert.go new file mode 100644 index 0000000..ebeef2c --- /dev/null +++ b/cmd/convert/convert.go @@ -0,0 +1,34 @@ +package convert + +import "github.com/p2p-org/dkc/utils" + +func Run() error { + utils.LogConvert.Info().Msg("init and validate config") + convertRuntime, err := newConvertRuntime() + if err != nil { + utils.LogConvert.Err(err).Send() + return err + } + + err = convertRuntime.validate() + if err != nil { + utils.LogConvert.Err(err).Send() + return err + } + + utils.LogConvert.Info().Msg("creating wallets") + err = convertRuntime.createWalletAndStore() + if err != nil { + utils.LogConvert.Err(err).Send() + return err + } + + utils.LogConvert.Info().Msg("checking signatures") + err = convertRuntime.checkSignature() + if err != nil { + utils.LogConvert.Err(err).Send() + return err + } + + return nil +} diff --git a/cmd/combine/helpers.go b/cmd/convert/helpers.go similarity index 81% rename from cmd/combine/helpers.go rename to cmd/convert/helpers.go index 6e5b1cc..0695f3f 100644 --- a/cmd/combine/helpers.go +++ b/cmd/convert/helpers.go @@ -1,4 +1,4 @@ -package combine +package convert import ( "context" @@ -8,52 +8,32 @@ import ( "github.com/p2p-org/dkc/utils" "github.com/p2p-org/dkc/utils/crypto/bls" "github.com/spf13/viper" - types "github.com/wealdtech/go-eth2-wallet-types/v2" ) -type AccountExtends struct { - PubKey []byte - CompositePubKeys [][]byte - Accounts []utils.Account -} - -type CombineRuntime struct { - ctx context.Context - dWalletsPath string - ndWalletsPath string - passphrasesIn [][]byte - passphrasesOut [][]byte - accountDatas map[string]AccountExtends - stores []utils.DirkStore - peers utils.Peers - wallet utils.NDWallet - store types.Store -} - -func newCombineRuntime() (*CombineRuntime, error) { - cr := &CombineRuntime{} +func newConvertRuntime() (*ConvertRuntime, error) { + cr := &utils.ConvertRuntime{} var err error - utils.LogCombine.Debug().Msg("validating nd-wallets field") - var ndWalletConfig utils.NDWalletConfig - err = viper.UnmarshalKey("nd-wallets", &ndWalletConfig) + utils.LogConvert.Debug().Msg("validating input wallet") + var inputW utils.W + err = viper.UnmarshalKey("input", &inputW) if err != nil { return nil, err } - err = ndWalletConfig.Validate() + err = inputW.Validate() if err != nil { return nil, err } - utils.LogCombine.Debug().Msg("validating distributed-wallets field") - var dWalletConfig utils.DWalletConfig - err = viper.UnmarshalKey("distributed-wallets", &dWalletConfig) + utils.LogConvert.Debug().Msg("validating output field") + var outputW utils.W + err = viper.UnmarshalKey("output", &outputW) if err != nil { return nil, err } - err = dWalletConfig.Validate() + err = outputW.Validate() if err != nil { return nil, err } @@ -83,7 +63,7 @@ func newCombineRuntime() (*CombineRuntime, error) { return cr, nil } -func (cr *CombineRuntime) validate() error { +func (cr *utils.ConvertRuntime) validate() error { if cr.dWalletsPath == cr.ndWalletsPath { return utils.ErrorSameDirs } diff --git a/cmd/root.go b/cmd/root.go index 0a0d3a0..2b92498 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -19,7 +19,7 @@ var ( var rootCmd = &cobra.Command{ Use: "dkc", Short: "Dirk Key Converter", - Long: `Allow to split and combine keystores and distributed wallets for Dirk`, + Long: `Allow to convert wallets between different types`, PersistentPreRun: func(cmd *cobra.Command, args []string) { }, } diff --git a/cmd/split.go b/cmd/split.go deleted file mode 100644 index fd8b4df..0000000 --- a/cmd/split.go +++ /dev/null @@ -1,27 +0,0 @@ -package cmd - -import ( - "github.com/p2p-org/dkc/cmd/split" - "github.com/p2p-org/dkc/utils" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var splitCmd = &cobra.Command{ - Use: "split", - Short: "Split keystore to distributed wallets", - Long: `Allow to split keystore to distributed wallets`, - Run: func(cmd *cobra.Command, args []string) { - utils.Log.Info().Msgf("starting DKC-%s", viper.Get("version")) - utils.Log.Info().Msgf("using config file: %s", viper.ConfigFileUsed()) - utils.LogSplit.Info().Msg("starting split function") - err := split.Run() - if err != nil { - utils.LogSplit.Fatal().Err(nil).Send() - } - }, -} - -func init() { - rootCmd.AddCommand(splitCmd) -} diff --git a/cmd/split/helpers.go b/cmd/split/helpers.go deleted file mode 100644 index e260ac7..0000000 --- a/cmd/split/helpers.go +++ /dev/null @@ -1,235 +0,0 @@ -package split - -import ( - "context" - "encoding/hex" - "regexp" - - "github.com/google/uuid" - "github.com/p2p-org/dkc/utils" - "github.com/p2p-org/dkc/utils/crypto/bls" - "github.com/spf13/viper" -) - -type SplitRuntime struct { - ctx context.Context - dWalletsPath string - ndWalletsPath string - passphrasesIn [][]byte - passphrasesOut [][]byte - accountDatas map[string]AccountExtends - peers utils.Peers - threshold uint32 - walletsMap map[uint64]utils.DWallet - peersIDs []uint64 - walletName string -} - -type AccountExtends struct { - InitialSignature []byte - PubKey []byte - CompositePubKeys [][]byte - Accounts []utils.Account - MasterPKs [][]byte -} - -func newSplitRuntime() (*SplitRuntime, error) { - sr := &SplitRuntime{} - var err error - - utils.LogSplit.Debug().Msg("validating nd-wallets config field") - var ndWalletConfig utils.NDWalletConfig - err = viper.UnmarshalKey("nd-wallets", &ndWalletConfig) - if err != nil { - return nil, err - } - - err = ndWalletConfig.Validate() - if err != nil { - return nil, err - } - - utils.LogSplit.Debug().Msg("validating d-wallets config field") - var dWalletConfig utils.DWalletConfig - err = viper.UnmarshalKey("distributed-wallets", &dWalletConfig) - if err != nil { - return nil, err - } - - err = dWalletConfig.Validate() - if err != nil { - return nil, err - } - - sr.ctx = context.Background() - sr.dWalletsPath = dWalletConfig.Path - sr.ndWalletsPath = ndWalletConfig.Path - sr.threshold = dWalletConfig.Threshold - sr.walletName = dWalletConfig.WalletName - utils.LogSplit.Debug().Msgf("getting input passwords from %s", ndWalletConfig.Passphrases) - sr.passphrasesIn, err = utils.GetAccountsPasswords(ndWalletConfig.Passphrases) - if err != nil { - return nil, err - } - utils.LogSplit.Debug().Msgf("getting input passwords from %s", dWalletConfig.Passphrases) - sr.passphrasesOut, err = utils.GetAccountsPasswords(dWalletConfig.Passphrases) - if err != nil { - return nil, err - } - sr.accountDatas = make(map[string]AccountExtends) - sr.walletsMap = make(map[uint64]utils.DWallet) - - sr.peers = dWalletConfig.Peers - - utils.LogSplit.Debug().Msg("generating peersIDs") - for id := range sr.peers { - sr.peersIDs = append(sr.peersIDs, id) - } - - return sr, nil -} - -func (sr *SplitRuntime) validate() error { - if sr.dWalletsPath == sr.ndWalletsPath { - return utils.ErrorSameDirs - } - return nil -} - -func (sr *SplitRuntime) createWallets() error { - walletName := uuid.New().String() - if sr.walletName != "" { - walletName = sr.walletName - } - for id, peer := range sr.peers { - res, err := regexp.Compile(`:.*`) - if err != nil { - return err - } - utils.LogSplit.Debug().Msgf("creating store for peer: %d", id) - storePath := sr.dWalletsPath + "/" + res.ReplaceAllString(peer, "") - store, err := utils.CreateStore(storePath) - if err != nil { - return err - } - utils.LogSplit.Debug().Msgf("creating wallet for peer %d", id) - wallet, err := utils.CreateDWallet(store, walletName) - if err != nil { - return err - } - sr.walletsMap[id] = wallet - } - return nil -} - -func (sr *SplitRuntime) loadWallets() error { - utils.LogSplit.Debug().Msgf("load store %s", sr.ndWalletsPath) - s, err := utils.LoadStore(sr.ctx, sr.ndWalletsPath, sr.passphrasesIn) - if err != nil { - return err - } - - for _, w := range s.Wallets { - utils.LogSplit.Debug().Msgf("load wallet %s ", w.Name()) - for account := range w.Accounts(sr.ctx) { - utils.LogSplit.Debug().Msgf("get private key for account %s ", account.Name()) - key, err := utils.GetAccountKey(sr.ctx, account, sr.passphrasesIn) - if err != nil { - return err - } - utils.LogSplit.Debug().Msgf("get pub key for account %s ", account.Name()) - pubKey, err := utils.GetAccountPubkey(account) - if err != nil { - return err - } - - utils.LogSplit.Debug().Msgf("signing test string for account %s ", account.Name()) - initialSignature, err := utils.AccountSign(sr.ctx, account, sr.passphrasesIn) - if err != nil { - return err - } - - utils.LogSplit.Debug().Msgf("bls split key for account %s ", account.Name()) - masterSKs, masterPKs, err := bls.Split(sr.ctx, key, sr.threshold) - if err != nil { - return err - } - - utils.LogSplit.Debug().Msgf("setup bls participants for account %s ", account.Name()) - participants, err := bls.SetupParticipants(masterSKs, masterPKs, sr.peersIDs, len(sr.peers)) - if err != nil { - return err - } - - sr.accountDatas[account.Name()] = AccountExtends{ - MasterPKs: masterPKs, - InitialSignature: initialSignature, - Accounts: participants, - PubKey: pubKey, - } - } - } - - return nil -} - -func (sr *SplitRuntime) saveAccounts() error { - for accountName, account := range sr.accountDatas { - utils.LogSplit.Debug().Msgf("saving account %s ", accountName) - for i, acc := range account.Accounts { - utils.LogSplit.Debug().Msgf("creating account with id %d ", acc.ID) - finalAccount, err := utils.CreateDAccount( - sr.walletsMap[acc.ID], - accountName, - account.MasterPKs, - acc.Key, - sr.threshold, - sr.peers, - sr.passphrasesOut[0], - ) - if err != nil { - return err - } - - utils.LogSplit.Debug().Msgf("generating signature for account with id %d ", acc.ID) - account.Accounts[i].Signature, err = utils.AccountSign(sr.ctx, finalAccount, sr.passphrasesOut) - if err != nil { - return err - } - utils.LogSplit.Debug().Msgf("getting composite pub key for account with id %d ", acc.ID) - compositePubKey, err := utils.GetAccountCompositePubkey(finalAccount) - if err != nil { - return err - } - account.CompositePubKeys = append(account.CompositePubKeys, compositePubKey) - } - } - - return nil -} - -func (sr *SplitRuntime) checkSignature() error { - for _, account := range sr.accountDatas { - utils.LogSplit.Debug().Msgf("generating bls signature for pub key %s", hex.EncodeToString(account.PubKey)) - finalSignature, err := bls.Sign(sr.ctx, account.Accounts) - if err != nil { - return err - } - - utils.LogSplit.Debug().Msgf("compare bls signatures for pub key %s", hex.EncodeToString(account.PubKey)) - err = bls.SignatureCompare(finalSignature, account.InitialSignature) - if err != nil { - return err - } - - utils.LogSplit.Debug().Msgf("compare composite pubkeys for pub key %s", hex.EncodeToString(account.PubKey)) - for _, compositePubKey := range account.CompositePubKeys { - err = bls.CompositeKeysCompare(compositePubKey, account.PubKey) - if err != nil { - return err - } - } - } - - return nil -} diff --git a/cmd/split/run.go b/cmd/split/run.go deleted file mode 100644 index 0eae30f..0000000 --- a/cmd/split/run.go +++ /dev/null @@ -1,48 +0,0 @@ -package split - -import "github.com/p2p-org/dkc/utils" - -func Run() error { - utils.LogSplit.Info().Msg("validating config") - splitRuntime, err := newSplitRuntime() - if err != nil { - utils.LogSplit.Err(err).Send() - return err - } - - err = splitRuntime.validate() - if err != nil { - utils.LogSplit.Err(err).Send() - return err - } - - utils.LogSplit.Info().Msg("loading wallets") - err = splitRuntime.loadWallets() - if err != nil { - utils.LogSplit.Err(err).Send() - return err - } - - utils.LogSplit.Info().Msg("creating wallets") - err = splitRuntime.createWallets() - if err != nil { - utils.LogSplit.Err(err).Send() - return err - } - - utils.LogSplit.Info().Msg("saving accounts") - err = splitRuntime.saveAccounts() - if err != nil { - utils.LogSplit.Err(err).Send() - return err - } - - utils.LogSplit.Info().Msg("checking signatures") - err = splitRuntime.checkSignature() - if err != nil { - utils.LogSplit.Err(err).Send() - return err - } - - return nil -} diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..1c68432 --- /dev/null +++ b/config.yaml @@ -0,0 +1,14 @@ +input: + type: distributed + path: DISTRIBUTED_WALLETS + passphrases: ./passphrases.txt + threshold: 2 + peers: + 10: old1:9091 + 20: old2:9091 + 30: old3:9091 +output: + type: nd + path: ND_WALLETS + passphrases: ./passphrases.txt +log-level: debug diff --git a/utils/logging.go b/utils/logging.go index b03d7f6..e934430 100644 --- a/utils/logging.go +++ b/utils/logging.go @@ -11,13 +11,9 @@ import ( var Log zerolog.Logger -var LogSplit zerolog.Logger -var LogCombine zerolog.Logger - func InitLogging() { Log = zerologger.With().Logger().Level(logLevel(viper.GetString("log-level"))).Output(zerolog.ConsoleWriter{Out: os.Stderr}) - LogSplit = Log.With().Str("cmd", "split").Logger() - LogCombine = Log.With().Str("cmd", "combine").Logger() + LogConvert = Log.With().Str("cmd", "convert").Logger() } diff --git a/utils/structs.go b/utils/structs.go new file mode 100644 index 0000000..5311cf1 --- /dev/null +++ b/utils/structs.go @@ -0,0 +1,46 @@ +package utils + +import ( + "context" +) + +type W struct { + Path string + Type string + Passphrases [][]byte +} + +type ConvertRuntime struct { + Ctx context.Context + InputW W + OutputW W +} + +func (W *W) Validate() error { + if W.Path == "" { + return ErrorPathField + } + + if W.Type == "" { + return ErrorEmptyType + } + + if len(W.Passphrases) == 0 { + return ErrorPassphraseEmpty + } + + return nil + +} + +func (CR *ConvertRuntime) validate() error { + if CR.InputW.Type != CR.OutputW.Type { + return ErrorSameWalletType + } + + if CR.OutputW.Path != CR.OutputW.Path { + return ErrorSameDirs + } + + return nil +}