Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

Commit

Permalink
console:
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
zelig committed Oct 21, 2015
1 parent 58d0752 commit 8b81ad1
Show file tree
Hide file tree
Showing 18 changed files with 347 additions and 151 deletions.
55 changes: 32 additions & 23 deletions cmd/geth/js.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 = ""
Expand All @@ -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)) {
Expand Down
66 changes: 35 additions & 31 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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.
`,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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()
}
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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 {
Expand All @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion cmd/utils/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 7 additions & 3 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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{
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}
Expand Down
6 changes: 6 additions & 0 deletions common/docserver/docserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,20 @@ func (self *DocServer) Get(uri, path string) (content []byte, err error) {
resp.Body.Close()
}
}()

if err != nil {
return
}

content, err = ioutil.ReadAll(resp.Body)
if err != nil {
return
}

if resp.StatusCode/100 != 2 {
return content, fmt.Errorf("HTTP error: %s", resp.Status)
}

if path != "" {
var abspath string
abspath, err = filepath.Abs(path)
Expand Down
Loading

0 comments on commit 8b81ad1

Please sign in to comment.