package main import ( "errors" "flag" "fmt" "os" "strings" "sync" "github.com/harmony-one/harmony/internal/blsgen" nodeconfig "github.com/harmony-one/harmony/internal/configs/node" "github.com/harmony-one/harmony/multibls" ) var ( blsKeyFile = flag.String("blskey_file", "", "The encrypted file of bls serialized private key by passphrase.") blsFolder = flag.String("blsfolder", ".hmy/blskeys", "The folder that stores the bls keys and corresponding passphrases; e.g. .key and .pass; all bls keys mapped to same shard") maxBLSKeysPerNode = flag.Int("max_bls_keys_per_node", 4, "Maximum number of bls keys allowed per node (default 4)") // TODO(jacky): rename it to a better name with cobra alias blsPass = flag.String("blspass", "default", "The source for bls passphrases. (default, no-prompt, prompt, file:$CONFIG_FILE, none)") persistPass = flag.Bool("save-passphrase", false, "Whether the prompt passphrase is saved after prompt.") awsConfigSource = flag.String("aws-config-source", "default", "The source for aws config. (default, prompt, none, file:$CONFIG_FILE)") ) var ( multiBLSPriKey multibls.PrivateKeys blsKeyLoadErr error onceLoadBLSKey sync.Once ) // setupConsensusKeys load bls keys and add the keys to nodeConfig. Return the loaded public keys. func setupConsensusKeys(config *nodeconfig.ConfigType) multibls.PublicKeys { onceLoadBLSKey.Do(func() { multiBLSPriKey, blsKeyLoadErr = loadBLSKeys() if blsKeyLoadErr != nil { fmt.Fprintf(os.Stderr, "ERROR when loading bls key: %v\n", blsKeyLoadErr) os.Exit(100) } fmt.Printf("Successfully loaded %v keys\n", len(multiBLSPriKey)) }) config.ConsensusPriKey = multiBLSPriKey return multiBLSPriKey.GetPublicKeys() } func loadBLSKeys() (multibls.PrivateKeys, error) { config, err := parseBLSLoadingConfig() if err != nil { return nil, err } keys, err := blsgen.LoadKeys(config) if err != nil { return nil, err } if len(keys) == 0 { return nil, fmt.Errorf("0 bls keys loaded") } if len(keys) >= *maxBLSKeysPerNode { return nil, fmt.Errorf("bls keys exceed maximum count %v", *maxBLSKeysPerNode) } return keys, err } func parseBLSLoadingConfig() (blsgen.Config, error) { var ( config blsgen.Config err error ) if len(*blsKeyFile) != 0 { config.MultiBlsKeys = strings.Split(*blsKeyFile, ",") } config.BlsDir = blsFolder config, err = parseBLSPass(config, *blsPass) if err != nil { return blsgen.Config{}, err } config, err = parseAwsConfigSrc(config, *awsConfigSource) if err != nil { return blsgen.Config{}, err } return config, nil } func parseBLSPass(config blsgen.Config, src string) (blsgen.Config, error) { methodArgs := strings.SplitN(src, ":", 2) method := methodArgs[0] switch method { case "default", "stdin": config.PassSrcType = blsgen.PassSrcAuto case "file": config.PassSrcType = blsgen.PassSrcFile if len(methodArgs) < 2 { return blsgen.Config{}, errors.New("must specify passphrase file") } config.PassFile = &methodArgs[1] case "no-prompt": config.PassSrcType = blsgen.PassSrcFile case "prompt": config.PassSrcType = blsgen.PassSrcPrompt config.PersistPassphrase = *persistPass case "none": config.PassSrcType = blsgen.PassSrcNil } return config, nil } func parseAwsConfigSrc(config blsgen.Config, src string) (blsgen.Config, error) { methodArgs := strings.SplitN(src, ":", 2) method := methodArgs[0] switch method { case "default": config.AwsCfgSrcType = blsgen.AwsCfgSrcShared case "file": config.AwsCfgSrcType = blsgen.AwsCfgSrcFile if len(methodArgs) < 2 { return blsgen.Config{}, errors.New("must specify aws config file") } config.AwsConfigFile = &methodArgs[1] case "prompt": config.AwsCfgSrcType = blsgen.AwsCfgSrcPrompt case "none": config.AwsCfgSrcType = blsgen.AwsCfgSrcNil } return config, nil }