aboutsummaryrefslogtreecommitdiffstats
path: root/cmd/geth
diff options
context:
space:
mode:
authorJeffrey Wilcke <geffobscura@gmail.com>2015-11-03 18:47:07 +0800
committerJeffrey Wilcke <geffobscura@gmail.com>2015-11-03 18:47:07 +0800
commite5532154a50114d5ffb1ffd850b746cab00cb899 (patch)
tree0042cc997ccf4166b9b52464339d52d37d7a8ad6 /cmd/geth
parent9666db2a442887ccf8ec2d81f5e2fedc1a3a3d3e (diff)
parentf75becc264f8bde0f58391fc226243d03e78aa7b (diff)
downloadgo-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/geth')
-rw-r--r--cmd/geth/blocktestcmd.go12
-rw-r--r--cmd/geth/chaincmd.go6
-rw-r--r--cmd/geth/js.go83
-rw-r--r--cmd/geth/js_test.go15
-rw-r--r--cmd/geth/main.go149
-rw-r--r--cmd/geth/usage.go212
6 files changed, 369 insertions, 108 deletions
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)
+ }
+ }
+}