cmd/utils, node: create account manager in package node
The account manager was previously created by packge cmd/utils as part of flag processing and then passed down into eth.Ethereum through its config struct. Since we are starting to create nodes which do not have eth.Ethereum as a registered service, the code was rearranged to register the account manager as its own service. Making it a service is ugly though and it doesn't really fix the root cause: creating nodes without eth.Ethereum requires duplicating lots of code. This commit splits utils.MakeSystemNode into three functions, making creation of other node/service configurations easier. It also moves the account manager into Node so it can be used by those configurations without requiring package eth.
This commit is contained in:
@ -27,6 +27,7 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
@ -36,10 +37,11 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
datadirPrivateKey = "nodekey" // Path within the datadir to the node's private key
|
||||
datadirStaticNodes = "static-nodes.json" // Path within the datadir to the static node list
|
||||
datadirTrustedNodes = "trusted-nodes.json" // Path within the datadir to the trusted node list
|
||||
datadirNodeDatabase = "nodes" // Path within the datadir to store the node infos
|
||||
datadirPrivateKey = "nodekey" // Path within the datadir to the node's private key
|
||||
datadirDefaultKeyStore = "keystore" // Path within the datadir to the keystore
|
||||
datadirStaticNodes = "static-nodes.json" // Path within the datadir to the static node list
|
||||
datadirTrustedNodes = "trusted-nodes.json" // Path within the datadir to the trusted node list
|
||||
datadirNodeDatabase = "nodes" // Path within the datadir to store the node infos
|
||||
)
|
||||
|
||||
// Config represents a small collection of configuration values to fine tune the
|
||||
@ -53,6 +55,19 @@ type Config struct {
|
||||
// in memory.
|
||||
DataDir string
|
||||
|
||||
// KeyStoreDir is the file system folder that contains private keys. The directory can
|
||||
// be specified as a relative path, in which case it is resolved relative to the
|
||||
// current directory.
|
||||
//
|
||||
// If KeyStoreDir is empty, the default location is the "keystore" subdirectory of
|
||||
// DataDir. If DataDir is unspecified and KeyStoreDir is empty, an ephemeral directory
|
||||
// is created by New and destroyed when the node is stopped.
|
||||
KeyStoreDir string
|
||||
|
||||
// UseLightweightKDF lowers the memory and CPU requirements of the key store
|
||||
// scrypt KDF at the expense of security.
|
||||
UseLightweightKDF bool
|
||||
|
||||
// IPCPath is the requested location to place the IPC endpoint. If the path is
|
||||
// a simple file name, it is placed inside the data directory (or on the root
|
||||
// pipe path on Windows), whereas if it's a resolvable path name (absolute or
|
||||
@ -278,3 +293,38 @@ func (c *Config) parsePersistentNodes(file string) []*discover.Node {
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
func makeAccountManager(conf *Config) (am *accounts.Manager, ephemeralKeystore string, err error) {
|
||||
scryptN := accounts.StandardScryptN
|
||||
scryptP := accounts.StandardScryptP
|
||||
if conf.UseLightweightKDF {
|
||||
scryptN = accounts.LightScryptN
|
||||
scryptP = accounts.LightScryptP
|
||||
}
|
||||
|
||||
var keydir string
|
||||
switch {
|
||||
case filepath.IsAbs(conf.KeyStoreDir):
|
||||
keydir = conf.KeyStoreDir
|
||||
case conf.DataDir != "":
|
||||
if conf.KeyStoreDir == "" {
|
||||
keydir = filepath.Join(conf.DataDir, datadirDefaultKeyStore)
|
||||
} else {
|
||||
keydir, err = filepath.Abs(conf.KeyStoreDir)
|
||||
}
|
||||
case conf.KeyStoreDir != "":
|
||||
keydir, err = filepath.Abs(conf.KeyStoreDir)
|
||||
default:
|
||||
// There is no datadir.
|
||||
keydir, err = ioutil.TempDir("", "go-ethereum-keystore")
|
||||
ephemeralKeystore = keydir
|
||||
}
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if err := os.MkdirAll(keydir, 0700); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return accounts.NewManager(keydir, scryptN, scryptP), ephemeralKeystore, nil
|
||||
}
|
||||
|
34
node/node.go
34
node/node.go
@ -26,6 +26,7 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/internal/debug"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
@ -49,6 +50,9 @@ type Node struct {
|
||||
datadir string // Path to the currently used data directory
|
||||
eventmux *event.TypeMux // Event multiplexer used between the services of a stack
|
||||
|
||||
accman *accounts.Manager
|
||||
ephemeralKeystore string // if non-empty, the key directory that will be removed by Stop
|
||||
|
||||
serverConfig p2p.Config
|
||||
server *p2p.Server // Currently running P2P networking layer
|
||||
|
||||
@ -90,13 +94,20 @@ func New(conf *Config) (*Node, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
am, ephemeralKeystore, err := makeAccountManager(conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Assemble the networking layer and the node itself
|
||||
nodeDbPath := ""
|
||||
if conf.DataDir != "" {
|
||||
nodeDbPath = filepath.Join(conf.DataDir, datadirNodeDatabase)
|
||||
}
|
||||
return &Node{
|
||||
datadir: conf.DataDir,
|
||||
datadir: conf.DataDir,
|
||||
accman: am,
|
||||
ephemeralKeystore: ephemeralKeystore,
|
||||
serverConfig: p2p.Config{
|
||||
PrivateKey: conf.NodeKey(),
|
||||
Name: conf.Name,
|
||||
@ -156,9 +167,10 @@ func (n *Node) Start() error {
|
||||
for _, constructor := range n.serviceFuncs {
|
||||
// Create a new context for the particular service
|
||||
ctx := &ServiceContext{
|
||||
datadir: n.datadir,
|
||||
services: make(map[reflect.Type]Service),
|
||||
EventMux: n.eventmux,
|
||||
datadir: n.datadir,
|
||||
services: make(map[reflect.Type]Service),
|
||||
EventMux: n.eventmux,
|
||||
AccountManager: n.accman,
|
||||
}
|
||||
for kind, s := range services { // copy needed for threaded access
|
||||
ctx.services[kind] = s
|
||||
@ -473,9 +485,18 @@ func (n *Node) Stop() error {
|
||||
n.server = nil
|
||||
close(n.stop)
|
||||
|
||||
// Remove the keystore if it was created ephemerally.
|
||||
var keystoreErr error
|
||||
if n.ephemeralKeystore != "" {
|
||||
keystoreErr = os.RemoveAll(n.ephemeralKeystore)
|
||||
}
|
||||
|
||||
if len(failure.Services) > 0 {
|
||||
return failure
|
||||
}
|
||||
if keystoreErr != nil {
|
||||
return keystoreErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -548,6 +569,11 @@ func (n *Node) DataDir() string {
|
||||
return n.datadir
|
||||
}
|
||||
|
||||
// AccountManager retrieves the account manager used by the protocol stack.
|
||||
func (n *Node) AccountManager() *accounts.Manager {
|
||||
return n.accman
|
||||
}
|
||||
|
||||
// IPCEndpoint retrieves the current IPC endpoint used by the protocol stack.
|
||||
func (n *Node) IPCEndpoint() string {
|
||||
return n.ipcEndpoint
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
@ -30,9 +31,10 @@ import (
|
||||
// the protocol stack, that is passed to all constructors to be optionally used;
|
||||
// as well as utility methods to operate on the service environment.
|
||||
type ServiceContext struct {
|
||||
datadir string // Data directory for protocol persistence
|
||||
services map[reflect.Type]Service // Index of the already constructed services
|
||||
EventMux *event.TypeMux // Event multiplexer used for decoupled notifications
|
||||
datadir string // Data directory for protocol persistence
|
||||
services map[reflect.Type]Service // Index of the already constructed services
|
||||
EventMux *event.TypeMux // Event multiplexer used for decoupled notifications
|
||||
AccountManager *accounts.Manager // Account manager created by the node.
|
||||
}
|
||||
|
||||
// OpenDatabase opens an existing database with the given name (or creates one
|
||||
|
Reference in New Issue
Block a user