Skip to content

Commit dce5037

Browse files
committed
Merge pull request #1840 from ethersphere/console
console, cli, api fixes
2 parents 58d0752 + 8b81ad1 commit dce5037

File tree

18 files changed

+347
-151
lines changed

18 files changed

+347
-151
lines changed

cmd/geth/js.go

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,12 @@ import (
4545
"github.com/robertkrimen/otto"
4646
)
4747

48-
var passwordRegexp = regexp.MustCompile("personal.[nu]")
49-
50-
const passwordRepl = ""
48+
var (
49+
passwordRegexp = regexp.MustCompile("personal.[nu]")
50+
leadingSpace = regexp.MustCompile("^ ")
51+
onlyws = regexp.MustCompile("^\\s*$")
52+
exit = regexp.MustCompile("^\\s*exit\\s*;*\\s*$")
53+
)
5154

5255
type prompter interface {
5356
AppendHistory(string)
@@ -74,6 +77,7 @@ func (r dumbterm) PasswordPrompt(p string) (string, error) {
7477
func (r dumbterm) AppendHistory(string) {}
7578

7679
type jsre struct {
80+
docRoot string
7781
ds *docserver.DocServer
7882
re *re.JSRE
7983
ethereum *eth.Ethereum
@@ -145,14 +149,14 @@ func apiWordCompleter(line string, pos int) (head string, completions []string,
145149
return begin, completionWords, end
146150
}
147151

148-
func newLightweightJSRE(libPath string, client comms.EthereumClient, datadir string, interactive bool) *jsre {
152+
func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir string, interactive bool) *jsre {
149153
js := &jsre{ps1: "> "}
150154
js.wait = make(chan *big.Int)
151155
js.client = client
152-
js.ds = docserver.New("/")
156+
js.ds = docserver.New(docRoot)
153157

154158
// update state in separare forever blocks
155-
js.re = re.New(libPath)
159+
js.re = re.New(docRoot)
156160
if err := js.apiBindings(js); err != nil {
157161
utils.Fatalf("Unable to initialize console - %v", err)
158162
}
@@ -176,25 +180,25 @@ func newLightweightJSRE(libPath string, client comms.EthereumClient, datadir str
176180
return js
177181
}
178182

179-
func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
180-
js := &jsre{ethereum: ethereum, ps1: "> "}
183+
func newJSRE(ethereum *eth.Ethereum, docRoot, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
184+
js := &jsre{ethereum: ethereum, ps1: "> ", docRoot: docRoot}
181185
// set default cors domain used by startRpc from CLI flag
182186
js.corsDomain = corsDomain
183187
if f == nil {
184188
f = js
185189
}
186-
js.ds = docserver.New("/")
190+
js.ds = docserver.New(docRoot)
187191
js.xeth = xeth.New(ethereum, f)
188192
js.wait = js.xeth.UpdateState()
189193
js.client = client
190194
if clt, ok := js.client.(*comms.InProcClient); ok {
191-
if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, ethereum); err == nil {
195+
if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, ethereum, docRoot); err == nil {
192196
clt.Initialize(api.Merge(offeredApis...))
193197
}
194198
}
195199

196200
// update state in separare forever blocks
197-
js.re = re.New(libPath)
201+
js.re = re.New(docRoot)
198202
if err := js.apiBindings(f); err != nil {
199203
utils.Fatalf("Unable to connect - %v", err)
200204
}
@@ -277,7 +281,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
277281
apiNames = append(apiNames, a)
278282
}
279283

280-
apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.ethereum)
284+
apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.ethereum, js.docRoot)
281285
if err != nil {
282286
utils.Fatalf("Unable to determine supported api's: %v", err)
283287
}
@@ -334,6 +338,14 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
334338
return nil
335339
}
336340

341+
func (self *jsre) AskPassword() (string, bool) {
342+
pass, err := self.PasswordPrompt("Passphrase: ")
343+
if err != nil {
344+
return "", false
345+
}
346+
return pass, true
347+
}
348+
337349
func (self *jsre) ConfirmTransaction(tx string) bool {
338350
if self.ethereum.NatSpec {
339351
notice := natspec.GetNotice(self.xeth, tx, self.ds)
@@ -405,18 +417,17 @@ func (self *jsre) interactive() {
405417
fmt.Println("caught interrupt, exiting")
406418
return
407419
case input, ok := <-inputln:
408-
if !ok || indentCount <= 0 && input == "exit" {
420+
if !ok || indentCount <= 0 && exit.MatchString(input) {
409421
return
410422
}
411-
if input == "" {
423+
if onlyws.MatchString(input) {
412424
continue
413425
}
414426
str += input + "\n"
415427
self.setIndent()
416428
if indentCount <= 0 {
417-
hist := hidepassword(str[:len(str)-1])
418-
if len(hist) > 0 {
419-
self.AppendHistory(hist)
429+
if mustLogInHistory(str) {
430+
self.AppendHistory(str[:len(str)-1])
420431
}
421432
self.parseInput(str)
422433
str = ""
@@ -425,12 +436,10 @@ func (self *jsre) interactive() {
425436
}
426437
}
427438

428-
func hidepassword(input string) string {
429-
if passwordRegexp.MatchString(input) {
430-
return passwordRepl
431-
} else {
432-
return input
433-
}
439+
func mustLogInHistory(input string) bool {
440+
return len(input) == 0 ||
441+
passwordRegexp.MatchString(input) ||
442+
leadingSpace.MatchString(input)
434443
}
435444

436445
func (self *jsre) withHistory(datadir string, op func(*os.File)) {

cmd/geth/main.go

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,6 @@ var (
5858
gitCommit string // set via linker flagg
5959
nodeNameVersion string
6060
app *cli.App
61-
62-
ExtraDataFlag = cli.StringFlag{
63-
Name: "extradata",
64-
Usage: "Extra data for the miner",
65-
}
6661
)
6762

6863
func init() {
@@ -176,8 +171,12 @@ It is safe to transfer the entire directory or the individual keys therein
176171
between ethereum nodes by simply copying.
177172
Make sure you backup your keys regularly.
178173
179-
In order to use your account to send transactions, you need to unlock them using the
180-
'--unlock' option. The argument is a comma
174+
In order to use your account to send transactions, you need to unlock them using
175+
the '--unlock' option. The argument is a space separated list of addresses or
176+
indexes. If used non-interactively with a passwordfile, the file should contain
177+
the respective passwords one per line. If you unlock n accounts and the password
178+
file contains less than n entries, then the last password is meant to apply to
179+
all remaining accounts.
181180
182181
And finally. DO NOT FORGET YOUR PASSWORD.
183182
`,
@@ -227,7 +226,7 @@ format to the newest format or change the password for an account.
227226
228227
For non-interactive use the passphrase can be specified with the --password flag:
229228
230-
ethereum --password <passwordfile> account new
229+
ethereum --password <passwordfile> account update <address>
231230
232231
Since only one password can be given, only format update can be performed,
233232
changing your password is only possible interactively.
@@ -354,7 +353,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
354353
utils.GpobaseStepDownFlag,
355354
utils.GpobaseStepUpFlag,
356355
utils.GpobaseCorrectionFactorFlag,
357-
ExtraDataFlag,
356+
utils.ExtraDataFlag,
358357
}
359358
app.Before = func(ctx *cli.Context) error {
360359
utils.SetupLogger(ctx)
@@ -380,8 +379,8 @@ func main() {
380379

381380
// makeExtra resolves extradata for the miner from a flag or returns a default.
382381
func makeExtra(ctx *cli.Context) []byte {
383-
if ctx.GlobalIsSet(ExtraDataFlag.Name) {
384-
return []byte(ctx.GlobalString(ExtraDataFlag.Name))
382+
if ctx.GlobalIsSet(utils.ExtraDataFlag.Name) {
383+
return []byte(ctx.GlobalString(utils.ExtraDataFlag.Name))
385384
}
386385
return makeDefaultExtra()
387386
}
@@ -517,28 +516,29 @@ func execJSFiles(ctx *cli.Context) {
517516
ethereum.WaitForShutdown()
518517
}
519518

520-
func unlockAccount(ctx *cli.Context, am *accounts.Manager, addr string, i int) (addrHex, auth string) {
521-
utils.CheckLegalese(utils.MustDataDir(ctx))
519+
func unlockAccount(ctx *cli.Context, am *accounts.Manager, addr string, i int, inputpassphrases []string) (addrHex, auth string, passphrases []string) {
520+
utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
522521

523522
var err error
523+
passphrases = inputpassphrases
524524
addrHex, err = utils.ParamToAddress(addr, am)
525525
if err == nil {
526526
// Attempt to unlock the account 3 times
527527
attempts := 3
528528
for tries := 0; tries < attempts; tries++ {
529529
msg := fmt.Sprintf("Unlocking account %s | Attempt %d/%d", addr, tries+1, attempts)
530-
auth = getPassPhrase(ctx, msg, false, i)
530+
auth, passphrases = getPassPhrase(ctx, msg, false, i, passphrases)
531531
err = am.Unlock(common.HexToAddress(addrHex), auth)
532-
if err == nil {
532+
if err == nil || passphrases != nil {
533533
break
534534
}
535535
}
536536
}
537537

538538
if err != nil {
539-
utils.Fatalf("Unlock account failed '%v'", err)
539+
utils.Fatalf("Unlock account '%s' (%v) failed: %v", addr, addrHex, err)
540540
}
541-
fmt.Printf("Account '%s' unlocked.\n", addr)
541+
fmt.Printf("Account '%s' (%v) unlocked.\n", addr, addrHex)
542542
return
543543
}
544544

@@ -582,12 +582,13 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) {
582582
am := eth.AccountManager()
583583
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
584584
accounts := strings.Split(account, " ")
585+
var passphrases []string
585586
for i, account := range accounts {
586587
if len(account) > 0 {
587588
if account == "primary" {
588589
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.")
589590
}
590-
unlockAccount(ctx, am, account, i)
591+
_, _, passphrases = unlockAccount(ctx, am, account, i, passphrases)
591592
}
592593
}
593594
// Start auxiliary services if enabled.
@@ -624,7 +625,7 @@ func accountList(ctx *cli.Context) {
624625
}
625626
}
626627

627-
func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int) (passphrase string) {
628+
func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int, inputpassphrases []string) (passphrase string, passphrases []string) {
628629
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
629630
if len(passfile) == 0 {
630631
fmt.Println(desc)
@@ -644,14 +645,17 @@ func getPassPhrase(ctx *cli.Context, desc string, confirmation bool, i int) (pas
644645
passphrase = auth
645646

646647
} else {
647-
passbytes, err := ioutil.ReadFile(passfile)
648-
if err != nil {
649-
utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
648+
passphrases = inputpassphrases
649+
if passphrases == nil {
650+
passbytes, err := ioutil.ReadFile(passfile)
651+
if err != nil {
652+
utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
653+
}
654+
// this is backwards compatible if the same password unlocks several accounts
655+
// it also has the consequence that trailing newlines will not count as part
656+
// of the password, so --password <(echo -n 'pass') will now work without -n
657+
passphrases = strings.Split(string(passbytes), "\n")
650658
}
651-
// this is backwards compatible if the same password unlocks several accounts
652-
// it also has the consequence that trailing newlines will not count as part
653-
// of the password, so --password <(echo -n 'pass') will now work without -n
654-
passphrases := strings.Split(string(passbytes), "\n")
655659
if i >= len(passphrases) {
656660
passphrase = passphrases[len(passphrases)-1]
657661
} else {
@@ -665,7 +669,7 @@ func accountCreate(ctx *cli.Context) {
665669
utils.CheckLegalese(utils.MustDataDir(ctx))
666670

667671
am := utils.MakeAccountManager(ctx)
668-
passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0)
672+
passphrase, _ := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, nil)
669673
acct, err := am.NewAccount(passphrase)
670674
if err != nil {
671675
utils.Fatalf("Could not create the account: %v", err)
@@ -682,8 +686,8 @@ func accountUpdate(ctx *cli.Context) {
682686
utils.Fatalf("account address or index must be given as argument")
683687
}
684688

685-
addr, authFrom := unlockAccount(ctx, am, arg, 0)
686-
authTo := getPassPhrase(ctx, "Please give a new password. Do not forget this password.", true, 0)
689+
addr, authFrom, passphrases := unlockAccount(ctx, am, arg, 0, nil)
690+
authTo, _ := getPassPhrase(ctx, "Please give a new password. Do not forget this password.", true, 0, passphrases)
687691
err := am.Update(common.HexToAddress(addr), authFrom, authTo)
688692
if err != nil {
689693
utils.Fatalf("Could not update the account: %v", err)
@@ -703,7 +707,7 @@ func importWallet(ctx *cli.Context) {
703707
}
704708

705709
am := utils.MakeAccountManager(ctx)
706-
passphrase := getPassPhrase(ctx, "", false, 0)
710+
passphrase, _ := getPassPhrase(ctx, "", false, 0, nil)
707711

708712
acct, err := am.ImportPreSaleKey(keyJson, passphrase)
709713
if err != nil {
@@ -720,7 +724,7 @@ func accountImport(ctx *cli.Context) {
720724
utils.Fatalf("keyfile must be given as argument")
721725
}
722726
am := utils.MakeAccountManager(ctx)
723-
passphrase := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0)
727+
passphrase, _ := getPassPhrase(ctx, "Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, nil)
724728
acct, err := am.Import(keyfile, passphrase)
725729
if err != nil {
726730
utils.Fatalf("Could not create the account: %v", err)

cmd/utils/cmd.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ const (
4040
importBatchSize = 2500
4141
)
4242

43-
var interruptCallbacks = []func(os.Signal){}
43+
var (
44+
interruptCallbacks = []func(os.Signal){}
45+
)
4446

4547
func openLogFile(Datadir string, filename string) *os.File {
4648
path := common.AbsolutePath(Datadir, filename)

cmd/utils/flags.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ var (
183183
Usage: "Sets the minimal gasprice when mining transactions",
184184
Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
185185
}
186+
ExtraDataFlag = cli.StringFlag{
187+
Name: "extradata",
188+
Usage: "Extra data for the miner",
189+
}
186190

187191
UnlockedAccountFlag = cli.StringFlag{
188192
Name: "unlock",
@@ -345,7 +349,7 @@ var (
345349
// ATM the url is left to the user and deployment to
346350
JSpathFlag = cli.StringFlag{
347351
Name: "jspath",
348-
Usage: "JS library path to be used with console and js subcommands",
352+
Usage: "JS root path for loadScript and document root for admin.httpGet",
349353
Value: ".",
350354
}
351355
SolcPathFlag = cli.StringFlag{
@@ -612,7 +616,7 @@ func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error {
612616
xeth := xeth.New(eth, fe)
613617
codec := codec.JSON
614618

615-
apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth)
619+
apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth, ctx.GlobalString(JSpathFlag.Name))
616620
if err != nil {
617621
return nil, err
618622
}
@@ -633,7 +637,7 @@ func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error {
633637
xeth := xeth.New(eth, nil)
634638
codec := codec.JSON
635639

636-
apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, eth)
640+
apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, eth, ctx.GlobalString(JSpathFlag.Name))
637641
if err != nil {
638642
return err
639643
}

common/docserver/docserver.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,20 @@ func (self *DocServer) Get(uri, path string) (content []byte, err error) {
9595
resp.Body.Close()
9696
}
9797
}()
98+
9899
if err != nil {
99100
return
100101
}
102+
101103
content, err = ioutil.ReadAll(resp.Body)
102104
if err != nil {
103105
return
104106
}
105107

108+
if resp.StatusCode/100 != 2 {
109+
return content, fmt.Errorf("HTTP error: %s", resp.Status)
110+
}
111+
106112
if path != "" {
107113
var abspath string
108114
abspath, err = filepath.Abs(path)

0 commit comments

Comments
 (0)