aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorzelig <viktor.tron@gmail.com>2015-09-22 16:34:58 +0800
committerzelig <viktor.tron@gmail.com>2015-10-22 06:22:39 +0800
commit8b81ad1fc40080af441c0c6df94f0b2ea46e320b (patch)
tree7d8817ec84be38b911f967f1ecd5618d02e4caa9 /cmd
parent58d0752fdd1c7363fb1a127cd7e0a86d7602be02 (diff)
downloadgo-tangerine-8b81ad1fc40080af441c0c6df94f0b2ea46e320b.tar.gz
go-tangerine-8b81ad1fc40080af441c0c6df94f0b2ea46e320b.tar.zst
go-tangerine-8b81ad1fc40080af441c0c6df94f0b2ea46e320b.zip
console:
* lines with leading space are ommitted from history * exit processed even with whitespace around * all whitespace lines (not only empty ones) are ignored add 7 missing commands to admin api autocomplete registrar: methods now return proper error if reg addresses are not set. fixes #1457 rpc/console: fix personal.newAccount() regression. Now all comms accept interactive password registrar: add registrar tests for errors crypto: catch AES decryption error on presale wallet import + fix error msg format. fixes #1580 CLI: improve error message when starting a second instance of geth. fixes #1564 cli/accounts: unlock multiple accounts. fixes #1785 * make unlocking multiple accounts work with inline <() fd * passwdfile now correctly read only once * improve logs * fix CLI help text for unlocking fix regression with docRoot / admin API * docRoot/jspath passed to rpc/api ParseApis, which passes onto adminApi * docRoot field for JS console in order to pass when RPC is (re)started * improve flag desc for jspath common/docserver: catch http errors from response fix rpc/api tests common/natspec: fix end to end test (skipped because takes 8s) registrar: fix major regression: * deploy registrars on frontier * register HashsReg and UrlHint in GlobalRegistrar. * set all 3 contract addresses in code * zero out addresses first in tests
Diffstat (limited to 'cmd')
-rw-r--r--cmd/geth/js.go55
-rw-r--r--cmd/geth/main.go66
-rw-r--r--cmd/utils/cmd.go4
-rw-r--r--cmd/utils/flags.go10
4 files changed, 77 insertions, 58 deletions
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index b5ec82b57..8ebb04bce 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -45,9 +45,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,6 +77,7 @@ func (r dumbterm) PasswordPrompt(p string) (string, error) {
func (r dumbterm) AppendHistory(string) {}
type jsre struct {
+ docRoot string
ds *docserver.DocServer
re *re.JSRE
ethereum *eth.Ethereum
@@ -145,14 +149,14 @@ func apiWordCompleter(line string, pos int) (head string, completions []string,
return begin, completionWords, end
}
-func newLightweightJSRE(libPath string, client comms.EthereumClient, datadir string, 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("/")
+ js.ds = docserver.New(docRoot)
// 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)
}
@@ -176,25 +180,25 @@ func newLightweightJSRE(libPath string, client comms.EthereumClient, datadir str
return js
}
-func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
- js := &jsre{ethereum: ethereum, ps1: "> "}
+func newJSRE(ethereum *eth.Ethereum, docRoot, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
+ js := &jsre{ethereum: ethereum, ps1: "> ", docRoot: docRoot}
// set default cors domain used by startRpc from CLI flag
js.corsDomain = corsDomain
if f == nil {
f = js
}
- js.ds = docserver.New("/")
+ js.ds = docserver.New(docRoot)
js.xeth = xeth.New(ethereum, f)
js.wait = js.xeth.UpdateState()
js.client = client
if clt, ok := js.client.(*comms.InProcClient); ok {
- if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, ethereum); err == nil {
+ if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, ethereum, docRoot); err == nil {
clt.Initialize(api.Merge(offeredApis...))
}
}
// 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)
}
@@ -277,7 +281,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
apiNames = append(apiNames, a)
}
- apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.ethereum)
+ apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.ethereum, js.docRoot)
if err != nil {
utils.Fatalf("Unable to determine supported api's: %v", err)
}
@@ -334,6 +338,14 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
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)
@@ -405,18 +417,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,12 +436,10 @@ 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(datadir string, op func(*os.File)) {
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 3e3a3eb03..8bdc01999 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -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() {
@@ -176,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.
`,
@@ -227,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.
@@ -354,7 +353,7 @@ 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)
@@ -380,8 +379,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()
}
@@ -517,28 +516,29 @@ func execJSFiles(ctx *cli.Context) {
ethereum.WaitForShutdown()
}
-func unlockAccount(ctx *cli.Context, am *accounts.Manager, addr string, i int) (addrHex, auth string) {
- utils.CheckLegalese(utils.MustDataDir(ctx))
+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
}
@@ -582,12 +582,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.
@@ -624,7 +625,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)
@@ -644,14 +645,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 {
@@ -665,7 +669,7 @@ func accountCreate(ctx *cli.Context) {
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)
@@ -682,8 +686,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)
@@ -703,7 +707,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 {
@@ -720,7 +724,7 @@ func accountImport(ctx *cli.Context) {
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)
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 1fbd96dc8..9b75ccab4 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -40,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)
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index eb2a7d421..66ec46f80 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -183,6 +183,10 @@ var (
Usage: "Sets the minimal gasprice when mining transactions",
Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
}
+ ExtraDataFlag = cli.StringFlag{
+ Name: "extradata",
+ Usage: "Extra data for the miner",
+ }
UnlockedAccountFlag = cli.StringFlag{
Name: "unlock",
@@ -345,7 +349,7 @@ var (
// 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: "JS root path for loadScript and document root for admin.httpGet",
Value: ".",
}
SolcPathFlag = cli.StringFlag{
@@ -612,7 +616,7 @@ func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error {
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, xeth, eth, ctx.GlobalString(JSpathFlag.Name))
if err != nil {
return nil, err
}
@@ -633,7 +637,7 @@ func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error {
xeth := xeth.New(eth, nil)
codec := codec.JSON
- apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, eth)
+ apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, eth, ctx.GlobalString(JSpathFlag.Name))
if err != nil {
return err
}