diff options
author | Jeffrey Wilcke <geffobscura@gmail.com> | 2015-11-03 18:47:07 +0800 |
---|---|---|
committer | Jeffrey Wilcke <geffobscura@gmail.com> | 2015-11-03 18:47:07 +0800 |
commit | e5532154a50114d5ffb1ffd850b746cab00cb899 (patch) | |
tree | 0042cc997ccf4166b9b52464339d52d37d7a8ad6 /cmd | |
parent | 9666db2a442887ccf8ec2d81f5e2fedc1a3a3d3e (diff) | |
parent | f75becc264f8bde0f58391fc226243d03e78aa7b (diff) | |
download | go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.gz go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.bz2 go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.lz go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.xz go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.tar.zst go-tangerine-e5532154a50114d5ffb1ffd850b746cab00cb899.zip |
Merge branch 'release/1.3.0'
Conflicts:
VERSION
cmd/geth/main.go
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/evm/main.go | 68 | ||||
-rw-r--r-- | cmd/geth/blocktestcmd.go | 12 | ||||
-rw-r--r-- | cmd/geth/chaincmd.go | 6 | ||||
-rw-r--r-- | cmd/geth/js.go | 83 | ||||
-rw-r--r-- | cmd/geth/js_test.go | 15 | ||||
-rw-r--r-- | cmd/geth/main.go | 149 | ||||
-rw-r--r-- | cmd/geth/usage.go | 212 | ||||
-rw-r--r-- | cmd/utils/cmd.go | 29 | ||||
-rw-r--r-- | cmd/utils/flags.go | 223 |
9 files changed, 543 insertions, 254 deletions
diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 243dd6266..64044c421 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -80,12 +80,17 @@ var ( Name: "sysstat", Usage: "display system stats", } + VerbosityFlag = cli.IntFlag{ + Name: "verbosity", + Usage: "sets the verbosity level", + } ) func init() { app = utils.NewApp("0.2", "the evm command line interface") app.Flags = []cli.Flag{ DebugFlag, + VerbosityFlag, ForceJitFlag, DisableJitFlag, SysStatFlag, @@ -105,9 +110,10 @@ func run(ctx *cli.Context) { vm.EnableJit = !ctx.GlobalBool(DisableJitFlag.Name) glog.SetToStderr(true) + glog.SetV(ctx.GlobalInt(VerbosityFlag.Name)) db, _ := ethdb.NewMemDatabase() - statedb := state.New(common.Hash{}, db) + statedb, _ := state.New(common.Hash{}, db) sender := statedb.CreateAccount(common.StringToAddress("sender")) receiver := statedb.CreateAccount(common.StringToAddress("receiver")) receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))) @@ -179,18 +185,20 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int) *VM } } -func (self *VMEnv) State() *state.StateDB { return self.state } -func (self *VMEnv) Origin() common.Address { return *self.transactor } -func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 } -func (self *VMEnv) Coinbase() common.Address { return *self.transactor } -func (self *VMEnv) Time() *big.Int { return self.time } -func (self *VMEnv) Difficulty() *big.Int { return common.Big1 } -func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) } -func (self *VMEnv) Value() *big.Int { return self.value } -func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) } -func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy } -func (self *VMEnv) Depth() int { return 0 } -func (self *VMEnv) SetDepth(i int) { self.depth = i } +func (self *VMEnv) Db() vm.Database { return self.state } +func (self *VMEnv) MakeSnapshot() vm.Database { return self.state.Copy() } +func (self *VMEnv) SetSnapshot(db vm.Database) { self.state.Set(db.(*state.StateDB)) } +func (self *VMEnv) Origin() common.Address { return *self.transactor } +func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 } +func (self *VMEnv) Coinbase() common.Address { return *self.transactor } +func (self *VMEnv) Time() *big.Int { return self.time } +func (self *VMEnv) Difficulty() *big.Int { return common.Big1 } +func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) } +func (self *VMEnv) Value() *big.Int { return self.value } +func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) } +func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy } +func (self *VMEnv) Depth() int { return 0 } +func (self *VMEnv) SetDepth(i int) { self.depth = i } func (self *VMEnv) GetHash(n uint64) common.Hash { if self.block.Number().Cmp(big.NewInt(int64(n))) == 0 { return self.block.Hash() @@ -203,34 +211,24 @@ func (self *VMEnv) AddStructLog(log vm.StructLog) { func (self *VMEnv) StructLogs() []vm.StructLog { return self.logs } -func (self *VMEnv) AddLog(log *state.Log) { +func (self *VMEnv) AddLog(log *vm.Log) { self.state.AddLog(log) } -func (self *VMEnv) CanTransfer(from vm.Account, balance *big.Int) bool { - return from.Balance().Cmp(balance) >= 0 -} -func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error { - return vm.Transfer(from, to, amount) +func (self *VMEnv) CanTransfer(from common.Address, balance *big.Int) bool { + return self.state.GetBalance(from).Cmp(balance) >= 0 } - -func (self *VMEnv) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *core.Execution { - return core.NewExecution(self, addr, data, gas, price, value) +func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) { + core.Transfer(from, to, amount) } -func (self *VMEnv) Call(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - exe := self.vm(&addr, data, gas, price, value) - ret, err := exe.Call(addr, caller) - self.Gas = exe.Gas - - return ret, err +func (self *VMEnv) Call(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { + self.Gas = gas + return core.Call(self, caller, addr, data, gas, price, value) } -func (self *VMEnv) CallCode(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - a := caller.Address() - exe := self.vm(&a, data, gas, price, value) - return exe.Call(addr, caller) +func (self *VMEnv) CallCode(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { + return core.CallCode(self, caller, addr, data, gas, price, value) } -func (self *VMEnv) Create(caller vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { - exe := self.vm(nil, data, gas, price, value) - return exe.Create(caller) +func (self *VMEnv) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) { + return core.Create(self, caller, data, gas, price, value) } diff --git a/cmd/geth/blocktestcmd.go b/cmd/geth/blocktestcmd.go index d6195e025..e4d97aa53 100644 --- a/cmd/geth/blocktestcmd.go +++ b/cmd/geth/blocktestcmd.go @@ -101,7 +101,8 @@ func runBlockTest(ctx *cli.Context) { func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) { cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx) - cfg.NewDB = func(path string) (ethdb.Database, error) { return ethdb.NewMemDatabase() } + db, _ := ethdb.NewMemDatabase() + cfg.NewDB = func(path string) (ethdb.Database, error) { return db, nil } cfg.MaxPeers = 0 // disable network cfg.Shh = false // disable whisper cfg.NAT = nil // disable port mapping @@ -113,17 +114,20 @@ func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, er // import the genesis block ethereum.ResetWithGenesisBlock(test.Genesis) // import pre accounts - _, err = test.InsertPreState(ethereum) + _, err = test.InsertPreState(db, cfg.AccountManager) if err != nil { return ethereum, fmt.Errorf("InsertPreState: %v", err) } - cm := ethereum.ChainManager() + cm := ethereum.BlockChain() validBlocks, err := test.TryBlocksInsert(cm) if err != nil { return ethereum, fmt.Errorf("Block Test load error: %v", err) } - newDB := cm.State() + newDB, err := cm.State() + if err != nil { + return ethereum, fmt.Errorf("Block Test get state error: %v", err) + } if err := test.ValidatePostState(newDB); err != nil { return ethereum, fmt.Errorf("post state validation failed: %v", err) } diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index c5bc4b66a..80f3777d6 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -179,7 +179,11 @@ func dump(ctx *cli.Context) { fmt.Println("{}") utils.Fatalf("block not found") } else { - state := state.New(block.Root(), chainDb) + state, err := state.New(block.Root(), chainDb) + if err != nil { + utils.Fatalf("could not create new state: %v", err) + return + } fmt.Printf("%s\n", state.Dump()) } } diff --git a/cmd/geth/js.go b/cmd/geth/js.go index 3e3600705..4d5462539 100644 --- a/cmd/geth/js.go +++ b/cmd/geth/js.go @@ -30,7 +30,6 @@ import ( "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/docserver" "github.com/ethereum/go-ethereum/common/natspec" "github.com/ethereum/go-ethereum/common/registrar" "github.com/ethereum/go-ethereum/eth" @@ -45,9 +44,12 @@ import ( "github.com/robertkrimen/otto" ) -var passwordRegexp = regexp.MustCompile("personal.[nu]") - -const passwordRepl = "" +var ( + passwordRegexp = regexp.MustCompile("personal.[nu]") + leadingSpace = regexp.MustCompile("^ ") + onlyws = regexp.MustCompile("^\\s*$") + exit = regexp.MustCompile("^\\s*exit\\s*;*\\s*$") +) type prompter interface { AppendHistory(string) @@ -74,7 +76,6 @@ func (r dumbterm) PasswordPrompt(p string) (string, error) { func (r dumbterm) AppendHistory(string) {} type jsre struct { - ds *docserver.DocServer re *re.JSRE ethereum *eth.Ethereum xeth *xeth.XEth @@ -145,14 +146,13 @@ func apiWordCompleter(line string, pos int) (head string, completions []string, return begin, completionWords, end } -func newLightweightJSRE(libPath string, client comms.EthereumClient, interactive bool) *jsre { +func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir string, interactive bool) *jsre { js := &jsre{ps1: "> "} js.wait = make(chan *big.Int) js.client = client - js.ds = docserver.New("/") // update state in separare forever blocks - js.re = re.New(libPath) + js.re = re.New(docRoot) if err := js.apiBindings(js); err != nil { utils.Fatalf("Unable to initialize console - %v", err) } @@ -161,14 +161,14 @@ func newLightweightJSRE(libPath string, client comms.EthereumClient, interactive js.prompter = dumbterm{bufio.NewReader(os.Stdin)} } else { lr := liner.NewLiner() - js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) }) + js.withHistory(datadir, func(hist *os.File) { lr.ReadHistory(hist) }) lr.SetCtrlCAborts(true) js.loadAutoCompletion() lr.SetWordCompleter(apiWordCompleter) lr.SetTabCompletionStyle(liner.TabPrints) js.prompter = lr js.atexit = func() { - js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) }) + js.withHistory(datadir, func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) }) lr.Close() close(js.wait) } @@ -176,14 +176,13 @@ func newLightweightJSRE(libPath string, client comms.EthereumClient, interactive return js } -func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre { +func newJSRE(ethereum *eth.Ethereum, docRoot, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre { js := &jsre{ethereum: ethereum, ps1: "> "} // set default cors domain used by startRpc from CLI flag js.corsDomain = corsDomain if f == nil { f = js } - js.ds = docserver.New("/") js.xeth = xeth.New(ethereum, f) js.wait = js.xeth.UpdateState() js.client = client @@ -194,7 +193,7 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, client comms.Et } // update state in separare forever blocks - js.re = re.New(libPath) + js.re = re.New(docRoot) if err := js.apiBindings(f); err != nil { utils.Fatalf("Unable to connect - %v", err) } @@ -203,14 +202,14 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, client comms.Et js.prompter = dumbterm{bufio.NewReader(os.Stdin)} } else { lr := liner.NewLiner() - js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) }) + js.withHistory(ethereum.DataDir, func(hist *os.File) { lr.ReadHistory(hist) }) lr.SetCtrlCAborts(true) js.loadAutoCompletion() lr.SetWordCompleter(apiWordCompleter) lr.SetTabCompletionStyle(liner.TabPrints) js.prompter = lr js.atexit = func() { - js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) }) + js.withHistory(ethereum.DataDir, func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) }) lr.Close() close(js.wait) } @@ -244,14 +243,14 @@ func (self *jsre) batch(statement string) { // show summary of current geth instance func (self *jsre) welcome() { self.re.Run(` - (function () { - console.log('instance: ' + web3.version.client); - console.log(' datadir: ' + admin.datadir); - console.log("coinbase: " + eth.coinbase); - var ts = 1000 * eth.getBlock(eth.blockNumber).timestamp; - console.log("at block: " + eth.blockNumber + " (" + new Date(ts) + ")"); - })(); - `) + (function () { + console.log('instance: ' + web3.version.client); + console.log(' datadir: ' + admin.datadir); + console.log("coinbase: " + eth.coinbase); + var ts = 1000 * eth.getBlock(eth.blockNumber).timestamp; + console.log("at block: " + eth.blockNumber + " (" + new Date(ts) + ")"); + })(); + `) if modules, err := self.supportedApis(); err == nil { loadedModules := make([]string, 0) for api, version := range modules { @@ -330,13 +329,21 @@ func (js *jsre) apiBindings(f xeth.Frontend) error { utils.Fatalf("Error setting namespaces: %v", err) } - js.re.Run(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `); registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`) + js.re.Run(`var GlobalRegistrar = eth.contract(` + registrar.GlobalRegistrarAbi + `); registrar = GlobalRegistrar.at("` + registrar.GlobalRegistrarAddr + `");`) return nil } +func (self *jsre) AskPassword() (string, bool) { + pass, err := self.PasswordPrompt("Passphrase: ") + if err != nil { + return "", false + } + return pass, true +} + func (self *jsre) ConfirmTransaction(tx string) bool { if self.ethereum.NatSpec { - notice := natspec.GetNotice(self.xeth, tx, self.ds) + notice := natspec.GetNotice(self.xeth, tx, self.ethereum.HTTPClient()) fmt.Println(notice) answer, _ := self.Prompt("Confirm Transaction [y/n]") return strings.HasPrefix(strings.Trim(answer, " "), "y") @@ -405,18 +412,17 @@ func (self *jsre) interactive() { fmt.Println("caught interrupt, exiting") return case input, ok := <-inputln: - if !ok || indentCount <= 0 && input == "exit" { + if !ok || indentCount <= 0 && exit.MatchString(input) { return } - if input == "" { + if onlyws.MatchString(input) { continue } str += input + "\n" self.setIndent() if indentCount <= 0 { - hist := hidepassword(str[:len(str)-1]) - if len(hist) > 0 { - self.AppendHistory(hist) + if mustLogInHistory(str) { + self.AppendHistory(str[:len(str)-1]) } self.parseInput(str) str = "" @@ -425,20 +431,13 @@ func (self *jsre) interactive() { } } -func hidepassword(input string) string { - if passwordRegexp.MatchString(input) { - return passwordRepl - } else { - return input - } +func mustLogInHistory(input string) bool { + return len(input) == 0 || + passwordRegexp.MatchString(input) || + !leadingSpace.MatchString(input) } -func (self *jsre) withHistory(op func(*os.File)) { - datadir := common.DefaultDataDir() - if self.ethereum != nil { - datadir = self.ethereum.DataDir - } - +func (self *jsre) withHistory(datadir string, op func(*os.File)) { hist, err := os.OpenFile(filepath.Join(datadir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm) if err != nil { fmt.Printf("unable to open history file: %v\n", err) diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go index 1f5b28e3a..477079706 100644 --- a/cmd/geth/js_test.go +++ b/cmd/geth/js_test.go @@ -31,7 +31,7 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/compiler" - "github.com/ethereum/go-ethereum/common/docserver" + "github.com/ethereum/go-ethereum/common/httpclient" "github.com/ethereum/go-ethereum/common/natspec" "github.com/ethereum/go-ethereum/common/registrar" "github.com/ethereum/go-ethereum/core" @@ -62,7 +62,7 @@ var ( type testjethre struct { *jsre lastConfirm string - ds *docserver.DocServer + client *httpclient.HTTPClient } func (self *testjethre) UnlockAccount(acc []byte) bool { @@ -75,7 +75,7 @@ func (self *testjethre) UnlockAccount(acc []byte) bool { func (self *testjethre) ConfirmTransaction(tx string) bool { if self.ethereum.NatSpec { - self.lastConfirm = natspec.GetNotice(self.xeth, tx, self.ds) + self.lastConfirm = natspec.GetNotice(self.xeth, tx, self.client) } return true } @@ -101,6 +101,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *eth AccountManager: am, MaxPeers: 0, Name: "test", + DocRoot: "/", SolcPath: testSolcPath, PowTest: true, NewDB: func(path string) (ethdb.Database, error) { return db, nil }, @@ -130,8 +131,7 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *eth assetPath := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext") client := comms.NewInProcClient(codec.JSON) - ds := docserver.New("/") - tf := &testjethre{ds: ds} + tf := &testjethre{client: ethereum.HTTPClient()} repl := newJSRE(ethereum, assetPath, "", client, false, tf) tf.jsre = repl return tmp, tf, ethereum @@ -196,7 +196,7 @@ func TestBlockChain(t *testing.T) { tmpfile := filepath.Join(extmp, "export.chain") tmpfileq := strconv.Quote(tmpfile) - ethereum.ChainManager().Reset() + ethereum.BlockChain().Reset() checkEvalJSON(t, repl, `admin.exportChain(`+tmpfileq+`)`, `true`) if _, err := os.Stat(tmpfile); err != nil { @@ -468,8 +468,7 @@ func processTxs(repl *testjethre, t *testing.T, expTxc int) bool { t.Errorf("incorrect number of pending transactions, expected %v, got %v", expTxc, txc) return false } - - err = repl.ethereum.StartMining(runtime.NumCPU()) + err = repl.ethereum.StartMining(runtime.NumCPU(), "") if err != nil { t.Errorf("unexpected error mining: %v", err) return false diff --git a/cmd/geth/main.go b/cmd/geth/main.go index e4e54c73c..f70a0bb67 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -48,9 +48,9 @@ import ( const ( ClientIdentifier = "Geth" - Version = "1.2.1" + Version = "1.3.1" VersionMajor = 1 - VersionMinor = 2 + VersionMinor = 3 VersionPatch = 1 ) @@ -58,11 +58,6 @@ var ( gitCommit string // set via linker flagg nodeNameVersion string app *cli.App - - ExtraDataFlag = cli.StringFlag{ - Name: "extradata", - Usage: "Extra data for the miner", - } ) func init() { @@ -79,7 +74,7 @@ func init() { { Action: blockRecovery, Name: "recover", - Usage: "attempts to recover a corrupted database by setting a new block by number or hash. See help recover.", + Usage: "Attempts to recover a corrupted database by setting a new block by number or hash", Description: ` The recover commands will attempt to read out the last block based on that. @@ -107,6 +102,22 @@ Regular users do not need to execute it. `, }, { + Action: gpuinfo, + Name: "gpuinfo", + Usage: "gpuinfo", + Description: ` +Prints OpenCL device info for all found GPUs. +`, + }, + { + Action: gpubench, + Name: "gpubench", + Usage: "benchmark GPU", + Description: ` +Runs quick benchmark on first GPU found. +`, + }, + { Action: version, Name: "version", Usage: "print ethereum version numbers", @@ -160,8 +171,12 @@ It is safe to transfer the entire directory or the individual keys therein between ethereum nodes by simply copying. Make sure you backup your keys regularly. -In order to use your account to send transactions, you need to unlock them using the -'--unlock' option. The argument is a comma +In order to use your account to send transactions, you need to unlock them using +the '--unlock' option. The argument is a space separated list of addresses or +indexes. If used non-interactively with a passwordfile, the file should contain +the respective passwords one per line. If you unlock n accounts and the password +file contains less than n entries, then the last password is meant to apply to +all remaining accounts. And finally. DO NOT FORGET YOUR PASSWORD. `, @@ -211,7 +226,7 @@ format to the newest format or change the password for an account. For non-interactive use the passphrase can be specified with the --password flag: - ethereum --password <passwordfile> account new + ethereum --password <passwordfile> account update <address> Since only one password can be given, only format update can be performed, changing your password is only possible interactively. @@ -288,7 +303,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.DataDirFlag, utils.BlockchainVersionFlag, utils.OlympicFlag, - utils.EthVersionFlag, + utils.FastSyncFlag, utils.CacheFlag, utils.JSpathFlag, utils.ListenPortFlag, @@ -298,6 +313,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.GasPriceFlag, utils.MinerThreadsFlag, utils.MiningEnabledFlag, + utils.MiningGPUFlag, utils.AutoDAGFlag, utils.NATFlag, utils.NatspecEnabledFlag, @@ -314,6 +330,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.ExecFlag, utils.WhisperEnabledFlag, utils.DevModeFlag, + utils.TestNetFlag, utils.VMDebugFlag, utils.VMForceJitFlag, utils.VMJitCacheFlag, @@ -322,10 +339,8 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.RPCCORSDomainFlag, utils.VerbosityFlag, utils.BacktraceAtFlag, - utils.LogToStdErrFlag, utils.LogVModuleFlag, utils.LogFileFlag, - utils.LogJSONFlag, utils.PProfEanbledFlag, utils.PProfPortFlag, utils.MetricsEnabledFlag, @@ -336,12 +351,12 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.GpobaseStepDownFlag, utils.GpobaseStepUpFlag, utils.GpobaseCorrectionFactorFlag, - ExtraDataFlag, + utils.ExtraDataFlag, } app.Before = func(ctx *cli.Context) error { utils.SetupLogger(ctx) + utils.SetupNetwork(ctx) utils.SetupVM(ctx) - utils.SetupEth(ctx) if ctx.GlobalBool(utils.PProfEanbledFlag.Name) { utils.StartPProf(ctx) } @@ -362,8 +377,8 @@ func main() { // makeExtra resolves extradata for the miner from a flag or returns a default. func makeExtra(ctx *cli.Context) []byte { - if ctx.GlobalIsSet(ExtraDataFlag.Name) { - return []byte(ctx.GlobalString(ExtraDataFlag.Name)) + if ctx.GlobalIsSet(utils.ExtraDataFlag.Name) { + return []byte(ctx.GlobalString(utils.ExtraDataFlag.Name)) } return makeDefaultExtra() } @@ -385,15 +400,11 @@ func makeDefaultExtra() []byte { glog.V(logger.Debug).Infof("extra: %x\n", extra) return nil } - return extra } func run(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) - if ctx.GlobalBool(utils.OlympicFlag.Name) { - utils.InitOlympic() - } + utils.CheckLegalese(utils.MustDataDir(ctx)) cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx) cfg.ExtraData = makeExtra(ctx) @@ -409,7 +420,7 @@ func run(ctx *cli.Context) { } func attach(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) var client comms.EthereumClient var err error @@ -429,6 +440,7 @@ func attach(ctx *cli.Context) { repl := newLightweightJSRE( ctx.GlobalString(utils.JSpathFlag.Name), client, + ctx.GlobalString(utils.DataDirFlag.Name), true, ) @@ -441,7 +453,7 @@ func attach(ctx *cli.Context) { } func console(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx) cfg.ExtraData = makeExtra(ctx) @@ -475,7 +487,7 @@ func console(ctx *cli.Context) { } func execJSFiles(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx) ethereum, err := eth.New(cfg) @@ -501,33 +513,34 @@ func execJSFiles(ctx *cli.Context) { ethereum.WaitForShutdown() } -func unlockAccount(ctx *cli.Context, am *accounts.Manager, addr string, i int) (addrHex, auth string) { +func unlockAccount(ctx *cli.Context, am *accounts.Manager, addr string, i int, inputpassphrases []string) (addrHex, auth string, passphrases []string) { utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) var err error + passphrases = inputpassphrases addrHex, err = utils.ParamToAddress(addr, am) if err == nil { // Attempt to unlock the account 3 times attempts := 3 for tries := 0; tries < attempts; tries++ { msg := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", addr, tries+1, attempts) - auth = getPassPhrase(ctx, msg, false, i) + auth, passphrases = getPassPhrase(ctx, msg, false, i, passphrases) err = am.Unlock(common.HexToAddress(addrHex), auth) - if err == nil { + if err == nil || passphrases != nil { break } } } if err != nil { - utils.Fatalf("Unlock account failed '%v'", err) + utils.Fatalf("Unlock account '%s' (%v) failed: %v", addr, addrHex, err) } - fmt.Printf("Account '%s' unlocked.\n", addr) + fmt.Printf("Account '%s' (%v) unlocked.\n", addr, addrHex) return } func blockRecovery(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) arg := ctx.Args().First() if len(ctx.Args()) < 1 && len(arg) > 0 { @@ -566,12 +579,13 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) { am := eth.AccountManager() account := ctx.GlobalString(utils.UnlockedAccountFlag.Name) accounts := strings.Split(account, " ") + var passphrases []string for i, account := range accounts { if len(account) > 0 { if account == "primary" { utils.Fatalf("the 'primary' keyword is deprecated. You can use integer indexes, but the indexes are not permanent, they can change if you add external keys, export your keys or copy your keystore to another node.") } - unlockAccount(ctx, am, account, i) + _, _, passphrases = unlockAccount(ctx, am, account, i, passphrases) } } // Start auxiliary services if enabled. @@ -586,14 +600,17 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) { } } if ctx.GlobalBool(utils.MiningEnabledFlag.Name) { - if err := eth.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name)); err != nil { + err := eth.StartMining( + ctx.GlobalInt(utils.MinerThreadsFlag.Name), + ctx.GlobalString(utils.MiningGPUFlag.Name)) + if err != nil { utils.Fatalf("%v", err) } } } func accountList(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) am := utils.MakeAccountManager(ctx) accts, err := am.Accounts() @@ -605,7 +622,7 @@ func accountList(ctx *cli.Context) { } } -func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int) (passphrase string) { +func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int, inputpassphrases []string) (passphrase string, passphrases []string) { passfile := ctx.GlobalString(utils.PasswordFileFlag.Name) if len(passfile) == 0 { fmt.Println(desc) @@ -625,14 +642,17 @@ func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int) (pas passphrase = auth } else { - passbytes, err := ioutil.ReadFile(passfile) - if err != nil { - utils.Fatalf("Unable to read password file '%s': %v", passfile, err) + passphrases = inputpassphrases + if passphrases == nil { + passbytes, err := ioutil.ReadFile(passfile) + if err != nil { + utils.Fatalf("Unable to read password file '%s': %v", passfile, err) + } + // this is backwards compatible if the same password unlocks several accounts + // it also has the consequence that trailing newlines will not count as part + // of the password, so --password <(echo -n 'pass') will now work without -n + passphrases = strings.Split(string(passbytes), "\n") } - // this is backwards compatible if the same password unlocks several accounts - // it also has the consequence that trailing newlines will not count as part - // of the password, so --password <(echo -n 'pass') will now work without -n - passphrases := strings.Split(string(passbytes), "\n") if i >= len(passphrases) { passphrase = passphrases[len(passphrases)-1] } else { @@ -643,10 +663,10 @@ func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int) (pas } func accountCreate(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) am := utils.MakeAccountManager(ctx) - passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0) + passphrase, _ := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, nil) acct, err := am.NewAccount(passphrase) if err != nil { utils.Fatalf("Could not create the account: %v", err) @@ -655,7 +675,7 @@ func accountCreate(ctx *cli.Context) { } func accountUpdate(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) am := utils.MakeAccountManager(ctx) arg := ctx.Args().First() @@ -663,8 +683,8 @@ func accountUpdate(ctx *cli.Context) { utils.Fatalf("account address or index must be given as argument") } - addr, authFrom := unlockAccount(ctx, am, arg, 0) - authTo := getPassPhrase(ctx, "Please give a new password. Do not forget this password.", true, 0) + addr, authFrom, passphrases := unlockAccount(ctx, am, arg, 0, nil) + authTo, _ := getPassPhrase(ctx, "Please give a new password. Do not forget this password.", true, 0, passphrases) err := am.Update(common.HexToAddress(addr), authFrom, authTo) if err != nil { utils.Fatalf("Could not update the account: %v", err) @@ -672,7 +692,7 @@ func accountUpdate(ctx *cli.Context) { } func importWallet(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) keyfile := ctx.Args().First() if len(keyfile) == 0 { @@ -684,7 +704,7 @@ func importWallet(ctx *cli.Context) { } am := utils.MakeAccountManager(ctx) - passphrase := getPassPhrase(ctx, "", false, 0) + passphrase, _ := getPassPhrase(ctx, "", false, 0, nil) acct, err := am.ImportPreSaleKey(keyJson, passphrase) if err != nil { @@ -694,14 +714,14 @@ func importWallet(ctx *cli.Context) { } func accountImport(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) keyfile := ctx.Args().First() if len(keyfile) == 0 { utils.Fatalf("keyfile must be given as argument") } am := utils.MakeAccountManager(ctx) - passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0) + passphrase, _ := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, nil) acct, err := am.Import(keyfile, passphrase) if err != nil { utils.Fatalf("Could not create the account: %v", err) @@ -710,7 +730,7 @@ func accountImport(ctx *cli.Context) { } func makedag(ctx *cli.Context) { - utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name)) + utils.CheckLegalese(utils.MustDataDir(ctx)) args := ctx.Args() wrongArgs := func() { @@ -740,6 +760,29 @@ func makedag(ctx *cli.Context) { } } +func gpuinfo(ctx *cli.Context) { + eth.PrintOpenCLDevices() +} + +func gpubench(ctx *cli.Context) { + args := ctx.Args() + wrongArgs := func() { + utils.Fatalf(`Usage: geth gpubench <gpu number>`) + } + switch { + case len(args) == 1: + n, err := strconv.ParseUint(args[0], 0, 64) + if err != nil { + wrongArgs() + } + eth.GPUBench(n) + case len(args) == 0: + eth.GPUBench(0) + default: + wrongArgs() + } +} + func version(c *cli.Context) { fmt.Println(ClientIdentifier) fmt.Println("Version:", Version) diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go new file mode 100644 index 000000000..9223b7cd6 --- /dev/null +++ b/cmd/geth/usage.go @@ -0,0 +1,212 @@ +// Copyright 2015 The go-ethereum Authors +// 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/>. + +// Contains the geth command usage template and generator. + +package main + +import ( + "io" + + "github.com/codegangsta/cli" + "github.com/ethereum/go-ethereum/cmd/utils" +) + +// AppHelpTemplate is the test template for the default, global app help topic. +var AppHelpTemplate = `NAME: + {{.App.Name}} - {{.App.Usage}} + +USAGE: + {{.App.HelpName}} [options]{{if .App.Commands}} command [command options]{{end}} {{if .App.ArgsUsage}}{{.App.ArgsUsage}}{{else}}[arguments...]{{end}} + {{if .App.Version}} +VERSION: + {{.App.Version}} + {{end}}{{if len .App.Authors}} +AUTHOR(S): + {{range .App.Authors}}{{ . }}{{end}} + {{end}}{{if .App.Commands}} +COMMANDS: + {{range .App.Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} + {{end}}{{end}}{{if .FlagGroups}} +{{range .FlagGroups}}{{.Name}} OPTIONS: + {{range .Flags}}{{.}} + {{end}} +{{end}}{{end}}{{if .App.Copyright }} +COPYRIGHT: + {{.App.Copyright}} + {{end}} +` + +// flagGroup is a collection of flags belonging to a single topic. +type flagGroup struct { + Name string + Flags []cli.Flag +} + +// AppHelpFlagGroups is the application flags, grouped by functionality. +var AppHelpFlagGroups = []flagGroup{ + { + Name: "ETHEREUM", + Flags: []cli.Flag{ + utils.DataDirFlag, + utils.NetworkIdFlag, + utils.OlympicFlag, + utils.TestNetFlag, + utils.DevModeFlag, + utils.GenesisFileFlag, + utils.IdentityFlag, + utils.FastSyncFlag, + utils.CacheFlag, + utils.BlockchainVersionFlag, + }, + }, + { + Name: "ACCOUNT", + Flags: []cli.Flag{ + utils.UnlockedAccountFlag, + utils.PasswordFileFlag, + }, + }, + { + Name: "API AND CONSOLE", + Flags: []cli.Flag{ + utils.RPCEnabledFlag, + utils.RPCListenAddrFlag, + utils.RPCPortFlag, + utils.RpcApiFlag, + utils.IPCDisabledFlag, + utils.IPCApiFlag, + utils.IPCPathFlag, + utils.RPCCORSDomainFlag, + utils.JSpathFlag, + utils.ExecFlag, + }, + }, + { + Name: "NETWORKING", + Flags: []cli.Flag{ + utils.BootnodesFlag, + utils.ListenPortFlag, + utils.MaxPeersFlag, + utils.MaxPendingPeersFlag, + utils.NATFlag, + utils.NoDiscoverFlag, + utils.NodeKeyFileFlag, + utils.NodeKeyHexFlag, + }, + }, + { + Name: "MINER", + Flags: []cli.Flag{ + utils.MiningEnabledFlag, + utils.MinerThreadsFlag, + utils.MiningGPUFlag, + utils.AutoDAGFlag, + utils.EtherbaseFlag, + utils.GasPriceFlag, + utils.ExtraDataFlag, + }, + }, + { + Name: "GAS PRICE ORACLE", + Flags: []cli.Flag{ + utils.GpoMinGasPriceFlag, + utils.GpoMaxGasPriceFlag, + utils.GpoFullBlockRatioFlag, + utils.GpobaseStepDownFlag, + utils.GpobaseStepUpFlag, + utils.GpobaseCorrectionFactorFlag, + }, + }, + { + Name: "VIRTUAL MACHINE", + Flags: []cli.Flag{ + utils.VMDebugFlag, + utils.VMEnableJitFlag, + utils.VMForceJitFlag, + utils.VMJitCacheFlag, + }, + }, + { + Name: "LOGGING AND DEBUGGING", + Flags: []cli.Flag{ + utils.VerbosityFlag, + utils.LogVModuleFlag, + utils.BacktraceAtFlag, + utils.LogFileFlag, + utils.PProfEanbledFlag, + utils.PProfPortFlag, + utils.MetricsEnabledFlag, + }, + }, + { + Name: "EXPERIMENTAL", + Flags: []cli.Flag{ + utils.WhisperEnabledFlag, + utils.NatspecEnabledFlag, + }, + }, + { + Name: "MISCELLANEOUS", + Flags: []cli.Flag{ + utils.SolcPathFlag, + }, + }, +} + +func init() { + // Override the default app help template + cli.AppHelpTemplate = AppHelpTemplate + + // Define a one shot struct to pass to the usage template + type helpData struct { + App interface{} + FlagGroups []flagGroup + } + // Override the default app help printer, but only for the global app help + originalHelpPrinter := cli.HelpPrinter + cli.HelpPrinter = func(w io.Writer, tmpl string, data interface{}) { + if tmpl == AppHelpTemplate { + // Iterate over all the flags and add any uncategorized ones + categorized := make(map[string]struct{}) + for _, group := range AppHelpFlagGroups { + for _, flag := range group.Flags { + categorized[flag.String()] = struct{}{} + } + } + uncategorized := []cli.Flag{} + for _, flag := range data.(*cli.App).Flags { + if _, ok := categorized[flag.String()]; !ok { + uncategorized = append(uncategorized, flag) + } + } + if len(uncategorized) > 0 { + // Append all ungategorized options to the misc group + miscs := len(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags) + AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = append(AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags, uncategorized...) + + // Make sure they are removed afterwards + defer func() { + AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags = AppHelpFlagGroups[len(AppHelpFlagGroups)-1].Flags[:miscs] + }() + } + // Render out custom usage screen + originalHelpPrinter(w, tmpl, helpData{data, AppHelpFlagGroups}) + } else { + originalHelpPrinter(w, tmpl, data) + } + } +} diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 983762db8..9b75ccab4 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -21,8 +21,6 @@ import ( "bufio" "fmt" "io" - "math" - "math/big" "os" "os/signal" "regexp" @@ -34,7 +32,6 @@ import ( "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" - "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/peterh/liner" ) @@ -43,7 +40,9 @@ const ( importBatchSize = 2500 ) -var interruptCallbacks = []func(os.Signal){} +var ( + interruptCallbacks = []func(os.Signal){} +) func openLogFile(Datadir string, filename string) *os.File { path := common.AbsolutePath(Datadir, filename) @@ -146,16 +145,6 @@ func StartEthereum(ethereum *eth.Ethereum) { }() } -func InitOlympic() { - params.DurationLimit = big.NewInt(8) - params.GenesisGasLimit = big.NewInt(3141592) - params.MinGasLimit = big.NewInt(125000) - params.MaximumExtraDataSize = big.NewInt(1024) - NetworkIdFlag.Value = 0 - core.BlockReward = big.NewInt(1.5e+18) - core.ExpDiffPeriod = big.NewInt(math.MaxInt64) -} - func FormatTransactionData(data string) []byte { d := common.StringToByteFunc(data, func(s string) (ret []byte) { slice := regexp.MustCompile("\\n|\\s").Split(s, 1000000000) @@ -169,7 +158,7 @@ func FormatTransactionData(data string) []byte { return d } -func ImportChain(chain *core.ChainManager, fn string) error { +func ImportChain(chain *core.BlockChain, fn string) error { // Watch for Ctrl-C while the import is running. // If a signal is received, the import will stop at the next batch. interrupt := make(chan os.Signal, 1) @@ -244,7 +233,7 @@ func ImportChain(chain *core.ChainManager, fn string) error { return nil } -func hasAllBlocks(chain *core.ChainManager, bs []*types.Block) bool { +func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool { for _, b := range bs { if !chain.HasBlock(b.Hash()) { return false @@ -253,21 +242,21 @@ func hasAllBlocks(chain *core.ChainManager, bs []*types.Block) bool { return true } -func ExportChain(chainmgr *core.ChainManager, fn string) error { +func ExportChain(blockchain *core.BlockChain, fn string) error { glog.Infoln("Exporting blockchain to", fn) fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) if err != nil { return err } defer fh.Close() - if err := chainmgr.Export(fh); err != nil { + if err := blockchain.Export(fh); err != nil { return err } glog.Infoln("Exported blockchain to", fn) return nil } -func ExportAppendChain(chainmgr *core.ChainManager, fn string, first uint64, last uint64) error { +func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, last uint64) error { glog.Infoln("Exporting blockchain to", fn) // TODO verify mode perms fh, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm) @@ -275,7 +264,7 @@ func ExportAppendChain(chainmgr *core.ChainManager, fn string, first uint64, las return err } defer fh.Close() - if err := chainmgr.ExportN(fh, first, last); err != nil { + if err := blockchain.ExportN(fh, first, last); err != nil { return err } glog.Infoln("Exported blockchain to", fn) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b45ef0af2..d741d0544 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -20,6 +20,7 @@ import ( "crypto/ecdsa" "fmt" "log" + "math" "math/big" "net" "net/http" @@ -42,6 +43,7 @@ import ( "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p/nat" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/comms" @@ -99,31 +101,29 @@ var ( // General settings DataDirFlag = DirectoryFlag{ Name: "datadir", - Usage: "Data directory to be used", + Usage: "Data directory for the databases and keystore", Value: DirectoryString{common.DefaultDataDir()}, } NetworkIdFlag = cli.IntFlag{ Name: "networkid", - Usage: "Network Id (integer)", + Usage: "Network identifier (integer, 0=Olympic, 1=Frontier, 2=Morden)", Value: eth.NetworkId, } - BlockchainVersionFlag = cli.IntFlag{ - Name: "blockchainversion", - Usage: "Blockchain version (integer)", - Value: core.BlockChainVersion, + OlympicFlag = cli.BoolFlag{ + Name: "olympic", + Usage: "Olympic network: pre-configured pre-release test network", } - GenesisNonceFlag = cli.IntFlag{ - Name: "genesisnonce", - Usage: "Sets the genesis nonce", - Value: 42, - } - GenesisFileFlag = cli.StringFlag{ - Name: "genesis", - Usage: "Inserts/Overwrites the genesis block (json format)", + TestNetFlag = cli.BoolFlag{ + Name: "testnet", + Usage: "Morden network: pre-configured test network with modified starting nonces (replay protection)", } DevModeFlag = cli.BoolFlag{ Name: "dev", - Usage: "Developer mode. This mode creates a private network and sets several debugging flags", + Usage: "Developer mode: pre-configured private network with several debugging flags", + } + GenesisFileFlag = cli.StringFlag{ + Name: "genesis", + Usage: "Insert/overwrite the genesis block (JSON format)", } IdentityFlag = cli.StringFlag{ Name: "identity", @@ -133,54 +133,71 @@ var ( Name: "natspec", Usage: "Enable NatSpec confirmation notice", } + DocRootFlag = DirectoryFlag{ + Name: "docroot", + Usage: "Document Root for HTTPClient file scheme", + Value: DirectoryString{common.HomeDir()}, + } CacheFlag = cli.IntFlag{ Name: "cache", - Usage: "Megabytes of memory allocated to internal caching", + Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)", Value: 0, } - OlympicFlag = cli.BoolFlag{ - Name: "olympic", - Usage: "Use olympic style protocol", + BlockchainVersionFlag = cli.IntFlag{ + Name: "blockchainversion", + Usage: "Blockchain version (integer)", + Value: core.BlockChainVersion, } - EthVersionFlag = cli.IntFlag{ - Name: "eth", - Value: 62, - Usage: "Highest eth protocol to advertise (temporary, dev option)", + FastSyncFlag = cli.BoolFlag{ + Name: "fast", + Usage: "Enables fast syncing through state downloads", } - - // miner settings - MinerThreadsFlag = cli.IntFlag{ - Name: "minerthreads", - Usage: "Number of miner threads", - Value: runtime.NumCPU(), + LightKDFFlag = cli.BoolFlag{ + Name: "lightkdf", + Usage: "Reduce KDF memory & CPU usage at some expense of KDF strength", } + // Miner settings + // TODO: refactor CPU vs GPU mining flags MiningEnabledFlag = cli.BoolFlag{ Name: "mine", Usage: "Enable mining", } + MinerThreadsFlag = cli.IntFlag{ + Name: "minerthreads", + Usage: "Number of CPU threads to use for mining", + Value: runtime.NumCPU(), + } + MiningGPUFlag = cli.StringFlag{ + Name: "minergpus", + Usage: "List of GPUs to use for mining (e.g. '0,1' will use the first two GPUs found)", + } AutoDAGFlag = cli.BoolFlag{ Name: "autodag", Usage: "Enable automatic DAG pregeneration", } EtherbaseFlag = cli.StringFlag{ Name: "etherbase", - Usage: "Public address for block mining rewards. By default the address first created is used", + Usage: "Public address for block mining rewards (default = first account created)", Value: "0", } GasPriceFlag = cli.StringFlag{ Name: "gasprice", - Usage: "Sets the minimal gasprice when mining transactions", + Usage: "Minimal gas price to accept for mining a transactions", Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(), } - + ExtraDataFlag = cli.StringFlag{ + Name: "extradata", + Usage: "Block extra data set by the miner (default = client version)", + } + // Account settings UnlockedAccountFlag = cli.StringFlag{ Name: "unlock", - Usage: "Unlock the account given until this program exits (prompts for password). '--unlock n' unlocks the n-th account in order or creation.", + Usage: "Unlock an account (may be creation index) until this program exits (prompts for password)", Value: "", } PasswordFileFlag = cli.StringFlag{ Name: "password", - Usage: "Path to password file to use with options and subcommands needing a password", + Usage: "Password file to use with options/subcommands needing a pass phrase", Value: "", } @@ -204,32 +221,24 @@ var ( } // logging and debug settings - LogFileFlag = cli.StringFlag{ - Name: "logfile", - Usage: "Send log output to a file", - } VerbosityFlag = cli.IntFlag{ Name: "verbosity", Usage: "Logging verbosity: 0-6 (0=silent, 1=error, 2=warn, 3=info, 4=core, 5=debug, 6=debug detail)", Value: int(logger.InfoLevel), } - LogJSONFlag = cli.StringFlag{ - Name: "logjson", - Usage: "Send json structured log output to a file or '-' for standard output (default: no json output)", + LogFileFlag = cli.StringFlag{ + Name: "logfile", + Usage: "Log output file within the data dir (default = no log file generated)", Value: "", } - LogToStdErrFlag = cli.BoolFlag{ - Name: "logtostderr", - Usage: "Logs are written to standard error instead of to files.", - } LogVModuleFlag = cli.GenericFlag{ Name: "vmodule", - Usage: "The syntax of the argument is a comma-separated list of pattern=N, where pattern is a literal file name (minus the \".go\" suffix) or \"glob\" pattern and N is a log verbosity level.", + Usage: "Per-module verbosity: comma-separated list of <module>=<level>, where <module> is file literal or a glog pattern", Value: glog.GetVModule(), } BacktraceAtFlag = cli.GenericFlag{ - Name: "backtrace_at", - Usage: "If set to a file and line number (e.g., \"block.go:271\") holding a logging statement, a stack trace will be logged", + Name: "backtrace", + Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")", Value: glog.GetTraceLocation(), } PProfEanbledFlag = cli.BoolFlag{ @@ -238,37 +247,37 @@ var ( } PProfPortFlag = cli.IntFlag{ Name: "pprofport", - Usage: "Port on which the profiler should listen", + Usage: "Profile server listening port", Value: 6060, } MetricsEnabledFlag = cli.BoolFlag{ Name: metrics.MetricsEnabledFlag, - Usage: "Enables metrics collection and reporting", + Usage: "Enable metrics collection and reporting", } // RPC settings RPCEnabledFlag = cli.BoolFlag{ Name: "rpc", - Usage: "Enable the JSON-RPC server", + Usage: "Enable the HTTP-RPC server", } RPCListenAddrFlag = cli.StringFlag{ Name: "rpcaddr", - Usage: "Listening address for the JSON-RPC server", + Usage: "HTTP-RPC server listening interface", Value: "127.0.0.1", } RPCPortFlag = cli.IntFlag{ Name: "rpcport", - Usage: "Port on which the JSON-RPC server should listen", + Usage: "HTTP-RPC server listening port", Value: 8545, } RPCCORSDomainFlag = cli.StringFlag{ Name: "rpccorsdomain", - Usage: "Domain on which to send Access-Control-Allow-Origin header", + Usage: "Domains from which to accept cross origin requests (browser enforced)", Value: "", } RpcApiFlag = cli.StringFlag{ Name: "rpcapi", - Usage: "Specify the API's which are offered over the HTTP RPC interface", + Usage: "API's offered over the HTTP-RPC interface", Value: comms.DefaultHttpRpcApis, } IPCDisabledFlag = cli.BoolFlag{ @@ -277,7 +286,7 @@ var ( } IPCApiFlag = cli.StringFlag{ Name: "ipcapi", - Usage: "Specify the API's which are offered over the IPC interface", + Usage: "API's offered over the IPC-RPC interface", Value: comms.DefaultIpcApis, } IPCPathFlag = DirectoryFlag{ @@ -287,7 +296,7 @@ var ( } ExecFlag = cli.StringFlag{ Name: "exec", - Usage: "Execute javascript statement (only in combination with console/attach)", + Usage: "Execute JavaScript statement (only in combination with console/attach)", } // Network Settings MaxPeersFlag = cli.IntFlag{ @@ -307,7 +316,7 @@ var ( } BootnodesFlag = cli.StringFlag{ Name: "bootnodes", - Usage: "Space-separated enode URLs for p2p discovery bootstrap", + Usage: "Space-separated enode URLs for P2P discovery bootstrap", Value: "", } NodeKeyFileFlag = cli.StringFlag{ @@ -329,19 +338,21 @@ var ( } WhisperEnabledFlag = cli.BoolFlag{ Name: "shh", - Usage: "Enable whisper", + Usage: "Enable Whisper", } // ATM the url is left to the user and deployment to JSpathFlag = cli.StringFlag{ Name: "jspath", - Usage: "JS library path to be used with console and js subcommands", + Usage: "JavaSript root path for `loadScript` and document root for `admin.httpGet`", Value: ".", } SolcPathFlag = cli.StringFlag{ Name: "solc", - Usage: "solidity compiler to be used", + Usage: "Solidity compiler command to be used", Value: "solc", } + + // Gas price oracle settings GpoMinGasPriceFlag = cli.StringFlag{ Name: "gpomin", Usage: "Minimum suggested gas price", @@ -413,19 +424,18 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { if err != nil { glog.V(logger.Error).Infoln("WARNING: No etherbase set and no accounts found as default") } - + // Assemble the entire eth configuration and return cfg := ð.Config{ Name: common.MakeName(clientID, version), - DataDir: ctx.GlobalString(DataDirFlag.Name), - GenesisNonce: ctx.GlobalInt(GenesisNonceFlag.Name), + DataDir: MustDataDir(ctx), GenesisFile: ctx.GlobalString(GenesisFileFlag.Name), + FastSync: ctx.GlobalBool(FastSyncFlag.Name), BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name), DatabaseCache: ctx.GlobalInt(CacheFlag.Name), SkipBcVersionCheck: false, NetworkId: ctx.GlobalInt(NetworkIdFlag.Name), LogFile: ctx.GlobalString(LogFileFlag.Name), Verbosity: ctx.GlobalInt(VerbosityFlag.Name), - LogJSON: ctx.GlobalString(LogJSONFlag.Name), Etherbase: common.HexToAddress(etherbase), MinerThreads: ctx.GlobalInt(MinerThreadsFlag.Name), AccountManager: am, @@ -436,6 +446,7 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { Olympic: ctx.GlobalBool(OlympicFlag.Name), NAT: MakeNAT(ctx), NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name), + DocRoot: ctx.GlobalString(DocRootFlag.Name), Discovery: !ctx.GlobalBool(NoDiscoverFlag.Name), NodeKey: MakeNodeKey(ctx), Shh: ctx.GlobalBool(WhisperEnabledFlag.Name), @@ -452,6 +463,20 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { AutoDAG: ctx.GlobalBool(AutoDAGFlag.Name) || ctx.GlobalBool(MiningEnabledFlag.Name), } + if ctx.GlobalBool(DevModeFlag.Name) && ctx.GlobalBool(TestNetFlag.Name) { + glog.Fatalf("%s and %s are mutually exclusive\n", DevModeFlag.Name, TestNetFlag.Name) + } + + if ctx.GlobalBool(TestNetFlag.Name) { + // testnet is always stored in the testnet folder + cfg.DataDir += "/testnet" + cfg.NetworkId = 2 + cfg.TestNet = true + } + + if ctx.GlobalBool(VMEnableJitFlag.Name) { + cfg.Name += "/JIT" + } if ctx.GlobalBool(DevModeFlag.Name) { if !ctx.GlobalIsSet(VMDebugFlag.Name) { cfg.VmDebug = true @@ -476,7 +501,6 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { glog.V(logger.Info).Infoln("dev mode enabled") } - return cfg } @@ -488,6 +512,20 @@ func SetupLogger(ctx *cli.Context) { glog.SetLogDir(ctx.GlobalString(LogFileFlag.Name)) } +// SetupNetwork configures the system for either the main net or some test network. +func SetupNetwork(ctx *cli.Context) { + switch { + case ctx.GlobalBool(OlympicFlag.Name): + params.DurationLimit = big.NewInt(8) + params.GenesisGasLimit = big.NewInt(3141592) + params.MinGasLimit = big.NewInt(125000) + params.MaximumExtraDataSize = big.NewInt(1024) + NetworkIdFlag.Value = 0 + core.BlockReward = big.NewInt(1.5e+18) + core.ExpDiffPeriod = big.NewInt(math.MaxInt64) + } +} + // SetupVM configured the VM package's global settings func SetupVM(ctx *cli.Context) { vm.EnableJit = ctx.GlobalBool(VMEnableJitFlag.Name) @@ -495,21 +533,9 @@ func SetupVM(ctx *cli.Context) { vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name)) } -// SetupEth configures the eth packages global settings -func SetupEth(ctx *cli.Context) { - version := ctx.GlobalInt(EthVersionFlag.Name) - for len(eth.ProtocolVersions) > 0 && eth.ProtocolVersions[0] > uint(version) { - eth.ProtocolVersions = eth.ProtocolVersions[1:] - eth.ProtocolLengths = eth.ProtocolLengths[1:] - } - if len(eth.ProtocolVersions) == 0 { - Fatalf("No valid eth protocols remaining") - } -} - // MakeChain creates a chain manager from set command line flags. -func MakeChain(ctx *cli.Context) (chain *core.ChainManager, chainDb ethdb.Database) { - datadir := ctx.GlobalString(DataDirFlag.Name) +func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) { + datadir := MustDataDir(ctx) cache := ctx.GlobalInt(CacheFlag.Name) var err error @@ -517,7 +543,6 @@ func MakeChain(ctx *cli.Context) (chain *core.ChainManager, chainDb ethdb.Databa Fatalf("Could not open database: %v", err) } if ctx.GlobalBool(OlympicFlag.Name) { - InitOlympic() _, err := core.WriteTestNetGenesisBlock(chainDb, 42) if err != nil { glog.Fatalln(err) @@ -527,7 +552,7 @@ func MakeChain(ctx *cli.Context) (chain *core.ChainManager, chainDb ethdb.Databa eventMux := new(event.TypeMux) pow := ethash.New() //genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB) - chain, err = core.NewChainManager(chainDb, pow, eventMux) + chain, err = core.NewBlockChain(chainDb, pow, eventMux) if err != nil { Fatalf("Could not start chainmanager: %v", err) } @@ -539,11 +564,30 @@ func MakeChain(ctx *cli.Context) (chain *core.ChainManager, chainDb ethdb.Databa // MakeChain creates an account manager from set command line flags. func MakeAccountManager(ctx *cli.Context) *accounts.Manager { - dataDir := ctx.GlobalString(DataDirFlag.Name) - ks := crypto.NewKeyStorePassphrase(filepath.Join(dataDir, "keystore")) + dataDir := MustDataDir(ctx) + if ctx.GlobalBool(TestNetFlag.Name) { + dataDir += "/testnet" + } + scryptN := crypto.StandardScryptN + scryptP := crypto.StandardScryptP + if ctx.GlobalBool(LightKDFFlag.Name) { + scryptN = crypto.LightScryptN + scryptP = crypto.LightScryptP + } + ks := crypto.NewKeyStorePassphrase(filepath.Join(dataDir, "keystore"), scryptN, scryptP) return accounts.NewManager(ks) } +// MustDataDir retrieves the currently requested data directory, terminating if +// none (or the empty string) is specified. +func MustDataDir(ctx *cli.Context) string { + if path := ctx.GlobalString(DataDirFlag.Name); path != "" { + return path + } + Fatalf("Cannot determine default data directory, please set manually (--datadir)") + return "" +} + func IpcSocketPath(ctx *cli.Context) (ipcpath string) { if runtime.GOOS == "windows" { ipcpath = common.DefaultIpcPath() @@ -568,17 +612,14 @@ func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error { Endpoint: IpcSocketPath(ctx), } - initializer := func(conn net.Conn) (shared.EthereumApi, error) { + initializer := func(conn net.Conn) (comms.Stopper, shared.EthereumApi, error) { fe := useragent.NewRemoteFrontend(conn, eth.AccountManager()) xeth := xeth.New(eth, fe) - codec := codec.JSON - - apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth) + apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec.JSON, xeth, eth) if err != nil { - return nil, err + return nil, nil, err } - - return api.Merge(apis...), nil + return xeth, api.Merge(apis...), nil } return comms.StartIpc(config, codec.JSON, initializer) |