diff options
Diffstat (limited to 'cmd/swarm/main.go')
-rw-r--r-- | cmd/swarm/main.go | 229 |
1 files changed, 78 insertions, 151 deletions
diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index 48cf032a2..4b0823796 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -27,7 +27,6 @@ import ( "strconv" "strings" "syscall" - "unicode" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" @@ -44,6 +43,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/swarm" bzzapi "github.com/ethereum/go-ethereum/swarm/api" + "gopkg.in/urfave/cli.v1" ) @@ -62,44 +62,53 @@ var ( var ( ChequebookAddrFlag = cli.StringFlag{ - Name: "chequebook", - Usage: "chequebook contract address", + Name: "chequebook", + Usage: "chequebook contract address", + EnvVar: SWARM_ENV_CHEQUEBOOK_ADDR, } SwarmAccountFlag = cli.StringFlag{ - Name: "bzzaccount", - Usage: "Swarm account key file", + Name: "bzzaccount", + Usage: "Swarm account key file", + EnvVar: SWARM_ENV_ACCOUNT, } SwarmListenAddrFlag = cli.StringFlag{ - Name: "httpaddr", - Usage: "Swarm HTTP API listening interface", + Name: "httpaddr", + Usage: "Swarm HTTP API listening interface", + EnvVar: SWARM_ENV_LISTEN_ADDR, } SwarmPortFlag = cli.StringFlag{ - Name: "bzzport", - Usage: "Swarm local http api port", + Name: "bzzport", + Usage: "Swarm local http api port", + EnvVar: SWARM_ENV_PORT, } SwarmNetworkIdFlag = cli.IntFlag{ - Name: "bzznetworkid", - Usage: "Network identifier (integer, default 3=swarm testnet)", + Name: "bzznetworkid", + Usage: "Network identifier (integer, default 3=swarm testnet)", + EnvVar: SWARM_ENV_NETWORK_ID, } SwarmConfigPathFlag = cli.StringFlag{ Name: "bzzconfig", - Usage: "Swarm config file path (datadir/bzz)", + Usage: "DEPRECATED: please use --config path/to/TOML-file", } SwarmSwapEnabledFlag = cli.BoolFlag{ - Name: "swap", - Usage: "Swarm SWAP enabled (default false)", + Name: "swap", + Usage: "Swarm SWAP enabled (default false)", + EnvVar: SWARM_ENV_SWAP_ENABLE, } SwarmSwapAPIFlag = cli.StringFlag{ - Name: "swap-api", - Usage: "URL of the Ethereum API provider to use to settle SWAP payments", + Name: "swap-api", + Usage: "URL of the Ethereum API provider to use to settle SWAP payments", + EnvVar: SWARM_ENV_SWAP_API, } SwarmSyncEnabledFlag = cli.BoolTFlag{ - Name: "sync", - Usage: "Swarm Syncing enabled (default true)", + Name: "sync", + Usage: "Swarm Syncing enabled (default true)", + EnvVar: SWARM_ENV_SYNC_ENABLE, } EnsAPIFlag = cli.StringSliceFlag{ - Name: "ens-api", - Usage: "ENS API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url", + Name: "ens-api", + Usage: "ENS API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url", + EnvVar: SWARM_ENV_ENS_API, } SwarmApiFlag = cli.StringFlag{ Name: "bzzapi", @@ -127,8 +136,9 @@ var ( Usage: "force mime type", } CorsStringFlag = cli.StringFlag{ - Name: "corsdomain", - Usage: "Domain on which to send Access-Control-Allow-Origin header (multiple domains can be supplied separated by a ',')", + Name: "corsdomain", + Usage: "Domain on which to send Access-Control-Allow-Origin header (multiple domains can be supplied separated by a ',')", + EnvVar: SWARM_ENV_CORS, } // the following flags are deprecated and should be removed in the future @@ -142,6 +152,12 @@ var ( } ) +//declare a few constant error messages, useful for later error check comparisons in test +var ( + SWARM_ERR_NO_BZZACCOUNT = "bzzaccount option is required but not set; check your config file, command line or environment variables" + SWARM_ERR_SWAP_SET_NO_API = "SWAP is enabled but --swap-api is not set" +) + var defaultNodeConfig = node.DefaultConfig // This init function sets defaults so cmd/swarm can run alongside geth. @@ -297,6 +313,8 @@ Remove corrupt entries from a local chunk database. DEPRECATED: use 'swarm db clean'. `, }, + // See config.go + DumpConfigCommand, } sort.Sort(cli.CommandsByName(app.Commands)) @@ -319,6 +337,7 @@ DEPRECATED: use 'swarm db clean'. // bzzd-specific flags CorsStringFlag, EnsAPIFlag, + SwarmTomlConfigPathFlag, SwarmConfigPathFlag, SwarmSwapEnabledFlag, SwarmSwapAPIFlag, @@ -372,19 +391,32 @@ func version(ctx *cli.Context) error { } func bzzd(ctx *cli.Context) error { - // exit if the deprecated --ethapi flag is set - if ctx.GlobalString(DeprecatedEthAPIFlag.Name) != "" { - utils.Fatalf("--ethapi is no longer a valid command line flag, please use --ens-api and/or --swap-api.") + //build a valid bzzapi.Config from all available sources: + //default config, file config, command line and env vars + bzzconfig, err := buildConfig(ctx) + if err != nil { + utils.Fatalf("unable to configure swarm: %v", err) } cfg := defaultNodeConfig + //geth only supports --datadir via command line + //in order to be consistent within swarm, if we pass --datadir via environment variable + //or via config file, we get the same directory for geth and swarm + if _, err := os.Stat(bzzconfig.Path); err == nil { + cfg.DataDir = bzzconfig.Path + } + //setup the ethereum node utils.SetNodeConfig(ctx, &cfg) stack, err := node.New(&cfg) if err != nil { utils.Fatalf("can't create node: %v", err) } - - registerBzzService(ctx, stack) + //a few steps need to be done after the config phase is completed, + //due to overriding behavior + initSwarmNode(bzzconfig, stack, ctx) + //register BZZ as node.Service in the ethereum node + registerBzzService(bzzconfig, ctx, stack) + //start the node utils.StartNode(stack) go func() { @@ -396,13 +428,12 @@ func bzzd(ctx *cli.Context) error { stack.Stop() }() - networkId := ctx.GlobalUint64(SwarmNetworkIdFlag.Name) // Add bootnodes as initial peers. - if ctx.GlobalIsSet(utils.BootnodesFlag.Name) { - bootnodes := strings.Split(ctx.GlobalString(utils.BootnodesFlag.Name), ",") + if bzzconfig.BootNodes != "" { + bootnodes := strings.Split(bzzconfig.BootNodes, ",") injectBootnodes(stack.Server(), bootnodes) } else { - if networkId == 3 { + if bzzconfig.NetworkId == 3 { injectBootnodes(stack.Server(), testbetBootNodes) } } @@ -411,139 +442,35 @@ func bzzd(ctx *cli.Context) error { return nil } -func registerBzzService(ctx *cli.Context, stack *node.Node) { - prvkey := getAccount(ctx, stack) - - chbookaddr := common.HexToAddress(ctx.GlobalString(ChequebookAddrFlag.Name)) - bzzdir := ctx.GlobalString(SwarmConfigPathFlag.Name) - if bzzdir == "" { - bzzdir = stack.InstanceDir() - } - - bzzconfig, err := bzzapi.NewConfig(bzzdir, chbookaddr, prvkey, ctx.GlobalUint64(SwarmNetworkIdFlag.Name)) - if err != nil { - utils.Fatalf("unable to configure swarm: %v", err) - } - bzzport := ctx.GlobalString(SwarmPortFlag.Name) - if len(bzzport) > 0 { - bzzconfig.Port = bzzport - } - if bzzaddr := ctx.GlobalString(SwarmListenAddrFlag.Name); bzzaddr != "" { - bzzconfig.ListenAddr = bzzaddr - } - swapEnabled := ctx.GlobalBool(SwarmSwapEnabledFlag.Name) - syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabledFlag.Name) - - swapapi := ctx.GlobalString(SwarmSwapAPIFlag.Name) - if swapEnabled && swapapi == "" { - utils.Fatalf("SWAP is enabled but --swap-api is not set") - } - - ensAPIs := ctx.GlobalStringSlice(EnsAPIFlag.Name) - ensAddr := ctx.GlobalString(DeprecatedEnsAddrFlag.Name) - - if ensAddr != "" { - log.Warn("--ens-addr is no longer a valid command line flag, please use --ens-api to specify contract address.") - } - - cors := ctx.GlobalString(CorsStringFlag.Name) +func registerBzzService(bzzconfig *bzzapi.Config, ctx *cli.Context, stack *node.Node) { + //define the swarm service boot function boot := func(ctx *node.ServiceContext) (node.Service, error) { var swapClient *ethclient.Client - if swapapi != "" { - log.Info("connecting to SWAP API", "url", swapapi) - swapClient, err = ethclient.Dial(swapapi) + var err error + if bzzconfig.SwapApi != "" { + log.Info("connecting to SWAP API", "url", bzzconfig.SwapApi) + swapClient, err = ethclient.Dial(bzzconfig.SwapApi) if err != nil { - return nil, fmt.Errorf("error connecting to SWAP API %s: %s", swapapi, err) - } - } - - ensClientConfigs := []swarm.ENSClientConfig{} - switch len(ensAPIs) { - case 0: - ensClientConfigs = append(ensClientConfigs, swarm.ENSClientConfig{ - Endpoint: node.DefaultIPCEndpoint("geth"), - ContractAddress: ensAddr, - }) - case 1: - // Check if "--ens-api ''" is specified in order to disable ENS. - if ensAPIs[0] == "" { - break - } - // Check if only one --ens-api is specified in order to use --ens-addr value - // to preserve the backward compatibility with single --ens-api flag. - c := parseFlagEnsAPI(ensAPIs[0]) - if ensAddr != "" { - // If contract address is specified in both cases, check for conflict. - if c.ContractAddress != "" && ensAddr != c.ContractAddress { - utils.Fatalf("--ens-addr flag in conflict with --ens-api flag contract address") - } - c.ContractAddress = ensAddr - } - ensClientConfigs = append(ensClientConfigs, c) - default: - // Backward compatibility with single --ens-api flag and --ens-addr is preserved. - // Check for case where multiple --ens-api flags are set with --ens-addr where - // the specified contract address is not clear to which api belongs. - if ensAddr != "" { - utils.Fatalf("--ens-addr flag can not be used with multiple --ens-api flags") + return nil, fmt.Errorf("error connecting to SWAP API %s: %s", bzzconfig.SwapApi, err) } - for _, s := range ensAPIs { - if s != "" { - ensClientConfigs = append(ensClientConfigs, parseFlagEnsAPI(s)) - } - } - } - if len(ensClientConfigs) == 0 { - log.Warn("No ENS, please specify non-empty --ens-api to use domain name resolution") } - return swarm.NewSwarm(ctx, swapClient, ensClientConfigs, bzzconfig, swapEnabled, syncEnabled, cors) + return swarm.NewSwarm(ctx, swapClient, bzzconfig) } + //register within the ethereum node if err := stack.Register(boot); err != nil { utils.Fatalf("Failed to register the Swarm service: %v", err) } } -// parseFlagEnsAPI parses EnsAPIFlag according to format -// [tld:][contract-addr@]url and returns ENSClientConfig structure -// with endpoint, contract address and TLD. -func parseFlagEnsAPI(s string) swarm.ENSClientConfig { - isAllLetterString := func(s string) bool { - for _, r := range s { - if !unicode.IsLetter(r) { - return false - } - } - return true - } - endpoint := s - var addr, tld string - if i := strings.Index(endpoint, ":"); i > 0 { - if isAllLetterString(endpoint[:i]) && len(endpoint) > i+2 && endpoint[i+1:i+3] != "//" { - tld = endpoint[:i] - endpoint = endpoint[i+1:] - } - } - if i := strings.Index(endpoint, "@"); i > 0 { - addr = endpoint[:i] - endpoint = endpoint[i+1:] - } - return swarm.ENSClientConfig{ - Endpoint: endpoint, - ContractAddress: addr, - TLD: tld, - } -} - -func getAccount(ctx *cli.Context, stack *node.Node) *ecdsa.PrivateKey { - keyid := ctx.GlobalString(SwarmAccountFlag.Name) - - if keyid == "" { - utils.Fatalf("Option %q is required", SwarmAccountFlag.Name) +func getAccount(bzzaccount string, ctx *cli.Context, stack *node.Node) *ecdsa.PrivateKey { + //an account is mandatory + if bzzaccount == "" { + utils.Fatalf(SWARM_ERR_NO_BZZACCOUNT) } // Try to load the arg as a hex key file. - if key, err := crypto.LoadECDSA(keyid); err == nil { + if key, err := crypto.LoadECDSA(bzzaccount); err == nil { log.Info("Swarm account key loaded", "address", crypto.PubkeyToAddress(key.PublicKey)) return key } @@ -551,7 +478,7 @@ func getAccount(ctx *cli.Context, stack *node.Node) *ecdsa.PrivateKey { am := stack.AccountManager() ks := am.Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - return decryptStoreAccount(ks, keyid, utils.MakePasswordList(ctx)) + return decryptStoreAccount(ks, bzzaccount, utils.MakePasswordList(ctx)) } func decryptStoreAccount(ks *keystore.KeyStore, account string, passwords []string) *ecdsa.PrivateKey { @@ -569,7 +496,7 @@ func decryptStoreAccount(ks *keystore.KeyStore, account string, passwords []stri utils.Fatalf("Can't find swarm account key %s", account) } if err != nil { - utils.Fatalf("Can't find swarm account key: %v", err) + utils.Fatalf("Can't find swarm account key: %v - Is the provided bzzaccount(%s) from the right datadir/Path?", err, account) } keyjson, err := ioutil.ReadFile(a.URL.Path) if err != nil { |