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.
This commit is contained in:
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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 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")
|
||||
|
||||
// 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 func() {
|
||||
logger.Flush()
|
||||
}()
|
||||
|
||||
defer logger.Flush()
|
||||
utils.HandleInterrupt()
|
||||
|
||||
// precedence: code-internal flag default < config file < environment variables < command line
|
||||
Init() // parsing command line
|
||||
|
||||
if PrintVersion {
|
||||
printVersion()
|
||||
return
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
|
||||
|
||||
ethereum, err := eth.New(ð.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,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
clilogger.Fatalln(err)
|
||||
}
|
||||
|
||||
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
|
||||
|
||||
if Dump {
|
||||
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))
|
||||
} else {
|
||||
block = ethereum.ChainManager().GetBlockByNumber(uint64(DumpNumber))
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
||||
func printVersion() {
|
||||
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()
|
||||
}
|
||||
|
||||
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.")
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
utils.Fatalf("Import error: %v\n", err)
|
||||
}
|
||||
fmt.Printf("Import done in", time.Since(start))
|
||||
return
|
||||
}
|
||||
|
||||
func dump(ctx *cli.Context) {
|
||||
chain, db := utils.GetChain(ctx)
|
||||
for _, arg := range ctx.Args() {
|
||||
var block *types.Block
|
||||
if hashish(arg) {
|
||||
block = chain.GetBlock(ethutil.Hex2Bytes(arg))
|
||||
} else {
|
||||
num, _ := strconv.Atoi(arg)
|
||||
block = chain.GetBlockByNumber(uint64(num))
|
||||
}
|
||||
if block == nil {
|
||||
fmt.Println("{}")
|
||||
utils.Fatalf("block not found")
|
||||
} else {
|
||||
statedb := state.New(block.Root(), db)
|
||||
fmt.Printf("%s\n", statedb.Dump())
|
||||
// fmt.Println(block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hashish returns true for strings that look like hashes.
|
||||
func hashish(x string) bool {
|
||||
_, err := strconv.Atoi(x)
|
||||
return err != nil
|
||||
}
|
||||
|
||||
func version(c *cli.Context) {
|
||||
fmt.Printf(`%v %v
|
||||
PV=%d
|
||||
GOOS=%s
|
||||
|
@ -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
|
||||
}
|
||||
|
178
cmd/utils/flags.go
Normal file
178
cmd/utils/flags.go
Normal file
@ -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(ð.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
|
||||
}
|
Reference in New Issue
Block a user