diff options
author | Felix Lange <fjl@users.noreply.github.com> | 2017-04-12 22:27:23 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2017-04-12 22:27:23 +0800 |
commit | 30d706c35e16305e2e3ec0eb6a6bdd6aba50d9d2 (patch) | |
tree | 3ec076154049f1fa71b19fd9b7762085059ff15b /cmd/utils/flags.go | |
parent | b57680b0b21036460c689aab1e82d89297738d50 (diff) | |
download | dexon-30d706c35e16305e2e3ec0eb6a6bdd6aba50d9d2.tar.gz dexon-30d706c35e16305e2e3ec0eb6a6bdd6aba50d9d2.tar.zst dexon-30d706c35e16305e2e3ec0eb6a6bdd6aba50d9d2.zip |
cmd/geth: add --config file flag (#13875)
* p2p/discover, p2p/discv5: add marshaling methods to Node
* p2p/netutil: make Netlist decodable from TOML
* common/math: encode nil HexOrDecimal256 as 0x0
* cmd/geth: add --config file flag
* cmd/geth: add missing license header
* eth: prettify Config again, fix tests
* eth: use gasprice.Config instead of duplicating its fields
* eth/gasprice: hide nil default from dumpconfig output
* cmd/geth: hide genesis block in dumpconfig output
* node: make tests compile
* console: fix tests
* cmd/geth: make TOML keys look exactly like Go struct fields
* p2p: use discovery by default
This makes the zero Config slightly more useful. It also fixes package
node tests because Node detects reuse of the datadir through the
NodeDatabase.
* cmd/geth: make ethstats URL settable through config file
* cmd/faucet: fix configuration
* cmd/geth: dedup attach tests
* eth: add comment for DefaultConfig
* eth: pass downloader.SyncMode in Config
This removes the FastSync, LightSync flags in favour of a more
general SyncMode flag.
* cmd/utils: remove jitvm flags
* cmd/utils: make mutually exclusive flag error prettier
It now reads:
Fatal: flags --dev, --testnet can't be used at the same time
* p2p: fix typo
* node: add DefaultConfig, use it for geth
* mobile: add missing NoDiscovery option
* cmd/utils: drop MakeNode
This exposed a couple of places that needed to be updated to use
node.DefaultConfig.
* node: fix typo
* eth: make fast sync the default mode
* cmd/utils: remove IPCApiFlag (unused)
* node: remove default IPC path
Set it in the frontends instead.
* cmd/geth: add --syncmode
* cmd/utils: make --ipcdisable and --ipcpath mutually exclusive
* cmd/utils: don't enable WS, HTTP when setting addr
* cmd/utils: fix --identity
Diffstat (limited to 'cmd/utils/flags.go')
-rw-r--r-- | cmd/utils/flags.go | 550 |
1 files changed, 301 insertions, 249 deletions
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 0ca407a75..1bd77139c 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -23,7 +23,6 @@ import ( "io/ioutil" "math/big" "os" - "os/user" "path/filepath" "runtime" "strconv" @@ -38,6 +37,8 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/eth/downloader" + "github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethstats" "github.com/ethereum/go-ethereum/event" @@ -45,12 +46,12 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discv5" "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" whisper "github.com/ethereum/go-ethereum/whisper/whisperv2" "gopkg.in/urfave/cli.v1" ) @@ -121,31 +122,32 @@ var ( EthashCachesInMemoryFlag = cli.IntFlag{ Name: "ethash.cachesinmem", Usage: "Number of recent ethash caches to keep in memory (16MB each)", - Value: 2, + Value: eth.DefaultConfig.EthashCachesInMem, } EthashCachesOnDiskFlag = cli.IntFlag{ Name: "ethash.cachesondisk", Usage: "Number of recent ethash caches to keep on disk (16MB each)", - Value: 3, + Value: eth.DefaultConfig.EthashCachesOnDisk, } EthashDatasetDirFlag = DirectoryFlag{ Name: "ethash.dagdir", Usage: "Directory to store the ethash mining DAGs (default = inside home folder)", + Value: DirectoryString{eth.DefaultConfig.EthashDatasetDir}, } EthashDatasetsInMemoryFlag = cli.IntFlag{ Name: "ethash.dagsinmem", Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)", - Value: 1, + Value: eth.DefaultConfig.EthashDatasetsInMem, } EthashDatasetsOnDiskFlag = cli.IntFlag{ Name: "ethash.dagsondisk", Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)", - Value: 2, + Value: eth.DefaultConfig.EthashDatasetsOnDisk, } NetworkIdFlag = cli.IntFlag{ Name: "networkid", Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten)", - Value: eth.NetworkId, + Value: eth.DefaultConfig.NetworkId, } TestNetFlag = cli.BoolFlag{ Name: "testnet", @@ -172,6 +174,13 @@ var ( Name: "light", Usage: "Enable light client mode", } + defaultSyncMode = eth.DefaultConfig.SyncMode + SyncModeFlag = TextMarshalerFlag{ + Name: "syncmode", + Usage: `Blockchain sync mode ("fast", "full", or "light")`, + Value: &defaultSyncMode, + } + LightServFlag = cli.IntFlag{ Name: "lightserv", Usage: "Maximum percentage of time allowed for serving LES requests (0-90)", @@ -238,19 +247,6 @@ var ( Value: "", } - VMForceJitFlag = cli.BoolFlag{ - Name: "forcejit", - Usage: "Force the JIT VM to take precedence", - } - VMJitCacheFlag = cli.IntFlag{ - Name: "jitcache", - Usage: "Amount of cached JIT VM programs", - Value: 64, - } - VMEnableJitFlag = cli.BoolFlag{ - Name: "jitvm", - Usage: "Enable the JIT VM", - } VMEnableDebugFlag = cli.BoolFlag{ Name: "vmdebug", Usage: "Record information useful for VM and contract debugging", @@ -295,21 +291,15 @@ var ( RPCApiFlag = cli.StringFlag{ Name: "rpcapi", Usage: "API's offered over the HTTP-RPC interface", - Value: rpc.DefaultHTTPApis, + Value: "", } IPCDisabledFlag = cli.BoolFlag{ Name: "ipcdisable", Usage: "Disable the IPC-RPC server", } - IPCApiFlag = cli.StringFlag{ - Name: "ipcapi", - Usage: "APIs offered over the IPC-RPC interface", - Value: rpc.DefaultIPCApis, - } IPCPathFlag = DirectoryFlag{ Name: "ipcpath", Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", - Value: DirectoryString{"geth.ipc"}, } WSEnabledFlag = cli.BoolFlag{ Name: "ws", @@ -328,7 +318,7 @@ var ( WSApiFlag = cli.StringFlag{ Name: "wsapi", Usage: "API's offered over the WS-RPC interface", - Value: rpc.DefaultHTTPApis, + Value: "", } WSAllowedOriginsFlag = cli.StringFlag{ Name: "wsorigins", @@ -412,12 +402,12 @@ var ( GpoBlocksFlag = cli.IntFlag{ Name: "gpoblocks", Usage: "Number of recent blocks to check for gas prices", - Value: 10, + Value: eth.DefaultConfig.GPO.Blocks, } GpoPercentileFlag = cli.IntFlag{ Name: "gpopercentile", Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", - Value: 50, + Value: eth.DefaultConfig.GPO.Percentile, } ) @@ -436,88 +426,42 @@ func MakeDataDir(ctx *cli.Context) string { return "" } -// MakeEthashCacheDir returns the directory to use for storing the ethash cache -// dumps. -func MakeEthashCacheDir(ctx *cli.Context) string { - if ctx.GlobalIsSet(EthashCacheDirFlag.Name) && ctx.GlobalString(EthashCacheDirFlag.Name) == "" { - return "" - } - if !ctx.GlobalIsSet(EthashCacheDirFlag.Name) { - return "ethash" - } - return ctx.GlobalString(EthashCacheDirFlag.Name) -} - -// MakeEthashDatasetDir returns the directory to use for storing the full ethash -// dataset dumps. -func MakeEthashDatasetDir(ctx *cli.Context) string { - if !ctx.GlobalIsSet(EthashDatasetDirFlag.Name) { - home := os.Getenv("HOME") - if home == "" { - if user, err := user.Current(); err == nil { - home = user.HomeDir - } - } - if runtime.GOOS == "windows" { - return filepath.Join(home, "AppData", "Ethash") - } - return filepath.Join(home, ".ethash") - } - return ctx.GlobalString(EthashDatasetDirFlag.Name) -} - -// MakeIPCPath creates an IPC path configuration from the set command line flags, -// returning an empty string if IPC was explicitly disabled, or the set path. -func MakeIPCPath(ctx *cli.Context) string { - if ctx.GlobalBool(IPCDisabledFlag.Name) { - return "" - } - return ctx.GlobalString(IPCPathFlag.Name) -} - -// MakeNodeKey creates a node key from set command line flags, either loading it +// setNodeKey creates a node key from set command line flags, either loading it // from a file or as a specified hex value. If neither flags were provided, this // method returns nil and an emphemeral key is to be generated. -func MakeNodeKey(ctx *cli.Context) *ecdsa.PrivateKey { +func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { var ( hex = ctx.GlobalString(NodeKeyHexFlag.Name) file = ctx.GlobalString(NodeKeyFileFlag.Name) - - key *ecdsa.PrivateKey - err error + key *ecdsa.PrivateKey + err error ) switch { case file != "" && hex != "": Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) - case file != "": if key, err = crypto.LoadECDSA(file); err != nil { Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) } - + cfg.PrivateKey = key case hex != "": if key, err = crypto.HexToECDSA(hex); err != nil { Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) } + cfg.PrivateKey = key } - return key } -// makeNodeUserIdent creates the user identifier from CLI flags. -func makeNodeUserIdent(ctx *cli.Context) string { - var comps []string +// setNodeUserIdent creates the user identifier from CLI flags. +func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { - comps = append(comps, identity) + cfg.UserIdent = identity } - if ctx.GlobalBool(VMEnableJitFlag.Name) { - comps = append(comps, "JIT") - } - return strings.Join(comps, "/") } -// MakeBootstrapNodes creates a list of bootstrap nodes from the command line +// setBootstrapNodes creates a list of bootstrap nodes from the command line // flags, reverting to pre-configured ones if none have been specified. -func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node { +func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { urls := params.MainnetBootnodes if ctx.GlobalIsSet(BootnodesFlag.Name) { urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") @@ -525,62 +469,68 @@ func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node { urls = params.TestnetBootnodes } - bootnodes := make([]*discover.Node, 0, len(urls)) + cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls)) for _, url := range urls { node, err := discover.ParseNode(url) if err != nil { log.Error("Bootstrap URL invalid", "enode", url, "err", err) continue } - bootnodes = append(bootnodes, node) + cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) } - return bootnodes } -// MakeBootstrapNodesV5 creates a list of bootstrap nodes from the command line +// setBootstrapNodesV5 creates a list of bootstrap nodes from the command line // flags, reverting to pre-configured ones if none have been specified. -func MakeBootstrapNodesV5(ctx *cli.Context) []*discv5.Node { +func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { urls := params.DiscoveryV5Bootnodes if ctx.GlobalIsSet(BootnodesFlag.Name) { urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") + } else if cfg.BootstrapNodesV5 == nil { + return // already set, don't apply defaults. } - bootnodes := make([]*discv5.Node, 0, len(urls)) + cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls)) for _, url := range urls { node, err := discv5.ParseNode(url) if err != nil { log.Error("Bootstrap URL invalid", "enode", url, "err", err) continue } - bootnodes = append(bootnodes, node) + cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node) } - return bootnodes } -// MakeListenAddress creates a TCP listening address string from set command +// setListenAddress creates a TCP listening address string from set command // line flags. -func MakeListenAddress(ctx *cli.Context) string { - return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) +func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { + if ctx.GlobalIsSet(ListenPortFlag.Name) { + cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) + } } -// MakeDiscoveryV5Address creates a UDP listening address string from set command +// setDiscoveryV5Address creates a UDP listening address string from set command // line flags for the V5 discovery protocol. -func MakeDiscoveryV5Address(ctx *cli.Context) string { - return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)+1) +func setDiscoveryV5Address(ctx *cli.Context, cfg *p2p.Config) { + if ctx.GlobalIsSet(ListenPortFlag.Name) { + cfg.DiscoveryV5Addr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)+1) + } } -// MakeNAT creates a port mapper from set command line flags. -func MakeNAT(ctx *cli.Context) nat.Interface { - natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) - if err != nil { - Fatalf("Option %s: %v", NATFlag.Name, err) +// setNAT creates a port mapper from command line flags. +func setNAT(ctx *cli.Context, cfg *p2p.Config) { + if ctx.GlobalIsSet(NATFlag.Name) { + natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) + if err != nil { + Fatalf("Option %s: %v", NATFlag.Name, err) + } + cfg.NAT = natif } - return natif } -// MakeRPCModules splits input separated by a comma and trims excessive white +// makeRPCModules splits input separated by a comma and trims excessive white // space from the substrings. -func MakeRPCModules(input string) []string { +func makeRPCModules(input string) []string { result := strings.Split(input, ",") for i, r := range result { result[i] = strings.TrimSpace(r) @@ -588,27 +538,63 @@ func MakeRPCModules(input string) []string { return result } -// MakeHTTPRpcHost creates the HTTP RPC listener interface string from the set +// setHTTP creates the HTTP RPC listener interface string from the set // command line flags, returning empty if the HTTP endpoint is disabled. -func MakeHTTPRpcHost(ctx *cli.Context) string { - if !ctx.GlobalBool(RPCEnabledFlag.Name) { - return "" +func setHTTP(ctx *cli.Context, cfg *node.Config) { + if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { + cfg.HTTPHost = "127.0.0.1" + if ctx.GlobalIsSet(RPCListenAddrFlag.Name) { + cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name) + } + } + + if ctx.GlobalIsSet(RPCPortFlag.Name) { + cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name) + } + if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) { + cfg.HTTPCors = ctx.GlobalString(RPCCORSDomainFlag.Name) + } + if ctx.GlobalIsSet(RPCApiFlag.Name) { + cfg.HTTPModules = makeRPCModules(ctx.GlobalString(RPCApiFlag.Name)) } - return ctx.GlobalString(RPCListenAddrFlag.Name) } -// MakeWSRpcHost creates the WebSocket RPC listener interface string from the set +// setWS creates the WebSocket RPC listener interface string from the set // command line flags, returning empty if the HTTP endpoint is disabled. -func MakeWSRpcHost(ctx *cli.Context) string { - if !ctx.GlobalBool(WSEnabledFlag.Name) { - return "" +func setWS(ctx *cli.Context, cfg *node.Config) { + if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { + cfg.WSHost = "127.0.0.1" + if ctx.GlobalIsSet(WSListenAddrFlag.Name) { + cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) + } + } + + if ctx.GlobalIsSet(WSPortFlag.Name) { + cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) + } + if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { + cfg.WSOrigins = ctx.GlobalString(WSAllowedOriginsFlag.Name) + } + if ctx.GlobalIsSet(WSApiFlag.Name) { + cfg.WSModules = makeRPCModules(ctx.GlobalString(WSApiFlag.Name)) + } +} + +// setIPC creates an IPC path configuration from the set command line flags, +// returning an empty string if IPC was explicitly disabled, or the set path. +func setIPC(ctx *cli.Context, cfg *node.Config) { + checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag) + switch { + case ctx.GlobalBool(IPCDisabledFlag.Name): + cfg.IPCPath = "" + case ctx.GlobalIsSet(IPCPathFlag.Name): + cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) } - return ctx.GlobalString(WSListenAddrFlag.Name) } -// MakeDatabaseHandles raises out the number of allowed file handles per process +// makeDatabaseHandles raises out the number of allowed file handles per process // for Geth and returns half of the allowance to assign to the database. -func MakeDatabaseHandles() int { +func makeDatabaseHandles() int { if err := raiseFdLimit(2048); err != nil { Fatalf("Failed to raise file descriptor allowance: %v", err) } @@ -641,33 +627,25 @@ func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error return accs[index], nil } -// MakeEtherbase retrieves the etherbase either from the directly specified +// setEtherbase retrieves the etherbase either from the directly specified // command line flags or from the keystore if CLI indexed. -func MakeEtherbase(ks *keystore.KeyStore, ctx *cli.Context) common.Address { - accounts := ks.Accounts() - if !ctx.GlobalIsSet(EtherbaseFlag.Name) && len(accounts) == 0 { - log.Warn("No etherbase set and no accounts found as default") - return common.Address{} - } - etherbase := ctx.GlobalString(EtherbaseFlag.Name) - if etherbase == "" { - return common.Address{} - } - // If the specified etherbase is a valid address, return it - account, err := MakeAddress(ks, etherbase) - if err != nil { - Fatalf("Option %q: %v", EtherbaseFlag.Name, err) +func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) { + if ctx.GlobalIsSet(EtherbaseFlag.Name) { + account, err := MakeAddress(ks, ctx.GlobalString(EtherbaseFlag.Name)) + if err != nil { + Fatalf("Option %q: %v", EtherbaseFlag.Name, err) + } + cfg.Etherbase = account.Address + return } - return account.Address -} - -// MakeMinerExtra resolves extradata for the miner from the set command line flags -// or returns a default one composed on the client, runtime and OS metadata. -func MakeMinerExtra(extra []byte, ctx *cli.Context) []byte { - if ctx.GlobalIsSet(ExtraDataFlag.Name) { - return []byte(ctx.GlobalString(ExtraDataFlag.Name)) + accounts := ks.Accounts() + if (cfg.Etherbase == common.Address{}) { + if len(accounts) > 0 { + cfg.Etherbase = accounts[0].Address + } else { + log.Warn("No etherbase set and no accounts found as default") + } } - return extra } // MakePasswordList reads password lines from the file specified by --password. @@ -688,144 +666,217 @@ func MakePasswordList(ctx *cli.Context) []string { return lines } -// MakeNode configures a node with no services from command line flags. -func MakeNode(ctx *cli.Context, name, gitCommit string) *node.Node { - vsn := params.Version - if gitCommit != "" { - vsn += "-" + gitCommit[:8] +func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { + setNodeKey(ctx, cfg) + setNAT(ctx, cfg) + setListenAddress(ctx, cfg) + setDiscoveryV5Address(ctx, cfg) + setBootstrapNodes(ctx, cfg) + setBootstrapNodesV5(ctx, cfg) + + if ctx.GlobalIsSet(MaxPeersFlag.Name) { + cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) + } + if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { + cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) + } + if ctx.GlobalIsSet(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name) { + cfg.NoDiscovery = true } - // if we're running a light client or server, force enable the v5 peer discovery unless it is explicitly disabled with --nodiscover - // note that explicitly specifying --v5disc overrides --nodiscover, in which case the later only disables v4 discovery + // if we're running a light client or server, force enable the v5 peer discovery + // unless it is explicitly disabled with --nodiscover note that explicitly specifying + // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery forceV5Discovery := (ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalInt(LightServFlag.Name) > 0) && !ctx.GlobalBool(NoDiscoverFlag.Name) - - config := &node.Config{ - DataDir: MakeDataDir(ctx), - KeyStoreDir: ctx.GlobalString(KeyStoreDirFlag.Name), - UseLightweightKDF: ctx.GlobalBool(LightKDFFlag.Name), - PrivateKey: MakeNodeKey(ctx), - Name: name, - Version: vsn, - UserIdent: makeNodeUserIdent(ctx), - NoDiscovery: ctx.GlobalBool(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name), // always disable v4 discovery in light client mode - DiscoveryV5: ctx.GlobalBool(DiscoveryV5Flag.Name) || forceV5Discovery, - DiscoveryV5Addr: MakeDiscoveryV5Address(ctx), - BootstrapNodes: MakeBootstrapNodes(ctx), - BootstrapNodesV5: MakeBootstrapNodesV5(ctx), - ListenAddr: MakeListenAddress(ctx), - NAT: MakeNAT(ctx), - MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name), - MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name), - IPCPath: MakeIPCPath(ctx), - HTTPHost: MakeHTTPRpcHost(ctx), - HTTPPort: ctx.GlobalInt(RPCPortFlag.Name), - HTTPCors: ctx.GlobalString(RPCCORSDomainFlag.Name), - HTTPModules: MakeRPCModules(ctx.GlobalString(RPCApiFlag.Name)), - WSHost: MakeWSRpcHost(ctx), - WSPort: ctx.GlobalInt(WSPortFlag.Name), - WSOrigins: ctx.GlobalString(WSAllowedOriginsFlag.Name), - WSModules: MakeRPCModules(ctx.GlobalString(WSApiFlag.Name)), - } - if ctx.GlobalBool(DevModeFlag.Name) { - if !ctx.GlobalIsSet(DataDirFlag.Name) { - config.DataDir = filepath.Join(os.TempDir(), "/ethereum_dev_mode") - } - // --dev mode does not need p2p networking. - config.MaxPeers = 0 - config.ListenAddr = ":0" + if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { + cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) + } else if forceV5Discovery { + cfg.DiscoveryV5 = true } + if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { list, err := netutil.ParseNetlist(netrestrict) if err != nil { Fatalf("Option %q: %v", NetrestrictFlag.Name, err) } - config.NetRestrict = list + cfg.NetRestrict = list } - stack, err := node.New(config) - if err != nil { - Fatalf("Failed to create the protocol stack: %v", err) + if ctx.GlobalBool(DevModeFlag.Name) { + // --dev mode can't use p2p networking. + cfg.MaxPeers = 0 + cfg.ListenAddr = ":0" + cfg.NoDiscovery = true + cfg.DiscoveryV5 = false } - return stack } -// RegisterEthService configures eth.Ethereum from command line flags and adds it to the -// given node. -func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) { - // Avoid conflicting network flags - networks, netFlags := 0, []cli.BoolFlag{DevModeFlag, TestNetFlag} - for _, flag := range netFlags { - if ctx.GlobalBool(flag.Name) { - networks++ +// SetNodeConfig applies node-related command line flags to the config. +func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { + SetP2PConfig(ctx, &cfg.P2P) + setIPC(ctx, cfg) + setHTTP(ctx, cfg) + setWS(ctx, cfg) + setNodeUserIdent(ctx, cfg) + + switch { + case ctx.GlobalIsSet(DataDirFlag.Name): + cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) + case ctx.GlobalBool(DevModeFlag.Name): + cfg.DataDir = filepath.Join(os.TempDir(), "ethereum_dev_mode") + case ctx.GlobalBool(TestNetFlag.Name): + cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet") + } + + if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { + cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) + } + if ctx.GlobalIsSet(LightKDFFlag.Name) { + cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name) + } +} + +func setGPO(ctx *cli.Context, cfg *gasprice.Config) { + if ctx.GlobalIsSet(GpoBlocksFlag.Name) { + cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name) + } + if ctx.GlobalIsSet(GpoPercentileFlag.Name) { + cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name) + } +} + +func setEthash(ctx *cli.Context, cfg *eth.Config) { + if ctx.GlobalIsSet(EthashCacheDirFlag.Name) { + cfg.EthashCacheDir = ctx.GlobalString(EthashCacheDirFlag.Name) + } + if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) { + cfg.EthashDatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name) + } + if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) { + cfg.EthashCachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name) + } + if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) { + cfg.EthashCachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name) + } + if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) { + cfg.EthashDatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name) + } + if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) { + cfg.EthashDatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name) + } +} + +func checkExclusive(ctx *cli.Context, flags ...cli.Flag) { + set := make([]string, 0, 1) + for _, flag := range flags { + if ctx.GlobalIsSet(flag.GetName()) { + set = append(set, "--"+flag.GetName()) } } - if networks > 1 { - Fatalf("The %v flags are mutually exclusive", netFlags) + if len(set) > 1 { + Fatalf("flags %v can't be used at the same time", strings.Join(set, ", ")) } +} + +// SetEthConfig applies eth-related command line flags to the config. +func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { + // Avoid conflicting network flags + checkExclusive(ctx, DevModeFlag, TestNetFlag) + checkExclusive(ctx, FastSyncFlag, LightModeFlag, SyncModeFlag) + ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) + setEtherbase(ctx, ks, cfg) + setGPO(ctx, &cfg.GPO) + setEthash(ctx, cfg) + + switch { + case ctx.GlobalIsSet(SyncModeFlag.Name): + cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) + case ctx.GlobalBool(FastSyncFlag.Name): + cfg.SyncMode = downloader.FastSync + case ctx.GlobalBool(LightModeFlag.Name): + cfg.SyncMode = downloader.LightSync + } + if ctx.GlobalIsSet(LightServFlag.Name) { + cfg.LightServ = ctx.GlobalInt(LightServFlag.Name) + } + if ctx.GlobalIsSet(LightPeersFlag.Name) { + cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name) + } + if ctx.GlobalIsSet(NetworkIdFlag.Name) { + cfg.NetworkId = ctx.GlobalInt(NetworkIdFlag.Name) + } + + // Ethereum needs to know maxPeers to calculate the light server peer ratio. + // TODO(fjl): ensure Ethereum can get MaxPeers from node. + cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) + + if ctx.GlobalIsSet(CacheFlag.Name) { + cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) + } + cfg.DatabaseHandles = makeDatabaseHandles() + + if ctx.GlobalIsSet(MinerThreadsFlag.Name) { + cfg.MinerThreads = ctx.GlobalInt(MinerThreadsFlag.Name) + } + if ctx.GlobalIsSet(DocRootFlag.Name) { + cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) + } + if ctx.GlobalIsSet(ExtraDataFlag.Name) { + cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name)) + } + if ctx.GlobalIsSet(GasPriceFlag.Name) { + cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name) + } + + if ctx.GlobalIsSet(SolcPathFlag.Name) { + cfg.SolcPath = ctx.GlobalString(SolcPathFlag.Name) + } + if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { + // TODO(fjl): force-enable this in --dev mode + cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) + } - ethConf := ð.Config{ - Etherbase: MakeEtherbase(ks, ctx), - FastSync: ctx.GlobalBool(FastSyncFlag.Name), - LightMode: ctx.GlobalBool(LightModeFlag.Name), - LightServ: ctx.GlobalInt(LightServFlag.Name), - LightPeers: ctx.GlobalInt(LightPeersFlag.Name), - MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name), - DatabaseCache: ctx.GlobalInt(CacheFlag.Name), - DatabaseHandles: MakeDatabaseHandles(), - NetworkId: ctx.GlobalInt(NetworkIdFlag.Name), - MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name), - ExtraData: MakeMinerExtra(extra, ctx), - DocRoot: ctx.GlobalString(DocRootFlag.Name), - GasPrice: GlobalBig(ctx, GasPriceFlag.Name), - GpoBlocks: ctx.GlobalInt(GpoBlocksFlag.Name), - GpoPercentile: ctx.GlobalInt(GpoPercentileFlag.Name), - SolcPath: ctx.GlobalString(SolcPathFlag.Name), - EthashCacheDir: MakeEthashCacheDir(ctx), - EthashCachesInMem: ctx.GlobalInt(EthashCachesInMemoryFlag.Name), - EthashCachesOnDisk: ctx.GlobalInt(EthashCachesOnDiskFlag.Name), - EthashDatasetDir: MakeEthashDatasetDir(ctx), - EthashDatasetsInMem: ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name), - EthashDatasetsOnDisk: ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name), - EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name), - } - - // Override any default configs in dev mode or the test net + // Override any default configs for --dev and --testnet. switch { case ctx.GlobalBool(TestNetFlag.Name): if !ctx.GlobalIsSet(NetworkIdFlag.Name) { - ethConf.NetworkId = 3 + cfg.NetworkId = 3 } - ethConf.Genesis = core.DefaultTestnetGenesisBlock() + cfg.Genesis = core.DefaultTestnetGenesisBlock() case ctx.GlobalBool(DevModeFlag.Name): - ethConf.Genesis = core.DevGenesisBlock() + cfg.Genesis = core.DevGenesisBlock() if !ctx.GlobalIsSet(GasPriceFlag.Name) { - ethConf.GasPrice = new(big.Int) + cfg.GasPrice = new(big.Int) } - ethConf.PowTest = true + cfg.PowTest = true } - // Override any global options pertaining to the Ethereum protocol + + // TODO(fjl): move trie cache generations into config if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 { state.MaxTrieCacheGen = uint16(gen) } +} - if ethConf.LightMode { - if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - return les.New(ctx, ethConf) - }); err != nil { - Fatalf("Failed to register the Ethereum light node service: %v", err) - } +// RegisterEthService adds an Ethereum client to the stack. +func RegisterEthService(stack *node.Node, cfg *eth.Config) { + var err error + if cfg.SyncMode == downloader.LightSync { + err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { + return les.New(ctx, cfg) + }) } else { - if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { - fullNode, err := eth.New(ctx, ethConf) - if fullNode != nil && ethConf.LightServ > 0 { - ls, _ := les.NewLesServer(fullNode, ethConf) + err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { + fullNode, err := eth.New(ctx, cfg) + if fullNode != nil && cfg.LightServ > 0 { + ls, _ := les.NewLesServer(fullNode, cfg) fullNode.AddLesServer(ls) } return fullNode, err - }); err != nil { - Fatalf("Failed to register the Ethereum full node service: %v", err) - } + }) + } + if err != nil { + Fatalf("Failed to register the Ethereum service: %v", err) } } @@ -855,6 +906,7 @@ func RegisterEthStatsService(stack *node.Node, url string) { // SetupNetwork configures the system for either the main net or some test network. func SetupNetwork(ctx *cli.Context) { + // TODO(fjl): move target gas limit into config params.TargetGasLimit = new(big.Int).SetUint64(ctx.GlobalUint64(TargetGasLimitFlag.Name)) } @@ -870,7 +922,7 @@ func ChainDbName(ctx *cli.Context) string { func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { var ( cache = ctx.GlobalInt(CacheFlag.Name) - handles = MakeDatabaseHandles() + handles = makeDatabaseHandles() name = ChainDbName(ctx) ) |