aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2015-03-06 10:00:41 +0800
committerFelix Lange <fjl@twurst.com>2015-03-06 10:57:13 +0800
commitbae7e93a9c5af679682f89b0f475e98c1eee9e58 (patch)
treebdf4c4fe1893c3e26d2c0dfd86204a1ea3d71085 /cmd
parentf9c6bc63df8170c6a3b1bb7848b92759b17e7d58 (diff)
downloadgo-tangerine-bae7e93a9c5af679682f89b0f475e98c1eee9e58.tar.gz
go-tangerine-bae7e93a9c5af679682f89b0f475e98c1eee9e58.tar.zst
go-tangerine-bae7e93a9c5af679682f89b0f475e98c1eee9e58.zip
cmd/ethereum: improve command line interface
The ethereum command line interface is now structured using subcommands. These separate the different tasks it can perform. Almost all flag names are backwards compatible. The key tasks have not been ported to subcommands since they will be replaced by the new accounts infrastructure very soon.
Diffstat (limited to 'cmd')
-rw-r--r--cmd/ethereum/flags.go168
-rw-r--r--cmd/ethereum/js.go (renamed from cmd/ethereum/cmd.go)13
-rw-r--r--cmd/ethereum/main.go238
-rw-r--r--cmd/utils/cmd.go25
-rw-r--r--cmd/utils/flags.go178
5 files changed, 350 insertions, 272 deletions
diff --git a/cmd/ethereum/flags.go b/cmd/ethereum/flags.go
deleted file mode 100644
index a3004f503..000000000
--- a/cmd/ethereum/flags.go
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- 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/>.
-*/
-/**
- * @authors
- * Jeffrey Wilcke <i@jev.io>
- */
-package main
-
-import (
- "crypto/ecdsa"
- "flag"
- "fmt"
- "log"
- "os"
- "path"
- "runtime"
-
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethutil"
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/p2p/nat"
- "github.com/ethereum/go-ethereum/vm"
-)
-
-var (
- Identifier string
- KeyRing string
- DiffTool bool
- DiffType string
- KeyStore string
- StartRpc bool
- StartWebSockets bool
- RpcListenAddress string
- RpcPort int
- OutboundPort string
- ShowGenesis bool
- AddPeer string
- MaxPeer int
- GenAddr bool
- BootNodes string
- NodeKey *ecdsa.PrivateKey
- NAT nat.Interface
- SecretFile string
- ExportDir string
- NonInteractive bool
- Datadir string
- LogFile string
- ConfigFile string
- DebugFile string
- LogLevel int
- LogFormat string
- Dump bool
- DumpHash string
- DumpNumber int
- VmType int
- ImportChain string
- SHH bool
- Dial bool
- PrintVersion bool
- MinerThreads int
-)
-
-// flags specific to cli client
-var (
- StartMining bool
- StartJsConsole bool
- InputFile string
-)
-
-var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
-
-func Init() {
- // TODO: move common flag processing to cmd/util
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, "%s [options] [filename]:\noptions precedence: default < config file < environment variables < command line\n", os.Args[0])
- flag.PrintDefaults()
- }
-
- flag.IntVar(&VmType, "vm", 0, "Virtual Machine type: 0-1: standard, debug")
- flag.StringVar(&Identifier, "id", "", "Custom client identifier")
- flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
- flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file")
-
- flag.StringVar(&RpcListenAddress, "rpcaddr", "127.0.0.1", "address for json-rpc server to listen on")
- flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
- flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
- flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
- flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
- flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
- flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
- flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
- flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use")
- flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
- flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
- flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5 (= silent,error,warn,info,debug,debug detail)")
- flag.StringVar(&LogFormat, "logformat", "std", "logformat: std,raw")
- flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
- flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
- flag.BoolVar(&ShowGenesis, "genesis", false, "Dump the genesis block")
- flag.StringVar(&ImportChain, "chain", "", "Imports given chain")
-
- flag.BoolVar(&Dump, "dump", false, "output the ethereum state in JSON format. Sub args [number, hash]")
- flag.StringVar(&DumpHash, "hash", "", "specify arg in hex")
- flag.IntVar(&DumpNumber, "number", -1, "specify arg in number")
-
- flag.BoolVar(&StartMining, "mine", false, "start mining")
- flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console")
- flag.BoolVar(&PrintVersion, "version", false, "prints version number")
- flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads")
-
- // Network stuff
- var (
- nodeKeyFile = flag.String("nodekey", "", "network private key file")
- nodeKeyHex = flag.String("nodekeyhex", "", "network private key (for testing)")
- natstr = flag.String("nat", "any", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)")
- )
- flag.BoolVar(&Dial, "dial", true, "dial out connections (default on)")
- //flag.BoolVar(&SHH, "shh", true, "run whisper protocol (default on)")
- flag.StringVar(&OutboundPort, "port", "30303", "listening port")
-
- flag.StringVar(&BootNodes, "bootnodes", "", "space-separated node URLs for discovery bootstrap")
- flag.IntVar(&MaxPeer, "maxpeer", 30, "maximum desired peers")
-
- flag.Parse()
-
- // When the javascript console is started log to a file instead
- // of stdout
- if StartJsConsole {
- LogFile = path.Join(Datadir, "ethereum.log")
- }
-
- var err error
- if NAT, err = nat.Parse(*natstr); err != nil {
- log.Fatalf("-nat: %v", err)
- }
- switch {
- case *nodeKeyFile != "" && *nodeKeyHex != "":
- log.Fatal("Options -nodekey and -nodekeyhex are mutually exclusive")
- case *nodeKeyFile != "":
- if NodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil {
- log.Fatalf("-nodekey: %v", err)
- }
- case *nodeKeyHex != "":
- if NodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil {
- log.Fatalf("-nodekeyhex: %v", err)
- }
- }
-
- if VmType >= int(vm.MaxVmTy) {
- log.Fatal("Invalid VM type ", VmType)
- }
-
- InputFile = flag.Arg(0)
-}
diff --git a/cmd/ethereum/cmd.go b/cmd/ethereum/js.go
index 7bb7c3ef7..f0aeb45f5 100644
--- a/cmd/ethereum/cmd.go
+++ b/cmd/ethereum/js.go
@@ -21,20 +21,23 @@ import (
"io/ioutil"
"os"
+ "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/javascript"
"github.com/ethereum/go-ethereum/xeth"
)
-func ExecJsFile(ethereum *eth.Ethereum, InputFile string) {
- file, err := os.Open(InputFile)
+func execJsFile(ethereum *eth.Ethereum, filename string) {
+ file, err := os.Open(filename)
if err != nil {
- clilogger.Fatalln(err)
+ utils.Fatalf("%v", err)
}
content, err := ioutil.ReadAll(file)
if err != nil {
- clilogger.Fatalln(err)
+ utils.Fatalf("%v", err)
}
re := javascript.NewJSRE(xeth.New(ethereum))
- re.Run(string(content))
+ if _, err := re.Run(string(content)); err != nil {
+ utils.Fatalf("Javascript Error: %v", err)
+ }
}
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index b9e69f700..a38e012c2 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -24,15 +24,16 @@ import (
"fmt"
"os"
"runtime"
+ "strconv"
"time"
+ "github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/ethereum/repl"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/state"
)
@@ -41,117 +42,174 @@ const (
Version = "0.8.6"
)
-var clilogger = logger.NewLogger("CLI")
+var (
+ clilogger = logger.NewLogger("CLI")
+ app = cli.NewApp()
+)
-func main() {
- runtime.GOMAXPROCS(runtime.NumCPU())
+func init() {
+ app.Version = Version
+ app.Usage = "the go-ethereum command-line client"
+ app.Action = run
+ app.HideVersion = true // we have a command to print the version
+ app.Commands = []cli.Command{
+ {
+ Action: version,
+ Name: "version",
+ Usage: "print ethereum version numbers",
+ Description: `
+The output of this command is supposed to be machine-readable.
+`,
+ },
+ {
+ Action: dump,
+ Name: "dump",
+ Usage: `dump a specific block from storage`,
+ Description: `
+The arguments are interpreted as block numbers or hashes.
+Use "ethereum dump 0" to dump the genesis block.
+`,
+ },
+ {
+ Action: runjs,
+ Name: "js",
+ Usage: `interactive JavaScript console`,
+ Description: `
+In the console, you can use the eth object to interact
+with the running ethereum stack. The API does not match
+ethereum.js.
+
+A JavaScript file can be provided as the argument. The
+runtime will execute the file and exit.
+`,
+ },
+ {
+ Action: importchain,
+ Name: "import",
+ Usage: `import a blockchain file`,
+ },
+ }
+ app.Author = ""
+ app.Email = ""
+ app.Flags = []cli.Flag{
+ utils.BootnodesFlag,
+ utils.DataDirFlag,
+ utils.KeyRingFlag,
+ utils.KeyStoreFlag,
+ utils.ListenPortFlag,
+ utils.LogFileFlag,
+ utils.LogFormatFlag,
+ utils.LogLevelFlag,
+ utils.MaxPeersFlag,
+ utils.MinerThreadsFlag,
+ utils.MiningEnabledFlag,
+ utils.NATFlag,
+ utils.NodeKeyFileFlag,
+ utils.NodeKeyHexFlag,
+ utils.RPCEnabledFlag,
+ utils.RPCListenAddrFlag,
+ utils.RPCPortFlag,
+ utils.VMTypeFlag,
+ }
+
+ // missing:
+ // flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
+ // flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
+ // flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
- defer func() {
- logger.Flush()
- }()
+ // potential subcommands:
+ // flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
+ // flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
+ // flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
+}
+func main() {
+ runtime.GOMAXPROCS(runtime.NumCPU())
+ defer logger.Flush()
utils.HandleInterrupt()
+ if err := app.Run(os.Args); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
- // precedence: code-internal flag default < config file < environment variables < command line
- Init() // parsing command line
+func run(ctx *cli.Context) {
+ fmt.Printf("Welcome to the FRONTIER\n")
+ eth := utils.GetEthereum(ClientIdentifier, Version, ctx)
+ startEth(ctx, eth)
+ // this blocks the thread
+ eth.WaitForShutdown()
+}
- if PrintVersion {
- printVersion()
- return
+func runjs(ctx *cli.Context) {
+ eth := utils.GetEthereum(ClientIdentifier, Version, ctx)
+ startEth(ctx, eth)
+ if len(ctx.Args()) == 0 {
+ repl := ethrepl.NewJSRepl(eth)
+ repl.Start()
+ utils.RegisterInterrupt(func(os.Signal) { repl.Stop() })
+ eth.WaitForShutdown()
+ } else if len(ctx.Args()) == 1 {
+ execJsFile(eth, ctx.Args()[0])
+ } else {
+ utils.Fatalf("This command can handle at most one argument.")
}
+}
- utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
-
- ethereum, err := eth.New(&eth.Config{
- Name: p2p.MakeName(ClientIdentifier, Version),
- KeyStore: KeyStore,
- DataDir: Datadir,
- LogFile: LogFile,
- LogLevel: LogLevel,
- LogFormat: LogFormat,
- MaxPeers: MaxPeer,
- Port: OutboundPort,
- NAT: NAT,
- KeyRing: KeyRing,
- Shh: true,
- Dial: Dial,
- BootNodes: BootNodes,
- NodeKey: NodeKey,
- MinerThreads: MinerThreads,
- })
+func startEth(ctx *cli.Context, eth *eth.Ethereum) {
+ utils.StartEthereum(eth)
+ if ctx.GlobalBool(utils.RPCEnabledFlag.Name) {
+ addr := ctx.GlobalString(utils.RPCListenAddrFlag.Name)
+ port := ctx.GlobalInt(utils.RPCPortFlag.Name)
+ utils.StartRpc(eth, addr, port)
+ }
+ if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
+ eth.Miner().Start()
+ }
+}
+func importchain(ctx *cli.Context) {
+ if len(ctx.Args()) != 1 {
+ utils.Fatalf("This command requires an argument.")
+ }
+ chain, _ := utils.GetChain(ctx)
+ start := time.Now()
+ err := utils.ImportChain(chain, ctx.Args().First())
if err != nil {
- clilogger.Fatalln(err)
+ utils.Fatalf("Import error: %v\n", err)
}
+ fmt.Printf("Import done in", time.Since(start))
+ return
+}
- utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
-
- if Dump {
+func dump(ctx *cli.Context) {
+ chain, db := utils.GetChain(ctx)
+ for _, arg := range ctx.Args() {
var block *types.Block
-
- if len(DumpHash) == 0 && DumpNumber == -1 {
- block = ethereum.ChainManager().CurrentBlock()
- } else if len(DumpHash) > 0 {
- block = ethereum.ChainManager().GetBlock(ethutil.Hex2Bytes(DumpHash))
+ if hashish(arg) {
+ block = chain.GetBlock(ethutil.Hex2Bytes(arg))
} else {
- block = ethereum.ChainManager().GetBlockByNumber(uint64(DumpNumber))
+ num, _ := strconv.Atoi(arg)
+ block = chain.GetBlockByNumber(uint64(num))
}
-
if block == nil {
- fmt.Fprintln(os.Stderr, "block not found")
-
- // We want to output valid JSON
fmt.Println("{}")
-
- os.Exit(1)
- }
-
- // Leave the Println. This needs clean output for piping
- statedb := state.New(block.Root(), ethereum.Db())
- fmt.Printf("%s\n", statedb.Dump())
-
- fmt.Println(block)
-
- return
- }
-
- if len(ImportChain) > 0 {
- start := time.Now()
- err := utils.ImportChain(ethereum, ImportChain)
- if err != nil {
- clilogger.Infoln(err)
+ utils.Fatalf("block not found")
+ } else {
+ statedb := state.New(block.Root(), db)
+ fmt.Printf("%s\n", statedb.Dump())
+ // fmt.Println(block)
}
- clilogger.Infoln("import done in", time.Since(start))
- return
- }
-
- if StartRpc {
- utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
- }
-
- utils.StartEthereum(ethereum)
-
- fmt.Printf("Welcome to the FRONTIER\n")
-
- if StartMining {
- ethereum.Miner().Start()
}
+}
- if StartJsConsole {
- repl := ethrepl.NewJSRepl(ethereum)
- repl.Start()
- utils.RegisterInterrupt(func(os.Signal) {
- repl.Stop()
- })
-
- } else if len(InputFile) > 0 {
- ExecJsFile(ethereum, InputFile)
- }
- // this blocks the thread
- ethereum.WaitForShutdown()
+// hashish returns true for strings that look like hashes.
+func hashish(x string) bool {
+ _, err := strconv.Atoi(x)
+ return err != nil
}
-func printVersion() {
+func version(c *cli.Context) {
fmt.Printf(`%v %v
PV=%d
GOOS=%s
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 2bd34d792..3c3d3955d 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -27,6 +27,7 @@ import (
"os/signal"
"regexp"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
@@ -108,13 +109,20 @@ func InitConfig(vmType int, ConfigFile string, Datadir string, EnvPrefix string)
func exit(err error) {
status := 0
if err != nil {
- clilogger.Errorln("Fatal: ", err)
+ fmt.Fprintln(os.Stderr, "Fatal: ", err)
status = 1
}
logger.Flush()
os.Exit(status)
}
+// Fatalf formats a message to standard output and exits the program.
+func Fatalf(format string, args ...interface{}) {
+ fmt.Fprintf(os.Stderr, "Fatal: "+format+"\n", args...)
+ logger.Flush()
+ os.Exit(1)
+}
+
func StartEthereum(ethereum *eth.Ethereum) {
clilogger.Infoln("Starting ", ethereum.Name())
if err := ethereum.Start(); err != nil {
@@ -127,7 +135,6 @@ func StartEthereum(ethereum *eth.Ethereum) {
}
func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
-
var err error
switch {
case GenAddr:
@@ -200,24 +207,24 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error {
}
-func ImportChain(ethereum *eth.Ethereum, fn string) error {
- clilogger.Infof("importing chain '%s'\n", fn)
+func ImportChain(chain *core.ChainManager, fn string) error {
+ fmt.Printf("importing chain '%s'\n", fn)
fh, err := os.OpenFile(fn, os.O_RDONLY, os.ModePerm)
if err != nil {
return err
}
defer fh.Close()
- var chain types.Blocks
- if err := rlp.Decode(fh, &chain); err != nil {
+ var blocks types.Blocks
+ if err := rlp.Decode(fh, &blocks); err != nil {
return err
}
- ethereum.ChainManager().Reset()
- if err := ethereum.ChainManager().InsertChain(chain); err != nil {
+ chain.Reset()
+ if err := chain.InsertChain(blocks); err != nil {
return err
}
- clilogger.Infof("imported %d blocks\n", len(chain))
+ fmt.Printf("imported %d blocks\n", len(blocks))
return nil
}
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
new file mode 100644
index 000000000..fb80ac708
--- /dev/null
+++ b/cmd/utils/flags.go
@@ -0,0 +1,178 @@
+package utils
+
+import (
+ "crypto/ecdsa"
+ "path"
+ "runtime"
+
+ "github.com/codegangsta/cli"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/ethutil"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/nat"
+)
+
+// These are all the command line flags we support.
+// If you add to this list, please remember to include the
+// flag in the appropriate command definition.
+//
+// The flags are defined here so their names and help texts
+// are the same for all commands.
+
+var (
+ // General settings
+ VMTypeFlag = cli.IntFlag{
+ Name: "vm",
+ Usage: "Virtual Machine type: 0 is standard VM, 1 is debug VM",
+ }
+ KeyRingFlag = cli.StringFlag{
+ Name: "keyring",
+ Usage: "Name of keyring to be used",
+ Value: "",
+ }
+ KeyStoreFlag = cli.StringFlag{
+ Name: "keystore",
+ Usage: `Where to store keyrings: "db" or "file"`,
+ Value: "db",
+ }
+ DataDirFlag = cli.StringFlag{
+ Name: "datadir",
+ Usage: "Data directory to be used",
+ Value: ethutil.DefaultDataDir(),
+ }
+ MinerThreadsFlag = cli.IntFlag{
+ Name: "minerthreads",
+ Usage: "Number of miner threads",
+ Value: runtime.NumCPU(),
+ }
+ MiningEnabledFlag = cli.BoolFlag{
+ Name: "mine",
+ Usage: "Enable mining",
+ }
+
+ LogFileFlag = cli.StringFlag{
+ Name: "logfile",
+ Usage: "Send log output to a file",
+ }
+ LogLevelFlag = cli.IntFlag{
+ Name: "loglevel",
+ Usage: "0-5 (silent, error, warn, info, debug, debug detail)",
+ Value: int(logger.InfoLevel),
+ }
+ LogFormatFlag = cli.StringFlag{
+ Name: "logformat",
+ Usage: `"std" or "raw"`,
+ Value: "std",
+ }
+
+ // RPC settings
+ RPCEnabledFlag = cli.BoolFlag{
+ Name: "rpc",
+ Usage: "Whether RPC server is enabled",
+ }
+ RPCListenAddrFlag = cli.StringFlag{
+ Name: "rpcaddr",
+ Usage: "Listening address for the JSON-RPC server",
+ Value: "127.0.0.1",
+ }
+ RPCPortFlag = cli.IntFlag{
+ Name: "rpcport",
+ Usage: "Port on which the JSON-RPC server should listen",
+ Value: 8545,
+ }
+
+ // Network Settings
+ MaxPeersFlag = cli.IntFlag{
+ Name: "maxpeers",
+ Usage: "Maximum number of network peers",
+ Value: 16,
+ }
+ ListenPortFlag = cli.IntFlag{
+ Name: "port",
+ Usage: "Network listening port",
+ Value: 30303,
+ }
+ BootnodesFlag = cli.StringFlag{
+ Name: "bootnodes",
+ Usage: "Space-separated enode URLs for discovery bootstrap",
+ Value: "",
+ }
+ NodeKeyFileFlag = cli.StringFlag{
+ Name: "nodekey",
+ Usage: "P2P node key file",
+ }
+ NodeKeyHexFlag = cli.StringFlag{
+ Name: "nodekeyhex",
+ Usage: "P2P node key as hex (for testing)",
+ }
+ NATFlag = cli.StringFlag{
+ Name: "nat",
+ Usage: "Port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
+ Value: "any",
+ }
+)
+
+func GetNAT(ctx *cli.Context) nat.Interface {
+ natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
+ if err != nil {
+ Fatalf("Option %s: %v", NATFlag.Name, err)
+ }
+ return natif
+}
+
+func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
+ hex, file := ctx.GlobalString(NodeKeyHexFlag.Name), ctx.GlobalString(NodeKeyFileFlag.Name)
+ var err error
+ switch {
+ case file != "" && hex != "":
+ Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
+ case file != "":
+ if key, err = crypto.LoadECDSA(file); err != nil {
+ Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
+ }
+ case hex != "":
+ if key, err = crypto.HexToECDSA(hex); err != nil {
+ Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
+ }
+ }
+ return key
+}
+
+func GetEthereum(clientID, version string, ctx *cli.Context) *eth.Ethereum {
+ ethereum, err := eth.New(&eth.Config{
+ Name: p2p.MakeName(clientID, version),
+ KeyStore: ctx.GlobalString(KeyStoreFlag.Name),
+ DataDir: ctx.GlobalString(DataDirFlag.Name),
+ LogFile: ctx.GlobalString(LogFileFlag.Name),
+ LogLevel: ctx.GlobalInt(LogLevelFlag.Name),
+ LogFormat: ctx.GlobalString(LogFormatFlag.Name),
+ MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name),
+
+ MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
+ Port: ctx.GlobalString(ListenPortFlag.Name),
+ NAT: GetNAT(ctx),
+ NodeKey: GetNodeKey(ctx),
+ KeyRing: ctx.GlobalString(KeyRingFlag.Name),
+ Shh: true,
+ Dial: true,
+ BootNodes: ctx.GlobalString(BootnodesFlag.Name),
+ })
+ if err != nil {
+ exit(err)
+ }
+ return ethereum
+}
+
+func GetChain(ctx *cli.Context) (*core.ChainManager, ethutil.Database) {
+ dataDir := ctx.GlobalString(DataDirFlag.Name)
+ db, err := ethdb.NewLDBDatabase(path.Join(dataDir, "blockchain"))
+ if err != nil {
+ Fatalf("Could not open database: %v", err)
+ }
+ return core.NewChainManager(db, new(event.TypeMux)), db
+}