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:
parent
d6625ac34d
commit
312263c7d9
@ -34,8 +34,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -342,23 +340,3 @@ func zeroKey(k *ecdsa.PrivateKey) {
|
|||||||
b[i] = 0
|
b[i] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIs implements node.Service
|
|
||||||
func (am *Manager) APIs() []rpc.API {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protocols implements node.Service
|
|
||||||
func (am *Manager) Protocols() []p2p.Protocol {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start implements node.Service
|
|
||||||
func (am *Manager) Start(srvr *p2p.Server) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop implements node.Service
|
|
||||||
func (am *Manager) Stop() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -168,8 +168,8 @@ nodes.
|
|||||||
)
|
)
|
||||||
|
|
||||||
func accountList(ctx *cli.Context) error {
|
func accountList(ctx *cli.Context) error {
|
||||||
accman := utils.MakeAccountManager(ctx)
|
stack := utils.MakeNode(ctx, clientIdentifier, verString)
|
||||||
for i, acct := range accman.Accounts() {
|
for i, acct := range stack.AccountManager().Accounts() {
|
||||||
fmt.Printf("Account #%d: {%x} %s\n", i, acct.Address, acct.File)
|
fmt.Printf("Account #%d: {%x} %s\n", i, acct.Address, acct.File)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -261,10 +261,10 @@ func ambiguousAddrRecovery(am *accounts.Manager, err *accounts.AmbiguousAddrErro
|
|||||||
|
|
||||||
// accountCreate creates a new account into the keystore defined by the CLI flags.
|
// accountCreate creates a new account into the keystore defined by the CLI flags.
|
||||||
func accountCreate(ctx *cli.Context) error {
|
func accountCreate(ctx *cli.Context) error {
|
||||||
accman := utils.MakeAccountManager(ctx)
|
stack := utils.MakeNode(ctx, clientIdentifier, verString)
|
||||||
password := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(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))
|
||||||
|
|
||||||
account, err := accman.NewAccount(password)
|
account, err := stack.AccountManager().NewAccount(password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to create account: %v", err)
|
utils.Fatalf("Failed to create account: %v", err)
|
||||||
}
|
}
|
||||||
@ -278,11 +278,10 @@ func accountUpdate(ctx *cli.Context) error {
|
|||||||
if len(ctx.Args()) == 0 {
|
if len(ctx.Args()) == 0 {
|
||||||
utils.Fatalf("No accounts specified to update")
|
utils.Fatalf("No accounts specified to update")
|
||||||
}
|
}
|
||||||
accman := utils.MakeAccountManager(ctx)
|
stack := utils.MakeNode(ctx, clientIdentifier, verString)
|
||||||
|
account, oldPassword := unlockAccount(ctx, stack.AccountManager(), ctx.Args().First(), 0, nil)
|
||||||
account, oldPassword := unlockAccount(ctx, accman, ctx.Args().First(), 0, nil)
|
|
||||||
newPassword := getPassPhrase("Please give a new password. Do not forget this password.", true, 0, nil)
|
newPassword := getPassPhrase("Please give a new password. Do not forget this password.", true, 0, nil)
|
||||||
if err := accman.Update(account, oldPassword, newPassword); err != nil {
|
if err := stack.AccountManager().Update(account, oldPassword, newPassword); err != nil {
|
||||||
utils.Fatalf("Could not update the account: %v", err)
|
utils.Fatalf("Could not update the account: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -298,10 +297,9 @@ func importWallet(ctx *cli.Context) error {
|
|||||||
utils.Fatalf("Could not read wallet file: %v", err)
|
utils.Fatalf("Could not read wallet file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
accman := utils.MakeAccountManager(ctx)
|
stack := utils.MakeNode(ctx, clientIdentifier, verString)
|
||||||
passphrase := getPassPhrase("", false, 0, utils.MakePasswordList(ctx))
|
passphrase := getPassPhrase("", false, 0, utils.MakePasswordList(ctx))
|
||||||
|
acct, err := stack.AccountManager().ImportPreSaleKey(keyJson, passphrase)
|
||||||
acct, err := accman.ImportPreSaleKey(keyJson, passphrase)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
@ -318,9 +316,9 @@ func accountImport(ctx *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to load the private key: %v", err)
|
utils.Fatalf("Failed to load the private key: %v", err)
|
||||||
}
|
}
|
||||||
accman := utils.MakeAccountManager(ctx)
|
stack := utils.MakeNode(ctx, clientIdentifier, verString)
|
||||||
passphrase := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(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))
|
||||||
acct, err := accman.ImportECDSA(key, passphrase)
|
acct, err := stack.AccountManager().ImportECDSA(key, passphrase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Could not create the account: %v", err)
|
utils.Fatalf("Could not create the account: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
|
|||||||
// same time.
|
// same time.
|
||||||
func localConsole(ctx *cli.Context) error {
|
func localConsole(ctx *cli.Context) error {
|
||||||
// Create and start the node based on the CLI flags
|
// Create and start the node based on the CLI flags
|
||||||
node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
|
node := makeFullNode(ctx)
|
||||||
startNode(ctx, node)
|
startNode(ctx, node)
|
||||||
defer node.Stop()
|
defer node.Stop()
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ func dialRPC(endpoint string) (*rpc.Client, error) {
|
|||||||
// everything down.
|
// everything down.
|
||||||
func ephemeralConsole(ctx *cli.Context) error {
|
func ephemeralConsole(ctx *cli.Context) error {
|
||||||
// Create and start the node based on the CLI flags
|
// Create and start the node based on the CLI flags
|
||||||
node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
|
node := makeFullNode(ctx)
|
||||||
startNode(ctx, node)
|
startNode(ctx, node)
|
||||||
defer node.Stop()
|
defer node.Stop()
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/ethash"
|
"github.com/ethereum/ethash"
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console"
|
||||||
@ -244,34 +243,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeDefaultExtra() []byte {
|
|
||||||
var clientInfo = struct {
|
|
||||||
Version uint
|
|
||||||
Name string
|
|
||||||
GoVersion string
|
|
||||||
Os string
|
|
||||||
}{uint(versionMajor<<16 | versionMinor<<8 | versionPatch), clientIdentifier, runtime.Version(), runtime.GOOS}
|
|
||||||
extra, err := rlp.EncodeToBytes(clientInfo)
|
|
||||||
if err != nil {
|
|
||||||
glog.V(logger.Warn).Infoln("error setting canonical miner information:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
|
|
||||||
glog.V(logger.Warn).Infoln("error setting canonical miner information: extra exceeds", params.MaximumExtraDataSize)
|
|
||||||
glog.V(logger.Debug).Infof("extra: %x\n", extra)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return extra
|
|
||||||
}
|
|
||||||
|
|
||||||
// geth is the main entry point into the system if no special subcommand is ran.
|
// geth is the main entry point into the system if no special subcommand is ran.
|
||||||
// It creates a default node based on the command line arguments and runs it in
|
// It creates a default node based on the command line arguments and runs it in
|
||||||
// blocking mode, waiting for it to be shut down.
|
// blocking mode, waiting for it to be shut down.
|
||||||
func geth(ctx *cli.Context) error {
|
func geth(ctx *cli.Context) error {
|
||||||
node := utils.MakeSystemNode(clientIdentifier, verString, relConfig, makeDefaultExtra(), ctx)
|
node := makeFullNode(ctx)
|
||||||
startNode(ctx, node)
|
startNode(ctx, node)
|
||||||
node.Wait()
|
node.Wait()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,6 +279,38 @@ func initGenesis(ctx *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeFullNode(ctx *cli.Context) *node.Node {
|
||||||
|
node := utils.MakeNode(ctx, clientIdentifier, verString)
|
||||||
|
utils.RegisterEthService(ctx, node, relConfig, makeDefaultExtra())
|
||||||
|
// 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(node)
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeDefaultExtra() []byte {
|
||||||
|
var clientInfo = struct {
|
||||||
|
Version uint
|
||||||
|
Name string
|
||||||
|
GoVersion string
|
||||||
|
Os string
|
||||||
|
}{uint(versionMajor<<16 | versionMinor<<8 | versionPatch), clientIdentifier, runtime.Version(), runtime.GOOS}
|
||||||
|
extra, err := rlp.EncodeToBytes(clientInfo)
|
||||||
|
if err != nil {
|
||||||
|
glog.V(logger.Warn).Infoln("error setting canonical miner information:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
|
||||||
|
glog.V(logger.Warn).Infoln("error setting canonical miner information: extra exceeds", params.MaximumExtraDataSize)
|
||||||
|
glog.V(logger.Debug).Infof("extra: %x\n", extra)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return extra
|
||||||
|
}
|
||||||
|
|
||||||
// startNode boots up the system node and all registered protocols, after which
|
// startNode boots up the system node and all registered protocols, after which
|
||||||
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
|
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
|
||||||
// miner.
|
// miner.
|
||||||
@ -311,12 +321,8 @@ func startNode(ctx *cli.Context, stack *node.Node) {
|
|||||||
utils.StartNode(stack)
|
utils.StartNode(stack)
|
||||||
|
|
||||||
// Unlock any account specifically requested
|
// Unlock any account specifically requested
|
||||||
var accman *accounts.Manager
|
accman := stack.AccountManager()
|
||||||
if err := stack.Service(&accman); err != nil {
|
|
||||||
utils.Fatalf("ethereum service not running: %v", err)
|
|
||||||
}
|
|
||||||
passwords := utils.MakePasswordList(ctx)
|
passwords := utils.MakePasswordList(ctx)
|
||||||
|
|
||||||
accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
|
accounts := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
|
||||||
for i, account := range accounts {
|
for i, account := range accounts {
|
||||||
if trimmed := strings.TrimSpace(account); trimmed != "" {
|
if trimmed := strings.TrimSpace(account); trimmed != "" {
|
||||||
|
@ -19,12 +19,10 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
@ -61,14 +59,8 @@ func main() {
|
|||||||
if !found {
|
if !found {
|
||||||
log.Fatalf("Requested test (%s) not found within suite", *testName)
|
log.Fatalf("Requested test (%s) not found within suite", *testName)
|
||||||
}
|
}
|
||||||
// Create the protocol stack to run the test with
|
|
||||||
keydir, err := ioutil.TempDir("", "")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to create temporary keystore directory: %v", err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(keydir)
|
|
||||||
|
|
||||||
stack, err := MakeSystemNode(keydir, *testKey, test)
|
stack, err := MakeSystemNode(*testKey, test)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to assemble test stack: %v", err)
|
log.Fatalf("Failed to assemble test stack: %v", err)
|
||||||
}
|
}
|
||||||
@ -92,9 +84,10 @@ func main() {
|
|||||||
|
|
||||||
// MakeSystemNode configures a protocol stack for the RPC tests based on a given
|
// MakeSystemNode configures a protocol stack for the RPC tests based on a given
|
||||||
// keystore path and initial pre-state.
|
// keystore path and initial pre-state.
|
||||||
func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node.Node, error) {
|
func MakeSystemNode(privkey string, test *tests.BlockTest) (*node.Node, error) {
|
||||||
// Create a networkless protocol stack
|
// Create a networkless protocol stack
|
||||||
stack, err := node.New(&node.Config{
|
stack, err := node.New(&node.Config{
|
||||||
|
UseLightweightKDF: true,
|
||||||
IPCPath: node.DefaultIPCEndpoint(),
|
IPCPath: node.DefaultIPCEndpoint(),
|
||||||
HTTPHost: common.DefaultHTTPHost,
|
HTTPHost: common.DefaultHTTPHost,
|
||||||
HTTPPort: common.DefaultHTTPPort,
|
HTTPPort: common.DefaultHTTPPort,
|
||||||
@ -108,7 +101,7 @@ func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Create the keystore and inject an unlocked account if requested
|
// Create the keystore and inject an unlocked account if requested
|
||||||
accman := accounts.NewPlaintextManager(keydir)
|
accman := stack.AccountManager()
|
||||||
if len(privkey) > 0 {
|
if len(privkey) > 0 {
|
||||||
key, err := crypto.HexToECDSA(privkey)
|
key, err := crypto.HexToECDSA(privkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -131,7 +124,6 @@ func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node
|
|||||||
TestGenesisState: db,
|
TestGenesisState: db,
|
||||||
TestGenesisBlock: test.Genesis,
|
TestGenesisBlock: test.Genesis,
|
||||||
ChainConfig: &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock},
|
ChainConfig: &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock},
|
||||||
AccountManager: accman,
|
|
||||||
}
|
}
|
||||||
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil {
|
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -413,16 +413,6 @@ func MustMakeDataDir(ctx *cli.Context) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeKeyStoreDir resolves the folder to use for storing the account keys from the
|
|
||||||
// set command line flags, returning the explicitly requested path, or one inside
|
|
||||||
// the data directory otherwise.
|
|
||||||
func MakeKeyStoreDir(datadir string, ctx *cli.Context) string {
|
|
||||||
if path := ctx.GlobalString(KeyStoreDirFlag.Name); path != "" {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
return filepath.Join(datadir, "keystore")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeIPCPath creates an IPC path configuration from the set command line flags,
|
// 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.
|
// returning an empty string if IPC was explicitly disabled, or the set path.
|
||||||
func MakeIPCPath(ctx *cli.Context) string {
|
func MakeIPCPath(ctx *cli.Context) string {
|
||||||
@ -555,20 +545,6 @@ func MakeDatabaseHandles() int {
|
|||||||
return limit / 2 // Leave half for networking and other stuff
|
return limit / 2 // Leave half for networking and other stuff
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeAccountManager creates an account manager from set command line flags.
|
|
||||||
func MakeAccountManager(ctx *cli.Context) *accounts.Manager {
|
|
||||||
// Create the keystore crypto primitive, light if requested
|
|
||||||
scryptN := accounts.StandardScryptN
|
|
||||||
scryptP := accounts.StandardScryptP
|
|
||||||
if ctx.GlobalBool(LightKDFFlag.Name) {
|
|
||||||
scryptN = accounts.LightScryptN
|
|
||||||
scryptP = accounts.LightScryptP
|
|
||||||
}
|
|
||||||
datadir := MustMakeDataDir(ctx)
|
|
||||||
keydir := MakeKeyStoreDir(datadir, ctx)
|
|
||||||
return accounts.NewManager(keydir, scryptN, scryptP)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MakeAddress converts an account specified directly as a hex encoded string or
|
// MakeAddress converts an account specified directly as a hex encoded string or
|
||||||
// a key index in the key store to an internal account representation.
|
// a key index in the key store to an internal account representation.
|
||||||
func MakeAddress(accman *accounts.Manager, account string) (accounts.Account, error) {
|
func MakeAddress(accman *accounts.Manager, account string) (accounts.Account, error) {
|
||||||
@ -631,22 +607,12 @@ func MakePasswordList(ctx *cli.Context) []string {
|
|||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeSystemNode sets up a local node, configures the services to launch and
|
// MakeNode configures a node with no services from command line flags.
|
||||||
// assembles the P2P protocol stack.
|
func MakeNode(ctx *cli.Context, name, version string) *node.Node {
|
||||||
func MakeSystemNode(name, version string, relconf release.Config, extra []byte, ctx *cli.Context) *node.Node {
|
config := &node.Config{
|
||||||
// Avoid conflicting network flags
|
|
||||||
networks, netFlags := 0, []cli.BoolFlag{DevModeFlag, TestNetFlag, OlympicFlag}
|
|
||||||
for _, flag := range netFlags {
|
|
||||||
if ctx.GlobalBool(flag.Name) {
|
|
||||||
networks++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if networks > 1 {
|
|
||||||
Fatalf("The %v flags are mutually exclusive", netFlags)
|
|
||||||
}
|
|
||||||
// Configure the node's service container
|
|
||||||
stackConf := &node.Config{
|
|
||||||
DataDir: MustMakeDataDir(ctx),
|
DataDir: MustMakeDataDir(ctx),
|
||||||
|
KeyStoreDir: ctx.GlobalString(KeyStoreDirFlag.Name),
|
||||||
|
UseLightweightKDF: ctx.GlobalBool(LightKDFFlag.Name),
|
||||||
PrivateKey: MakeNodeKey(ctx),
|
PrivateKey: MakeNodeKey(ctx),
|
||||||
Name: MakeNodeName(name, version, ctx),
|
Name: MakeNodeName(name, version, ctx),
|
||||||
NoDiscovery: ctx.GlobalBool(NoDiscoverFlag.Name),
|
NoDiscovery: ctx.GlobalBool(NoDiscoverFlag.Name),
|
||||||
@ -665,8 +631,34 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
|
|||||||
WSOrigins: ctx.GlobalString(WSAllowedOriginsFlag.Name),
|
WSOrigins: ctx.GlobalString(WSAllowedOriginsFlag.Name),
|
||||||
WSModules: MakeRPCModules(ctx.GlobalString(WSApiFlag.Name)),
|
WSModules: MakeRPCModules(ctx.GlobalString(WSApiFlag.Name)),
|
||||||
}
|
}
|
||||||
// Configure the Ethereum service
|
if ctx.GlobalBool(DevModeFlag.Name) {
|
||||||
accman := MakeAccountManager(ctx)
|
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"
|
||||||
|
}
|
||||||
|
stack, err := node.New(config)
|
||||||
|
if err != nil {
|
||||||
|
Fatalf("Failed to create the protocol stack: %v", err)
|
||||||
|
}
|
||||||
|
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, relconf release.Config, extra []byte) {
|
||||||
|
// Avoid conflicting network flags
|
||||||
|
networks, netFlags := 0, []cli.BoolFlag{DevModeFlag, TestNetFlag, OlympicFlag}
|
||||||
|
for _, flag := range netFlags {
|
||||||
|
if ctx.GlobalBool(flag.Name) {
|
||||||
|
networks++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if networks > 1 {
|
||||||
|
Fatalf("The %v flags are mutually exclusive", netFlags)
|
||||||
|
}
|
||||||
|
|
||||||
// initialise new random number generator
|
// initialise new random number generator
|
||||||
rand := rand.New(rand.NewSource(time.Now().UnixNano()))
|
rand := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
@ -679,14 +671,13 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ethConf := ð.Config{
|
ethConf := ð.Config{
|
||||||
|
Etherbase: MakeEtherbase(stack.AccountManager(), ctx),
|
||||||
ChainConfig: MustMakeChainConfig(ctx),
|
ChainConfig: MustMakeChainConfig(ctx),
|
||||||
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
|
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
|
||||||
BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
|
BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
|
||||||
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
|
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
|
||||||
DatabaseHandles: MakeDatabaseHandles(),
|
DatabaseHandles: MakeDatabaseHandles(),
|
||||||
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
|
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
|
||||||
AccountManager: accman,
|
|
||||||
Etherbase: MakeEtherbase(accman, ctx),
|
|
||||||
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
|
||||||
ExtraData: MakeMinerExtra(extra, ctx),
|
ExtraData: MakeMinerExtra(extra, ctx),
|
||||||
NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name),
|
NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name),
|
||||||
@ -703,8 +694,6 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
|
|||||||
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
|
SolcPath: ctx.GlobalString(SolcPathFlag.Name),
|
||||||
AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
|
AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name),
|
||||||
}
|
}
|
||||||
// Configure the Whisper service
|
|
||||||
shhEnable := ctx.GlobalBool(WhisperEnabledFlag.Name)
|
|
||||||
|
|
||||||
// Override any default configs in dev mode or the test net
|
// Override any default configs in dev mode or the test net
|
||||||
switch {
|
switch {
|
||||||
@ -722,54 +711,30 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
|
|||||||
state.StartingNonce = 1048576 // (2**20)
|
state.StartingNonce = 1048576 // (2**20)
|
||||||
|
|
||||||
case ctx.GlobalBool(DevModeFlag.Name):
|
case ctx.GlobalBool(DevModeFlag.Name):
|
||||||
// Override the base network stack configs
|
|
||||||
if !ctx.GlobalIsSet(DataDirFlag.Name) {
|
|
||||||
stackConf.DataDir = filepath.Join(os.TempDir(), "/ethereum_dev_mode")
|
|
||||||
}
|
|
||||||
if !ctx.GlobalIsSet(MaxPeersFlag.Name) {
|
|
||||||
stackConf.MaxPeers = 0
|
|
||||||
}
|
|
||||||
if !ctx.GlobalIsSet(ListenPortFlag.Name) {
|
|
||||||
stackConf.ListenAddr = ":0"
|
|
||||||
}
|
|
||||||
// Override the Ethereum protocol configs
|
|
||||||
ethConf.Genesis = core.OlympicGenesisBlock()
|
ethConf.Genesis = core.OlympicGenesisBlock()
|
||||||
if !ctx.GlobalIsSet(GasPriceFlag.Name) {
|
if !ctx.GlobalIsSet(GasPriceFlag.Name) {
|
||||||
ethConf.GasPrice = new(big.Int)
|
ethConf.GasPrice = new(big.Int)
|
||||||
}
|
}
|
||||||
if !ctx.GlobalIsSet(WhisperEnabledFlag.Name) {
|
|
||||||
shhEnable = true
|
|
||||||
}
|
|
||||||
ethConf.PowTest = true
|
ethConf.PowTest = true
|
||||||
}
|
}
|
||||||
// Assemble and return the protocol stack
|
|
||||||
stack, err := node.New(stackConf)
|
|
||||||
if err != nil {
|
|
||||||
Fatalf("Failed to create the protocol stack: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
|
||||||
return accman, nil
|
|
||||||
}); err != nil {
|
|
||||||
Fatalf("Failed to register the account manager service: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
return eth.New(ctx, ethConf)
|
return eth.New(ctx, ethConf)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
Fatalf("Failed to register the Ethereum service: %v", err)
|
Fatalf("Failed to register the Ethereum service: %v", err)
|
||||||
}
|
}
|
||||||
if shhEnable {
|
|
||||||
if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisper.New(), nil }); err != nil {
|
|
||||||
Fatalf("Failed to register the Whisper service: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
return release.NewReleaseService(ctx, relconf)
|
return release.NewReleaseService(ctx, relconf)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
Fatalf("Failed to register the Geth release oracle service: %v", err)
|
Fatalf("Failed to register the Geth release oracle service: %v", err)
|
||||||
}
|
}
|
||||||
return stack
|
}
|
||||||
|
|
||||||
|
// RegisterShhService configures whisper and adds it to the given node.
|
||||||
|
func RegisterShhService(stack *node.Node) {
|
||||||
|
if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisper.New(), nil }); err != nil {
|
||||||
|
Fatalf("Failed to register the Whisper service: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupNetwork configures the system for either the main net or some test network.
|
// SetupNetwork configures the system for either the main net or some test network.
|
||||||
|
@ -23,12 +23,10 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
@ -92,17 +90,15 @@ func newTester(t *testing.T, confOverride func(*eth.Config)) *tester {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create temporary keystore: %v", err)
|
t.Fatalf("failed to create temporary keystore: %v", err)
|
||||||
}
|
}
|
||||||
accman := accounts.NewPlaintextManager(filepath.Join(workspace, "keystore"))
|
|
||||||
|
|
||||||
// Create a networkless protocol stack and start an Ethereum service within
|
// Create a networkless protocol stack and start an Ethereum service within
|
||||||
stack, err := node.New(&node.Config{DataDir: workspace, Name: testInstance, NoDiscovery: true})
|
stack, err := node.New(&node.Config{DataDir: workspace, UseLightweightKDF: true, Name: testInstance, NoDiscovery: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create node: %v", err)
|
t.Fatalf("failed to create node: %v", err)
|
||||||
}
|
}
|
||||||
ethConf := ð.Config{
|
ethConf := ð.Config{
|
||||||
ChainConfig: &core.ChainConfig{HomesteadBlock: new(big.Int)},
|
ChainConfig: &core.ChainConfig{HomesteadBlock: new(big.Int)},
|
||||||
Etherbase: common.HexToAddress(testAddress),
|
Etherbase: common.HexToAddress(testAddress),
|
||||||
AccountManager: accman,
|
|
||||||
PowTest: true,
|
PowTest: true,
|
||||||
}
|
}
|
||||||
if confOverride != nil {
|
if confOverride != nil {
|
||||||
|
@ -83,7 +83,6 @@ type Config struct {
|
|||||||
PowShared bool
|
PowShared bool
|
||||||
ExtraData []byte
|
ExtraData []byte
|
||||||
|
|
||||||
AccountManager *accounts.Manager
|
|
||||||
Etherbase common.Address
|
Etherbase common.Address
|
||||||
GasPrice *big.Int
|
GasPrice *big.Int
|
||||||
MinerThreads int
|
MinerThreads int
|
||||||
@ -160,7 +159,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||||||
chainDb: chainDb,
|
chainDb: chainDb,
|
||||||
dappDb: dappDb,
|
dappDb: dappDb,
|
||||||
eventMux: ctx.EventMux,
|
eventMux: ctx.EventMux,
|
||||||
accountManager: config.AccountManager,
|
accountManager: ctx.AccountManager,
|
||||||
pow: pow,
|
pow: pow,
|
||||||
shutdownChan: make(chan bool),
|
shutdownChan: make(chan bool),
|
||||||
stopDbUpgrade: stopDbUpgrade,
|
stopDbUpgrade: stopDbUpgrade,
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
@ -37,6 +38,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
datadirPrivateKey = "nodekey" // Path within the datadir to the node's private key
|
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
|
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
|
datadirTrustedNodes = "trusted-nodes.json" // Path within the datadir to the trusted node list
|
||||||
datadirNodeDatabase = "nodes" // Path within the datadir to store the node infos
|
datadirNodeDatabase = "nodes" // Path within the datadir to store the node infos
|
||||||
@ -53,6 +55,19 @@ type Config struct {
|
|||||||
// in memory.
|
// in memory.
|
||||||
DataDir string
|
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
|
// 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
|
// 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
|
// 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
|
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
|
||||||
|
}
|
||||||
|
26
node/node.go
26
node/node.go
@ -26,6 +26,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/internal/debug"
|
"github.com/ethereum/go-ethereum/internal/debug"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
@ -49,6 +50,9 @@ type Node struct {
|
|||||||
datadir string // Path to the currently used data directory
|
datadir string // Path to the currently used data directory
|
||||||
eventmux *event.TypeMux // Event multiplexer used between the services of a stack
|
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
|
serverConfig p2p.Config
|
||||||
server *p2p.Server // Currently running P2P networking layer
|
server *p2p.Server // Currently running P2P networking layer
|
||||||
|
|
||||||
@ -90,6 +94,11 @@ func New(conf *Config) (*Node, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
am, ephemeralKeystore, err := makeAccountManager(conf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Assemble the networking layer and the node itself
|
// Assemble the networking layer and the node itself
|
||||||
nodeDbPath := ""
|
nodeDbPath := ""
|
||||||
if conf.DataDir != "" {
|
if conf.DataDir != "" {
|
||||||
@ -97,6 +106,8 @@ func New(conf *Config) (*Node, error) {
|
|||||||
}
|
}
|
||||||
return &Node{
|
return &Node{
|
||||||
datadir: conf.DataDir,
|
datadir: conf.DataDir,
|
||||||
|
accman: am,
|
||||||
|
ephemeralKeystore: ephemeralKeystore,
|
||||||
serverConfig: p2p.Config{
|
serverConfig: p2p.Config{
|
||||||
PrivateKey: conf.NodeKey(),
|
PrivateKey: conf.NodeKey(),
|
||||||
Name: conf.Name,
|
Name: conf.Name,
|
||||||
@ -159,6 +170,7 @@ func (n *Node) Start() error {
|
|||||||
datadir: n.datadir,
|
datadir: n.datadir,
|
||||||
services: make(map[reflect.Type]Service),
|
services: make(map[reflect.Type]Service),
|
||||||
EventMux: n.eventmux,
|
EventMux: n.eventmux,
|
||||||
|
AccountManager: n.accman,
|
||||||
}
|
}
|
||||||
for kind, s := range services { // copy needed for threaded access
|
for kind, s := range services { // copy needed for threaded access
|
||||||
ctx.services[kind] = s
|
ctx.services[kind] = s
|
||||||
@ -473,9 +485,18 @@ func (n *Node) Stop() error {
|
|||||||
n.server = nil
|
n.server = nil
|
||||||
close(n.stop)
|
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 {
|
if len(failure.Services) > 0 {
|
||||||
return failure
|
return failure
|
||||||
}
|
}
|
||||||
|
if keystoreErr != nil {
|
||||||
|
return keystoreErr
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,6 +569,11 @@ func (n *Node) DataDir() string {
|
|||||||
return n.datadir
|
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.
|
// IPCEndpoint retrieves the current IPC endpoint used by the protocol stack.
|
||||||
func (n *Node) IPCEndpoint() string {
|
func (n *Node) IPCEndpoint() string {
|
||||||
return n.ipcEndpoint
|
return n.ipcEndpoint
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
@ -33,6 +34,7 @@ type ServiceContext struct {
|
|||||||
datadir string // Data directory for protocol persistence
|
datadir string // Data directory for protocol persistence
|
||||||
services map[reflect.Type]Service // Index of the already constructed services
|
services map[reflect.Type]Service // Index of the already constructed services
|
||||||
EventMux *event.TypeMux // Event multiplexer used for decoupled notifications
|
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
|
// OpenDatabase opens an existing database with the given name (or creates one
|
||||||
|
Loading…
Reference in New Issue
Block a user