|
|
|
// Copyright 2017 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"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"math/big"
|
|
|
|
"os"
|
|
|
|
"reflect"
|
|
|
|
"unicode"
|
|
|
|
|
|
|
|
cli "gopkg.in/urfave/cli.v1"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
|
|
"github.com/ethereum/go-ethereum/dashboard"
|
|
|
|
"github.com/ethereum/go-ethereum/eth"
|
|
|
|
"github.com/ethereum/go-ethereum/node"
|
|
|
|
"github.com/ethereum/go-ethereum/params"
|
|
|
|
whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
|
|
|
|
"github.com/naoina/toml"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
dumpConfigCommand = cli.Command{
|
|
|
|
Action: utils.MigrateFlags(dumpConfig),
|
|
|
|
Name: "dumpconfig",
|
|
|
|
Usage: "Show configuration values",
|
|
|
|
ArgsUsage: "",
|
|
|
|
Flags: append(append(nodeFlags, rpcFlags...), whisperFlags...),
|
|
|
|
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
|
|
|
|
Shh whisper.Config
|
|
|
|
Node node.Config
|
|
|
|
Ethstats ethstatsConfig
|
|
|
|
Dashboard dashboard.Config
|
|
|
|
}
|
|
|
|
|
|
|
|
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, gitDate)
|
|
|
|
cfg.HTTPModules = append(cfg.HTTPModules, "eth", "shh")
|
|
|
|
cfg.WSModules = append(cfg.WSModules, "eth", "shh")
|
|
|
|
cfg.IPCPath = "geth.ipc"
|
|
|
|
return cfg
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
|
|
|
|
// Load defaults.
|
|
|
|
cfg := gethConfig{
|
|
|
|
Eth: eth.DefaultConfig,
|
|
|
|
Shh: whisper.DefaultConfig,
|
|
|
|
Node: defaultNodeConfig(),
|
|
|
|
Dashboard: dashboard.DefaultConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
utils.SetShhConfig(ctx, stack, &cfg.Shh)
|
|
|
|
utils.SetDashboardConfig(ctx, &cfg.Dashboard)
|
|
|
|
|
|
|
|
return stack, cfg
|
|
|
|
}
|
|
|
|
|
|
|
|
// enableWhisper returns true in case one of the whisper flags is set.
|
|
|
|
func enableWhisper(ctx *cli.Context) bool {
|
|
|
|
for _, flag := range whisperFlags {
|
|
|
|
if ctx.GlobalIsSet(flag.GetName()) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeFullNode(ctx *cli.Context) *node.Node {
|
|
|
|
stack, cfg := makeConfigNode(ctx)
|
|
|
|
if ctx.GlobalIsSet(utils.OverrideIstanbulFlag.Name) {
|
|
|
|
cfg.Eth.OverrideIstanbul = new(big.Int).SetUint64(ctx.GlobalUint64(utils.OverrideIstanbulFlag.Name))
|
|
|
|
}
|
|
|
|
utils.RegisterEthService(stack, &cfg.Eth)
|
|
|
|
|
|
|
|
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
|
|
|
|
shhEnabled := enableWhisper(ctx)
|
|
|
|
shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
|
|
|
|
if shhEnabled || shhAutoEnabled {
|
|
|
|
if ctx.GlobalIsSet(utils.WhisperMaxMessageSizeFlag.Name) {
|
|
|
|
cfg.Shh.MaxMessageSize = uint32(ctx.Int(utils.WhisperMaxMessageSizeFlag.Name))
|
|
|
|
}
|
|
|
|
if ctx.GlobalIsSet(utils.WhisperMinPOWFlag.Name) {
|
|
|
|
cfg.Shh.MinimumAcceptedPOW = ctx.Float64(utils.WhisperMinPOWFlag.Name)
|
|
|
|
}
|
|
|
|
if ctx.GlobalIsSet(utils.WhisperRestrictConnectionBetweenLightClientsFlag.Name) {
|
|
|
|
cfg.Shh.RestrictConnectionBetweenLightClients = true
|
|
|
|
}
|
|
|
|
utils.RegisterShhService(stack, &cfg.Shh)
|
|
|
|
}
|
|
|
|
// Configure GraphQL if requested
|
|
|
|
if ctx.GlobalIsSet(utils.GraphQLEnabledFlag.Name) {
|
|
|
|
utils.RegisterGraphQLService(stack, cfg.Node.GraphQLEndpoint(), cfg.Node.GraphQLCors, cfg.Node.GraphQLVirtualHosts, cfg.Node.HTTPTimeouts)
|
|
|
|
}
|
|
|
|
// Add the Ethereum Stats daemon if requested.
|
|
|
|
if cfg.Ethstats.URL != "" {
|
|
|
|
utils.RegisterEthStatsService(stack, cfg.Ethstats.URL)
|
|
|
|
}
|
dashboard: send current block to the dashboard client (#19762)
This adds all dashboard changes from the last couple months.
We're about to remove the dashboard, but decided that we should
get all the recent work in first in case anyone wants to pick up this
project later on.
* cmd, dashboard, eth, p2p: send peer info to the dashboard
* dashboard: update npm packages, improve UI, rebase
* dashboard, p2p: remove println, change doc
* cmd, dashboard, eth, p2p: cleanup after review
* dashboard: send current block to the dashboard client
5 years ago
|
|
|
|
|
|
|
// Add dashboard daemon if requested. This should be the last registered service
|
|
|
|
// in order to be able to collect information about the other services.
|
|
|
|
if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
|
|
|
|
utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
|
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
dump := os.Stdout
|
|
|
|
if ctx.NArg() > 0 {
|
|
|
|
dump, err = os.OpenFile(ctx.Args().Get(0), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer dump.Close()
|
|
|
|
}
|
|
|
|
dump.WriteString(comment)
|
|
|
|
dump.Write(out)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|