github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/cmd/burrow/commands/config_options.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"strings"
     7  
     8  	"github.com/hyperledger/burrow/config"
     9  	"github.com/hyperledger/burrow/crypto"
    10  	cli "github.com/jawher/mow.cli"
    11  )
    12  
    13  type configOptions struct {
    14  	configFileOpt      *string
    15  	genesisFileOpt     *string
    16  	validatorIndexOpt  *int
    17  	accountIndexOpt    *int
    18  	initAddressOpt     *string
    19  	initPassphraseOpt  *string
    20  	initMonikerOpt     *string
    21  	externalAddressOpt *string
    22  	grpcAddressOpt     *string
    23  }
    24  
    25  const configFileSpec = "[--config=<config file>]"
    26  
    27  var configFileOption = cli.StringOpt{
    28  	Name:   "c config",
    29  	Desc:   "Use the specified burrow config file",
    30  	EnvVar: "BURROW_CONFIG_FILE",
    31  }
    32  
    33  const genesisFileSpec = "[--genesis=<genesis json file>]"
    34  
    35  var genesisFileOption = cli.StringOpt{
    36  	Name:   "g genesis",
    37  	Desc:   "Use the specified genesis JSON file rather than a key in the main config, use - to read from STDIN",
    38  	EnvVar: "BURROW_GENESIS_FILE",
    39  }
    40  
    41  func addConfigOptions(cmd *cli.Cmd) *configOptions {
    42  	spec := "[--moniker=<human readable moniker>] " +
    43  		"[--index=<index of account in GenesisDoc> " +
    44  		"|--validator=<index of validator in GenesisDoc> " +
    45  		"|--address=<address of signing key>] " +
    46  		"[--passphrase=<secret passphrase to unlock key>] " +
    47  		"[--external-address=<hostname:port>] " +
    48  		"[--grpc-address=<hostname:port>] " +
    49  		configFileSpec + " " + genesisFileSpec
    50  
    51  	cmd.Spec = strings.Join([]string{cmd.Spec, spec}, " ")
    52  	return &configOptions{
    53  		accountIndexOpt: cmd.Int(cli.IntOpt{
    54  			Name:   "i index",
    55  			Desc:   "Account index (in accounts list - GenesisSpec or GenesisDoc) from which to set Address",
    56  			Value:  -1,
    57  			EnvVar: "BURROW_ACCOUNT_INDEX",
    58  		}),
    59  
    60  		validatorIndexOpt: cmd.Int(cli.IntOpt{
    61  			Name:   "v validator",
    62  			Desc:   "Validator index (in validators list - GenesisSpec or GenesisDoc) from which to set Address",
    63  			Value:  -1,
    64  			EnvVar: "BURROW_VALIDATOR_INDEX",
    65  		}),
    66  
    67  		initAddressOpt: cmd.String(cli.StringOpt{
    68  			Name:   "a address",
    69  			Desc:   "The address of the signing key of this node",
    70  			EnvVar: "BURROW_ADDRESS",
    71  		}),
    72  
    73  		initPassphraseOpt: cmd.String(cli.StringOpt{
    74  			Name:   "p passphrase",
    75  			Desc:   "The passphrase of the signing key of this node (currently unimplemented but planned for future version of our KeyClient interface)",
    76  			EnvVar: "BURROW_PASSPHRASE",
    77  		}),
    78  
    79  		initMonikerOpt: cmd.String(cli.StringOpt{
    80  			Name:   "m moniker",
    81  			Desc:   "An optional human-readable moniker to identify this node amongst Tendermint peers in logs and status queries",
    82  			EnvVar: "BURROW_NODE_MONIKER",
    83  		}),
    84  
    85  		externalAddressOpt: cmd.String(cli.StringOpt{
    86  			Name:   "x external-address",
    87  			Desc:   "An external address or host name provided with the port that this node will broadcast over gossip in order for other nodes to connect",
    88  			EnvVar: "BURROW_EXTERNAL_ADDRESS",
    89  		}),
    90  
    91  		grpcAddressOpt: cmd.String(cli.StringOpt{
    92  			Name:   "grpc-address",
    93  			Desc:   "GRPC listen address",
    94  			EnvVar: "BURROW_GRPC_ADDRESS",
    95  		}),
    96  
    97  		configFileOpt: cmd.String(configFileOption),
    98  
    99  		genesisFileOpt: cmd.String(genesisFileOption),
   100  	}
   101  }
   102  
   103  func (opts *configOptions) obtainBurrowConfig() (*config.BurrowConfig, error) {
   104  	conf, err := obtainDefaultConfig(*opts.configFileOpt, *opts.genesisFileOpt)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	// Which account am I?
   109  	conf.ValidatorAddress, err = accountAddress(conf, *opts.initAddressOpt, *opts.accountIndexOpt, *opts.validatorIndexOpt)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	if *opts.initPassphraseOpt != "" {
   114  		conf.Passphrase = opts.initPassphraseOpt
   115  	}
   116  	if *opts.initMonikerOpt == "" {
   117  		chainIDHeader := ""
   118  		if conf.GenesisDoc != nil && conf.GenesisDoc.GetChainID() != "" {
   119  			chainIDHeader = conf.GenesisDoc.GetChainID() + "_"
   120  		}
   121  		if conf.ValidatorAddress != nil {
   122  			// Set a default moniker... since we can at this stage of config completion and it is required for start
   123  			conf.Tendermint.Moniker = fmt.Sprintf("%sNode_%s", chainIDHeader, conf.ValidatorAddress)
   124  		}
   125  	} else {
   126  		conf.Tendermint.Moniker = *opts.initMonikerOpt
   127  	}
   128  	if *opts.externalAddressOpt != "" {
   129  		conf.Tendermint.ExternalAddress = *opts.externalAddressOpt
   130  	}
   131  	if *opts.grpcAddressOpt != "" {
   132  		host, port, err := net.SplitHostPort(*opts.grpcAddressOpt)
   133  		if err != nil {
   134  			return nil, fmt.Errorf("could not parse GRPC listen addres: %w", err)
   135  		}
   136  		conf.RPC.GRPC.ListenHost = host
   137  		conf.RPC.GRPC.ListenPort = port
   138  	}
   139  	return conf, nil
   140  }
   141  
   142  // address is sourced in the following order:
   143  // 	1. explicitly from cli
   144  // 	2. genesis accounts (by index)
   145  // 	3. genesis validators (by index)
   146  // 	4. config
   147  // 	5. genesis validator (if only one)
   148  func accountAddress(conf *config.BurrowConfig, addressIn string, accIndex, valIndex int) (*crypto.Address, error) {
   149  	if addressIn != "" {
   150  		address, err := crypto.AddressFromHexString(addressIn)
   151  		if err != nil {
   152  			return nil, fmt.Errorf("could not read address for account in '%s': %v", addressIn, err)
   153  		}
   154  		return &address, nil
   155  	} else if accIndex > -1 {
   156  		if conf.GenesisDoc == nil {
   157  			return nil, fmt.Errorf("unable to set Address from provided index since no " +
   158  				"GenesisDoc/GenesisSpec provided")
   159  		}
   160  		if accIndex >= len(conf.GenesisDoc.Accounts) {
   161  			return nil, fmt.Errorf("index of %v given but only %v accounts specified in GenesisDoc",
   162  				accIndex, len(conf.GenesisDoc.Accounts))
   163  		}
   164  		return &conf.GenesisDoc.Accounts[accIndex].Address, nil
   165  	} else if valIndex > -1 {
   166  		if conf.GenesisDoc == nil {
   167  			return nil, fmt.Errorf("unable to set Address from provided validator since no " +
   168  				"GenesisDoc/GenesisSpec provided")
   169  		}
   170  		if valIndex >= len(conf.GenesisDoc.Validators) {
   171  			return nil, fmt.Errorf("validator index of %v given but only %v validators specified in GenesisDoc",
   172  				valIndex, len(conf.GenesisDoc.Validators))
   173  		}
   174  		return &conf.GenesisDoc.Validators[valIndex].Address, nil
   175  	} else if conf.ValidatorAddress != nil {
   176  		return conf.ValidatorAddress, nil
   177  	} else if conf.GenesisDoc != nil && len(conf.GenesisDoc.Validators) == 1 {
   178  		return &conf.GenesisDoc.Validators[0].Address, nil
   179  	}
   180  	return nil, nil
   181  }