diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index 98bafb5a92f92a7375637a4b2cce9779c873b4a1..6c47de92c41d3c440c27b7db3777fdfb8df33971 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -14,6 +14,8 @@ import ( godebug "runtime/debug" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/eth/downloader" @@ -611,7 +613,7 @@ func (c *Config) loadChain() error { return nil } -func (c *Config) buildEth() (*ethconfig.Config, error) { +func (c *Config) buildEth(stack *node.Node) (*ethconfig.Config, error) { dbHandles, err := makeDatabaseHandles() if err != nil { return nil, err @@ -665,8 +667,36 @@ func (c *Config) buildEth() (*ethconfig.Config, error) { // update for developer mode if c.Developer.Enabled { + // Get a keystore + var ks *keystore.KeyStore + if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { + ks = keystores[0].(*keystore.KeyStore) + } + + // Create new developer account or reuse existing one + var ( + developer accounts.Account + passphrase string + err error + ) + // etherbase has been set above, configuring the miner address from command line flags. + if n.Miner.Etherbase != (common.Address{}) { + developer = accounts.Account{Address: n.Miner.Etherbase} + } else if accs := ks.Accounts(); len(accs) > 0 { + developer = ks.Accounts()[0] + } else { + developer, err = ks.NewAccount(passphrase) + if err != nil { + Fatalf("Failed to create developer account: %v", err) + } + } + if err := ks.Unlock(developer, passphrase); err != nil { + Fatalf("Failed to unlock developer account: %v", err) + } + log.Info("Using developer account", "address", developer.Address) + // get developer mode chain config - c.chain = chains.GetDeveloperChain(c.Developer.Period, n.Miner.Etherbase) + c.chain = chains.GetDeveloperChain(c.Developer.Period, developer.Address) // update the parameters n.NetworkId = c.chain.NetworkId @@ -841,9 +871,6 @@ func (c *Config) buildNode() (*node.Config, error) { cfg.P2P.ListenAddr = "" cfg.P2P.NoDial = true cfg.P2P.DiscoveryV5 = false - - // data dir - cfg.DataDir = "" } // enable jsonrpc endpoints @@ -864,23 +891,26 @@ func (c *Config) buildNode() (*node.Config, error) { } cfg.P2P.NAT = natif - // Discovery - // if no bootnodes are defined, use the ones from the chain file. - bootnodes := c.P2P.Discovery.Bootnodes - if len(bootnodes) == 0 { - bootnodes = c.chain.Bootnodes - } - if cfg.P2P.BootstrapNodes, err = parseBootnodes(bootnodes); err != nil { - return nil, err - } - if cfg.P2P.BootstrapNodesV5, err = parseBootnodes(c.P2P.Discovery.BootnodesV5); err != nil { - return nil, err - } - if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil { - return nil, err - } - if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil { - return nil, err + // only check for non-developer modes + if !c.Developer.Enabled { + // Discovery + // if no bootnodes are defined, use the ones from the chain file. + bootnodes := c.P2P.Discovery.Bootnodes + if len(bootnodes) == 0 { + bootnodes = c.chain.Bootnodes + } + if cfg.P2P.BootstrapNodes, err = parseBootnodes(bootnodes); err != nil { + return nil, err + } + if cfg.P2P.BootstrapNodesV5, err = parseBootnodes(c.P2P.Discovery.BootnodesV5); err != nil { + return nil, err + } + if cfg.P2P.StaticNodes, err = parseBootnodes(c.P2P.Discovery.StaticNodes); err != nil { + return nil, err + } + if cfg.P2P.TrustedNodes, err = parseBootnodes(c.P2P.Discovery.TrustedNodes); err != nil { + return nil, err + } } if c.P2P.NoDiscover { diff --git a/internal/cli/server/config_test.go b/internal/cli/server/config_test.go index 6383c3e0035d27d3c9e8e63368214080473a8729..62296d82a4d46507da99d410f931bb92c1b71916 100644 --- a/internal/cli/server/config_test.go +++ b/internal/cli/server/config_test.go @@ -16,7 +16,7 @@ func TestConfigDefault(t *testing.T) { _, err := config.buildNode() assert.NoError(t, err) - _, err = config.buildEth() + _, err = config.buildEth(nil) assert.NoError(t, err) } diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go index cb64654a69d715ac6a7926859770705bb8acbf0f..13b143d7c952dd4694b57dac2ea18c9a667a061e 100644 --- a/internal/cli/server/server.go +++ b/internal/cli/server/server.go @@ -7,6 +7,7 @@ import ( "net" "net/http" "os" + "runtime" "strings" "time" @@ -69,11 +70,22 @@ func NewServer(config *Config) (*Server, error) { } srv.node = stack + // setup account manager (only keystore) + { + keydir := stack.KeyStoreDir() + n, p := keystore.StandardScryptN, keystore.StandardScryptP + if config.Accounts.UseLightweightKDF { + n, p = keystore.LightScryptN, keystore.LightScryptP + } + stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p)) + } + // register the ethereum backend - ethCfg, err := config.buildEth() + ethCfg, err := config.buildEth(stack) if err != nil { return nil, err } + backend, err := eth.New(stack, ethCfg) if err != nil { return nil, err @@ -97,16 +109,6 @@ func NewServer(config *Config) (*Server, error) { } } - // setup account manager (only keystore) - { - keydir := stack.KeyStoreDir() - n, p := keystore.StandardScryptN, keystore.StandardScryptP - if config.Accounts.UseLightweightKDF { - n, p = keystore.LightScryptN, keystore.LightScryptP - } - stack.AccountManager().AddBackend(keystore.NewKeyStore(keydir, n, p)) - } - // sealing (if enabled) or in dev mode if config.Sealer.Enabled || config.Developer.Enabled { if err := backend.StartMining(1); err != nil { @@ -283,3 +285,23 @@ func setupLogger(logLevel string) { } log.Root().SetHandler(glogger) } + +// Fatalf formats a message to standard error and exits the program. +// The message is also printed to standard output if standard error +// is redirected to a different file. +func Fatalf(format string, args ...interface{}) { + w := io.MultiWriter(os.Stdout, os.Stderr) + if runtime.GOOS == "windows" { + // The SameFile check below doesn't work on Windows. + // stdout is unlikely to get redirected though, so just print there. + w = os.Stdout + } else { + outf, _ := os.Stdout.Stat() + errf, _ := os.Stderr.Stat() + if outf != nil && errf != nil && os.SameFile(outf, errf) { + w = os.Stderr + } + } + fmt.Fprintf(w, "Fatal: "+format+"\n", args...) + os.Exit(1) +}