Skip to content

Commit

Permalink
cmd/geth: add --config file flag (ethereum#13875)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
fjl authored and karalabe committed Apr 12, 2017
1 parent b57680b commit 30d706c
Show file tree
Hide file tree
Showing 55 changed files with 6,615 additions and 648 deletions.
39 changes: 19 additions & 20 deletions cmd/faucet/faucet.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethstats"
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/log"
"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"
Expand Down Expand Up @@ -175,32 +177,29 @@ type faucet struct {
func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network int, stats string, ks *keystore.KeyStore, index []byte) (*faucet, error) {
// Assemble the raw devp2p protocol stack
stack, err := node.New(&node.Config{
Name: "geth",
Version: params.Version,
DataDir: filepath.Join(os.Getenv("HOME"), ".faucet"),
NAT: nat.Any(),
DiscoveryV5: true,
ListenAddr: fmt.Sprintf(":%d", port),
DiscoveryV5Addr: fmt.Sprintf(":%d", port+1),
MaxPeers: 25,
BootstrapNodesV5: enodes,
Name: "geth",
Version: params.Version,
DataDir: filepath.Join(os.Getenv("HOME"), ".faucet"),
P2P: p2p.Config{
NAT: nat.Any(),
NoDiscovery: true,
DiscoveryV5: true,
ListenAddr: fmt.Sprintf(":%d", port),
DiscoveryV5Addr: fmt.Sprintf(":%d", port+1),
MaxPeers: 25,
BootstrapNodesV5: enodes,
},
})
if err != nil {
return nil, err
}
// Assemble the Ethereum light client protocol
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return les.New(ctx, &eth.Config{
LightMode: true,
NetworkId: network,
Genesis: genesis,
GasPrice: big.NewInt(20 * params.Shannon),
GpoBlocks: 10,
GpoPercentile: 50,
EthashCacheDir: "ethash",
EthashCachesInMem: 2,
EthashCachesOnDisk: 3,
})
cfg := eth.DefaultConfig
cfg.SyncMode = downloader.LightSync
cfg.NetworkId = network
cfg.Genesis = genesis
return les.New(ctx, &cfg)
}); err != nil {
return nil, err
}
Expand Down
11 changes: 5 additions & 6 deletions cmd/geth/accountcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,7 @@ nodes.
)

func accountList(ctx *cli.Context) error {
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)

stack, _ := makeConfigNode(ctx)
var index int
for _, wallet := range stack.AccountManager().Wallets() {
for _, account := range wallet.Accounts() {
Expand Down Expand Up @@ -278,7 +277,7 @@ func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrErr

// accountCreate creates a new account into the keystore defined by the CLI flags.
func accountCreate(ctx *cli.Context) error {
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
stack, _ := makeConfigNode(ctx)
password := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx))

ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
Expand All @@ -296,7 +295,7 @@ func accountUpdate(ctx *cli.Context) error {
if len(ctx.Args()) == 0 {
utils.Fatalf("No accounts specified to update")
}
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
stack, _ := makeConfigNode(ctx)
ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)

account, oldPassword := unlockAccount(ctx, ks, ctx.Args().First(), 0, nil)
Expand All @@ -317,7 +316,7 @@ func importWallet(ctx *cli.Context) error {
utils.Fatalf("Could not read wallet file: %v", err)
}

stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
stack, _ := makeConfigNode(ctx)
passphrase := getPassPhrase("", false, 0, utils.MakePasswordList(ctx))

ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
Expand All @@ -338,7 +337,7 @@ func accountImport(ctx *cli.Context) error {
if err != nil {
utils.Fatalf("Failed to load the private key: %v", err)
}
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
stack, _ := makeConfigNode(ctx)
passphrase := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx))

ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
Expand Down
2 changes: 1 addition & 1 deletion cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ func exportChain(ctx *cli.Context) error {
}

func removeDB(ctx *cli.Context) error {
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
stack, _ := makeConfigNode(ctx)
dbdir := stack.ResolvePath(utils.ChainDbName(ctx))
if !common.FileExist(dbdir) {
fmt.Println(dbdir, "does not exist")
Expand Down
186 changes: 186 additions & 0 deletions cmd/geth/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.

package main

import (
"bufio"
"encoding/hex"
"errors"
"fmt"
"io"
"os"
"reflect"
"unicode"

cli "gopkg.in/urfave/cli.v1"

"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/contracts/release"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/naoina/toml"
)

var (
dumpConfigCommand = cli.Command{
Action: dumpConfig,
Name: "dumpconfig",
Usage: "Show configuration values",
ArgsUsage: "",
Category: "MISCELLANEOUS COMMANDS",
Description: `The dumpconfig command shows configuration values.`,
}

configFileFlag = cli.StringFlag{
Name: "config",
Usage: "TOML configuration file",
}
)

// These settings ensure that TOML keys use the same names as Go struct fields.
var tomlSettings = toml.Config{
NormFieldName: func(rt reflect.Type, key string) string {
return key
},
FieldToKey: func(rt reflect.Type, field string) string {
return field
},
MissingField: func(rt reflect.Type, field string) error {
link := ""
if unicode.IsUpper(rune(rt.Name()[0])) && rt.PkgPath() != "main" {
link = fmt.Sprintf(", see https://godoc.org/%s#%s for available fields", rt.PkgPath(), rt.Name())
}
return fmt.Errorf("field '%s' is not defined in %s%s", field, rt.String(), link)
},
}

type ethstatsConfig struct {
URL string `toml:",omitempty"`
}

type gethConfig struct {
Eth eth.Config
Node node.Config
Ethstats ethstatsConfig
}

func loadConfig(file string, cfg *gethConfig) error {
f, err := os.Open(file)
if err != nil {
return err
}
defer f.Close()

err = tomlSettings.NewDecoder(bufio.NewReader(f)).Decode(cfg)
// Add file name to errors that have a line number.
if _, ok := err.(*toml.LineError); ok {
err = errors.New(file + ", " + err.Error())
}
return err
}

func defaultNodeConfig() node.Config {
cfg := node.DefaultConfig
cfg.Name = clientIdentifier
cfg.Version = params.VersionWithCommit(gitCommit)
cfg.HTTPModules = append(cfg.HTTPModules, "eth")
cfg.WSModules = append(cfg.WSModules, "eth")
cfg.IPCPath = "geth.ipc"
return cfg
}

func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
// Load defaults.
cfg := gethConfig{
Eth: eth.DefaultConfig,
Node: defaultNodeConfig(),
}

// Load config file.
if file := ctx.GlobalString(configFileFlag.Name); file != "" {
if err := loadConfig(file, &cfg); err != nil {
utils.Fatalf("%v", err)
}
}

// Apply flags.
utils.SetNodeConfig(ctx, &cfg.Node)
stack, err := node.New(&cfg.Node)
if err != nil {
utils.Fatalf("Failed to create the protocol stack: %v", err)
}
utils.SetEthConfig(ctx, stack, &cfg.Eth)
if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) {
cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name)
}

return stack, cfg
}

func makeFullNode(ctx *cli.Context) *node.Node {
stack, cfg := makeConfigNode(ctx)

utils.RegisterEthService(stack, &cfg.Eth)

// Whisper must be explicitly enabled, but is auto-enabled in --dev mode.
shhEnabled := ctx.GlobalBool(utils.WhisperEnabledFlag.Name)
shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DevModeFlag.Name)
if shhEnabled || shhAutoEnabled {
utils.RegisterShhService(stack)
}

// Add the Ethereum Stats daemon if requested.
if cfg.Ethstats.URL != "" {
utils.RegisterEthStatsService(stack, cfg.Ethstats.URL)
}

// Add the release oracle service so it boots along with node.
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
config := release.Config{
Oracle: relOracle,
Major: uint32(params.VersionMajor),
Minor: uint32(params.VersionMinor),
Patch: uint32(params.VersionPatch),
}
commit, _ := hex.DecodeString(gitCommit)
copy(config.Commit[:], commit)
return release.NewReleaseService(ctx, config)
}); err != nil {
utils.Fatalf("Failed to register the Geth release oracle service: %v", err)
}
return stack
}

// dumpConfig is the dumpconfig command.
func dumpConfig(ctx *cli.Context) error {
_, cfg := makeConfigNode(ctx)
comment := ""

if cfg.Eth.Genesis != nil {
cfg.Eth.Genesis = nil
comment += "# Note: this config doesn't contain the genesis block.\n\n"
}

out, err := tomlSettings.Marshal(&cfg)
if err != nil {
return err
}
io.WriteString(os.Stdout, comment)
os.Stdout.Write(out)
return nil
}
Loading

0 comments on commit 30d706c

Please sign in to comment.