diff --git a/cmd/tomo/chaincmd.go b/cmd/tomo/chaincmd.go index d3086921b9..fc3be707f0 100644 --- a/cmd/tomo/chaincmd.go +++ b/cmd/tomo/chaincmd.go @@ -190,7 +190,7 @@ func initGenesis(ctx *cli.Context) error { utils.Fatalf("invalid genesis file: %v", err) } // Open an initialise both full and light databases - stack := makeFullNode(ctx) + stack, _ := makeFullNode(ctx) for _, name := range []string{"chaindata", "lightchaindata"} { chaindb, err := stack.OpenDatabase(name, 0, 0) if err != nil { @@ -209,7 +209,7 @@ func importChain(ctx *cli.Context) error { if len(ctx.Args()) < 1 { utils.Fatalf("This command requires an argument.") } - stack := makeFullNode(ctx) + stack, _ := makeFullNode(ctx) chain, chainDb := utils.MakeChain(ctx, stack) defer chainDb.Close() @@ -303,7 +303,7 @@ func exportChain(ctx *cli.Context) error { if len(ctx.Args()) < 1 { utils.Fatalf("This command requires an argument.") } - stack := makeFullNode(ctx) + stack, _ := makeFullNode(ctx) chain, _ := utils.MakeChain(ctx, stack) start := time.Now() @@ -336,7 +336,7 @@ func importPreimages(ctx *cli.Context) error { if len(ctx.Args()) < 1 { utils.Fatalf("This command requires an argument.") } - stack := makeFullNode(ctx) + stack, _ := makeFullNode(ctx) diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase) start := time.Now() @@ -352,7 +352,7 @@ func exportPreimages(ctx *cli.Context) error { if len(ctx.Args()) < 1 { utils.Fatalf("This command requires an argument.") } - stack := makeFullNode(ctx) + stack, _ := makeFullNode(ctx) diskdb := utils.MakeChainDatabase(ctx, stack).(*ethdb.LDBDatabase) start := time.Now() @@ -369,7 +369,7 @@ func copyDb(ctx *cli.Context) error { utils.Fatalf("Source chaindata directory path argument missing") } // Initialize a new chain for the running node to sync into - stack := makeFullNode(ctx) + stack, _ := makeFullNode(ctx) chain, chainDb := utils.MakeChain(ctx, stack) syncmode := *utils.GlobalTextMarshaler(ctx, utils.SyncModeFlag.Name).(*downloader.SyncMode) @@ -441,7 +441,7 @@ func removeDB(ctx *cli.Context) error { } func dump(ctx *cli.Context) error { - stack := makeFullNode(ctx) + stack, _ := makeFullNode(ctx) chain, chainDb := utils.MakeChain(ctx, stack) for _, arg := range ctx.Args() { var block *types.Block diff --git a/cmd/tomo/config.go b/cmd/tomo/config.go index 8856071901..dc199a04d2 100644 --- a/cmd/tomo/config.go +++ b/cmd/tomo/config.go @@ -25,7 +25,7 @@ import ( "reflect" "unicode" - cli "gopkg.in/urfave/cli.v1" + "gopkg.in/urfave/cli.v1" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/dashboard" @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/params" whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" "github.com/naoina/toml" + "strings" ) var ( @@ -74,12 +75,25 @@ type ethstatsConfig struct { URL string `toml:",omitempty"` } +type account struct { + Unlocks []string + Passwords []string +} + +type Bootnodes struct { + Mainnet []string + Testnet []string +} + type tomoConfig struct { - Eth eth.Config - Shh whisper.Config - Node node.Config - Ethstats ethstatsConfig - Dashboard dashboard.Config + Eth eth.Config + Shh whisper.Config + Node node.Config + Ethstats ethstatsConfig + Dashboard dashboard.Config + Account account + StakeEnable bool + Bootnodes Bootnodes } func loadConfig(file string, cfg *tomoConfig) error { @@ -88,7 +102,6 @@ func loadConfig(file string, cfg *tomoConfig) error { 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 { @@ -115,7 +128,6 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, tomoConfig) { Node: defaultNodeConfig(), Dashboard: dashboard.DefaultConfig, } - // Load config file. if file := ctx.GlobalString(configFileFlag.Name); file != "" { if err := loadConfig(file, &cfg); err != nil { @@ -123,6 +135,23 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, tomoConfig) { } } + // read passwords from enviroment + passwords := []string{} + for _, env := range cfg.Account.Passwords { + if trimmed := strings.TrimSpace(env); trimmed != "" { + value := os.Getenv(trimmed) + for _, info := range strings.Split(value, ",") { + if trimmed2 := strings.TrimSpace(info); trimmed2 != "" { + passwords = append(passwords, trimmed2) + } + } + } + } + cfg.Account.Passwords = passwords + //Apply Bootnodes + applyValues(cfg.Bootnodes.Mainnet, ¶ms.MainnetBootnodes) + applyValues(cfg.Bootnodes.Testnet, ¶ms.TestnetBootnodes) + // Apply flags. utils.SetNodeConfig(ctx, &cfg.Node) stack, err := node.New(&cfg.Node) @@ -140,6 +169,19 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, tomoConfig) { return stack, cfg } +func applyValues(values []string, params *[]string) { + data := []string{} + for _, value := range values { + if trimmed := strings.TrimSpace(value); trimmed != "" { + data = append(data, trimmed) + } + } + if len(data) > 0 { + *params = data + } + +} + // enableWhisper returns true in case one of the whisper flags is set. func enableWhisper(ctx *cli.Context) bool { for _, flag := range whisperFlags { @@ -150,7 +192,7 @@ func enableWhisper(ctx *cli.Context) bool { return false } -func makeFullNode(ctx *cli.Context) *node.Node { +func makeFullNode(ctx *cli.Context) (*node.Node, tomoConfig) { stack, cfg := makeConfigNode(ctx) utils.RegisterEthService(stack, &cfg.Eth) @@ -175,7 +217,7 @@ func makeFullNode(ctx *cli.Context) *node.Node { if cfg.Ethstats.URL != "" { utils.RegisterEthStatsService(stack, cfg.Ethstats.URL) } - return stack + return stack, cfg } // dumpConfig is the dumpconfig command. diff --git a/cmd/tomo/consolecmd.go b/cmd/tomo/consolecmd.go index 296e63e66f..5029602e39 100644 --- a/cmd/tomo/consolecmd.go +++ b/cmd/tomo/consolecmd.go @@ -77,8 +77,8 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/JavaScript-Cons // same time. func localConsole(ctx *cli.Context) error { // Create and start the node based on the CLI flags - node := makeFullNode(ctx) - startNode(ctx, node) + node, cfg := makeFullNode(ctx) + startNode(ctx, node, cfg) defer node.Stop() // Attach to the newly started node and start the JavaScript console @@ -130,6 +130,7 @@ func remoteConsole(ctx *cli.Context) error { } endpoint = fmt.Sprintf("%s/tomo.ipc", path) } + client, err := dialRPC(endpoint) if err != nil { utils.Fatalf("Unable to attach to remote tomo: %v", err) @@ -178,8 +179,8 @@ func dialRPC(endpoint string) (*rpc.Client, error) { // everything down. func ephemeralConsole(ctx *cli.Context) error { // Create and start the node based on the CLI flags - node := makeFullNode(ctx) - startNode(ctx, node) + node, cfg := makeFullNode(ctx) + startNode(ctx, node, cfg) defer node.Stop() // Attach to the newly started node and start the JavaScript console diff --git a/cmd/tomo/main.go b/cmd/tomo/main.go index 0cae7de10e..3afa5d36bd 100644 --- a/cmd/tomo/main.go +++ b/cmd/tomo/main.go @@ -213,8 +213,8 @@ func main() { // It creates a default node based on the command line arguments and runs it in // blocking mode, waiting for it to be shut down. func tomo(ctx *cli.Context) error { - node := makeFullNode(ctx) - startNode(ctx, node) + node, cfg := makeFullNode(ctx) + startNode(ctx, node, cfg) node.Wait() return nil } @@ -222,18 +222,24 @@ func tomo(ctx *cli.Context) error { // 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 // miner. -func startNode(ctx *cli.Context, stack *node.Node) { +func startNode(ctx *cli.Context, stack *node.Node, cfg tomoConfig) { // Start up the node itself utils.StartNode(stack) // Unlock any account specifically requested ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) - passwords := utils.MakePasswordList(ctx) - unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") - for i, account := range unlocks { + if ctx.GlobalIsSet(utils.UnlockedAccountFlag.Name) { + cfg.Account.Unlocks = strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") + } + + if ctx.GlobalIsSet(utils.PasswordFileFlag.Name) { + cfg.Account.Passwords = utils.MakePasswordList(ctx) + } + + for i, account := range cfg.Account.Unlocks { if trimmed := strings.TrimSpace(account); trimmed != "" { - unlockAccount(ctx, ks, trimmed, i, passwords) + unlockAccount(ctx, ks, trimmed, i, cfg.Account.Passwords) } } // Register wallet event handlers to open and auto-derive wallets @@ -278,7 +284,7 @@ func startNode(ctx *cli.Context, stack *node.Node) { } }() // Start auxiliary services if enabled - if ctx.GlobalBool(utils.StakingEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { + if cfg.StakeEnable || ctx.GlobalBool(utils.DeveloperFlag.Name) { // Mining only makes sense if a full Ethereum node is running if ctx.GlobalBool(utils.LightModeFlag.Name) || ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { utils.Fatalf("Light clients do not support staking") @@ -305,7 +311,7 @@ func startNode(ctx *cli.Context, stack *node.Node) { } } // Set the gas price to the limits from the CLI and start mining - ethereum.TxPool().SetGasPrice(utils.GlobalBig(ctx, utils.GasPriceFlag.Name)) + ethereum.TxPool().SetGasPrice(cfg.Eth.GasPrice) if err := ethereum.StartStaking(true); err != nil { utils.Fatalf("Failed to start staking: %v", err) } @@ -341,7 +347,7 @@ func startNode(ctx *cli.Context, stack *node.Node) { } } // Set the gas price to the limits from the CLI and start mining - ethereum.TxPool().SetGasPrice(utils.GlobalBig(ctx, utils.GasPriceFlag.Name)) + ethereum.TxPool().SetGasPrice(cfg.Eth.GasPrice) if err := ethereum.StartStaking(true); err != nil { utils.Fatalf("Failed to start staking: %v", err) } diff --git a/cmd/tomo/testdata/config.toml b/cmd/tomo/testdata/config.toml new file mode 100644 index 0000000000..5185af3dc0 --- /dev/null +++ b/cmd/tomo/testdata/config.toml @@ -0,0 +1,35 @@ +StakeEnable = true # flag --miner ( true : enable staker , false : disable ) +[Eth] +NetworkId = 89 # flag --networkid +SyncMode = "full" # flag --syncmode +GasPrice = 1 # flag --gasprice + +[Shh] + +[Node] +DataDir = "node1/" # flag --datadir +HTTPHost = "localhost" # flag --rpcaddr +HTTPPort = 8501 # flag --rpcport +HTTPModules = ["personal","db","eth","net","web3","txpool","miner"] # flag --rpcapi +[Node.P2P] +ListenAddr = ":30311" # flag --port +BootstrapNodes = ["enode://a890c5762c406fe046fb93fd307577a8454d571b6bf789f7dbfbf3c559be751f5fa400bc10639691245a9b22be1cfce0bbf82b322a24d06c6dcf29bf7eeb930c@127.0.0.1:30310"] +# flag --bootnodes + +[Ethstats] +[Dashboard] +[Account] +Unlocks = ["0x12f90a417f41bedd4bbcc99d52971803fb4c3f8b"] # list account slipt in flag --unlock +Passwords = ["PWD_DEVNET"] # list password in environment variable (split by ',') : ex : export PWD_DEVNET=123456,123456789 + + +[Bootnodes] +Mainnet =[] +Testnet =[] + + + + + + +