From 2a0d888326036be9cabe6680617ce2d1a27761d3 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 8 Jun 2015 11:01:02 +0200 Subject: added API/IPC commandline flags --- cmd/geth/main.go | 8 ++++++++ cmd/utils/flags.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'cmd') diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 4d7d57220..d180c269f 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -239,6 +239,9 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.RPCEnabledFlag, utils.RPCListenAddrFlag, utils.RPCPortFlag, + utils.IPCDisabledFlag, + utils.IPCApiFlag, + utils.IPCPathFlag, utils.WhisperEnabledFlag, utils.VMDebugFlag, utils.ProtocolVersionFlag, @@ -382,6 +385,11 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) { } } // Start auxiliary services if enabled. + if !ctx.GlobalBool(utils.IPCDisabledFlag.Name) { + if err := utils.StartIPC(eth, ctx); err != nil { + utils.Fatalf("Error string IPC: %v", err) + } + } if ctx.GlobalBool(utils.RPCEnabledFlag.Name) { if err := utils.StartRPC(eth, ctx); err != nil { utils.Fatalf("Error starting RPC: %v", err) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index ab7eaf023..4c3690d49 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -24,6 +24,9 @@ import ( "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/xeth" + "github.com/ethereum/go-ethereum/rpc/api" + "github.com/ethereum/go-ethereum/rpc/comms" + "github.com/ethereum/go-ethereum/rpc/codec" ) func init() { @@ -206,6 +209,20 @@ var ( Usage: "Domain on which to send Access-Control-Allow-Origin header", Value: "", } + IPCDisabledFlag = cli.BoolFlag{ + Name: "ipcdisable", + Usage: "Disable the IPC-RPC server", + } + IPCApiFlag = cli.StringFlag{ + Name: "ipcapi", + Usage: "Specify the API's which are offered over this interface", + Value: api.DefaultIpcApis, + } + IPCPathFlag = DirectoryFlag{ + Name: "ipcpath", + Usage: "Filename for IPC socket/pipe", + Value: DirectoryString{common.DefaultIpcPath()}, + } // Network Settings MaxPeersFlag = cli.IntFlag{ Name: "maxpeers", @@ -368,6 +385,22 @@ func MakeAccountManager(ctx *cli.Context) *accounts.Manager { return accounts.NewManager(ks) } +func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error { + config := comms.IpcConfig{ + Endpoint: ctx.GlobalString(IPCPathFlag.Name), + } + + xeth := xeth.New(eth, nil) + codec := codec.JSON + + apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec, xeth, eth) + if err != nil { + return err + } + + return comms.StartIpc(config, codec, apis...) +} + func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error { config := rpc.RpcConfig{ ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name), -- cgit v1.2.3 From a1a475fb9296e214292840d89811123292c7953c Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 8 Jun 2015 12:43:58 +0200 Subject: added console command --- cmd/geth/js.go | 10 +++++----- cmd/geth/main.go | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'cmd') diff --git a/cmd/geth/js.go b/cmd/geth/js.go index 706bc6554..d1a6cc29d 100644 --- a/cmd/geth/js.go +++ b/cmd/geth/js.go @@ -73,7 +73,7 @@ type jsre struct { prompter } -func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, interactive bool, f xeth.Frontend) *jsre { +func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain, ipcpath string, interactive bool, f xeth.Frontend) *jsre { js := &jsre{ethereum: ethereum, ps1: "> "} // set default cors domain used by startRpc from CLI flag js.corsDomain = corsDomain @@ -84,7 +84,7 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, interactive boo js.wait = js.xeth.UpdateState() // update state in separare forever blocks js.re = re.New(libPath) - js.apiBindings(f) + js.apiBindings(ipcpath, f) js.adminBindings() if !liner.TerminalSupported() || !interactive { @@ -103,10 +103,10 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, interactive boo return js } -func (js *jsre) apiBindings(f xeth.Frontend) { +func (js *jsre) apiBindings(ipcpath string, f xeth.Frontend) { xe := xeth.New(js.ethereum, f) ethApi := rpc.NewEthereumApi(xe) - jeth := rpc.NewJeth(ethApi, js.re) + jeth := rpc.NewJeth(ethApi, js.re, ipcpath) js.re.Set("jeth", struct{}{}) t, _ := js.re.Get("jeth") @@ -119,7 +119,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) { utils.Fatalf("Error loading bignumber.js: %v", err) } - err = js.re.Compile("ethereum.js", re.Ethereum_JS) + err = js.re.Compile("ethereum.js", re.Web3_JS) if err != nil { utils.Fatalf("Error loading ethereum.js: %v", err) } diff --git a/cmd/geth/main.go b/cmd/geth/main.go index d180c269f..5d7e102c4 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -307,6 +307,7 @@ func console(ctx *cli.Context) { repl := newJSRE( ethereum, ctx.String(utils.JSpathFlag.Name), + ctx.GlobalString(utils.IPCPathFlag.Name), ctx.GlobalString(utils.RPCCORSDomainFlag.Name), true, nil, @@ -328,6 +329,7 @@ func execJSFiles(ctx *cli.Context) { repl := newJSRE( ethereum, ctx.String(utils.JSpathFlag.Name), + ctx.GlobalString(utils.IPCPathFlag.Name), ctx.GlobalString(utils.RPCCORSDomainFlag.Name), false, nil, -- cgit v1.2.3 From 862117e4bdcc5d255fc85fc35e223eec10f0ac7b Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 8 Jun 2015 13:21:24 +0200 Subject: changed send methods for backwards compatability in geth console --- cmd/geth/js.go | 1 + cmd/geth/main.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'cmd') diff --git a/cmd/geth/js.go b/cmd/geth/js.go index d1a6cc29d..7e6e10ca9 100644 --- a/cmd/geth/js.go +++ b/cmd/geth/js.go @@ -111,6 +111,7 @@ func (js *jsre) apiBindings(ipcpath string, f xeth.Frontend) { js.re.Set("jeth", struct{}{}) t, _ := js.re.Get("jeth") jethObj := t.Object() + jethObj.Set("send", jeth.Send) jethObj.Set("sendAsync", jeth.Send) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 5d7e102c4..8e55b310c 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -307,8 +307,8 @@ func console(ctx *cli.Context) { repl := newJSRE( ethereum, ctx.String(utils.JSpathFlag.Name), - ctx.GlobalString(utils.IPCPathFlag.Name), ctx.GlobalString(utils.RPCCORSDomainFlag.Name), + ctx.GlobalString(utils.IPCPathFlag.Name), true, nil, ) @@ -329,8 +329,8 @@ func execJSFiles(ctx *cli.Context) { repl := newJSRE( ethereum, ctx.String(utils.JSpathFlag.Name), - ctx.GlobalString(utils.IPCPathFlag.Name), ctx.GlobalString(utils.RPCCORSDomainFlag.Name), + ctx.GlobalString(utils.IPCPathFlag.Name), false, nil, ) -- cgit v1.2.3 From 0a600a03eeb5a7928233e541f26c0c81c70929fe Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 8 Jun 2015 13:46:53 +0200 Subject: fixed unittest build problem --- cmd/geth/js_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go index e7285a38d..20bde01f3 100644 --- a/cmd/geth/js_test.go +++ b/cmd/geth/js_test.go @@ -105,7 +105,7 @@ func testJEthRE(t *testing.T) (string, *testjethre, *eth.Ethereum) { t.Errorf("Error creating DocServer: %v", err) } tf := &testjethre{ds: ds, stateDb: ethereum.ChainManager().State().Copy()} - repl := newJSRE(ethereum, assetPath, "", false, tf) + repl := newJSRE(ethereum, assetPath, "", "", false, tf) tf.jsre = repl return tmp, tf, ethereum } -- cgit v1.2.3 From cb7f2d43b6da260dff80e4b705271c7088112c34 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 8 Jun 2015 19:14:42 +0200 Subject: added console binary --- cmd/console/admin.go | 9 ++ cmd/console/console | Bin 0 -> 19332472 bytes cmd/console/contracts.go | 6 + cmd/console/history | 7 ++ cmd/console/js.go | 279 +++++++++++++++++++++++++++++++++++++++++++++++ cmd/console/main.go | 101 +++++++++++++++++ 6 files changed, 402 insertions(+) create mode 100644 cmd/console/admin.go create mode 100755 cmd/console/console create mode 100644 cmd/console/contracts.go create mode 100755 cmd/console/history create mode 100644 cmd/console/js.go create mode 100644 cmd/console/main.go (limited to 'cmd') diff --git a/cmd/console/admin.go b/cmd/console/admin.go new file mode 100644 index 000000000..dee88e3a0 --- /dev/null +++ b/cmd/console/admin.go @@ -0,0 +1,9 @@ +package main + +/* +node admin bindings +*/ + +func (js *jsre) adminBindings() { + +} diff --git a/cmd/console/console b/cmd/console/console new file mode 100755 index 000000000..113fb5dac Binary files /dev/null and b/cmd/console/console differ diff --git a/cmd/console/contracts.go b/cmd/console/contracts.go new file mode 100644 index 000000000..1f27838d1 --- /dev/null +++ b/cmd/console/contracts.go @@ -0,0 +1,6 @@ +package main + +var ( + globalRegistrar = `var GlobalRegistrar = web3.eth.contract([{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"name","outputs":[{"name":"o_name","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"content","outputs":[{"name":"","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"addr","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"subRegistrar","outputs":[{"name":"o_subRegistrar","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_newOwner","type":"address"}],"name":"transfer","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_registrar","type":"address"}],"name":"setSubRegistrar","outputs":[],"type":"function"},{"constant":false,"inputs":[],"name":"Registrar","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_a","type":"address"},{"name":"_primary","type":"bool"}],"name":"setAddress","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_content","type":"bytes32"}],"name":"setContent","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"disown","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"address"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"}],"name":"Changed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"addr","type":"address"}],"name":"PrimaryChanged","type":"event"}]);` + globalRegistrarAddr = "0xc6d9d2cd449a754c494264e1809c50e34d64562b" +) diff --git a/cmd/console/history b/cmd/console/history new file mode 100755 index 000000000..728b6994a --- /dev/null +++ b/cmd/console/history @@ -0,0 +1,7 @@ +eth.accounts +help +eth +eth.getBlock(21) +net +admin +eth diff --git a/cmd/console/js.go b/cmd/console/js.go new file mode 100644 index 000000000..8b9137add --- /dev/null +++ b/cmd/console/js.go @@ -0,0 +1,279 @@ +// Copyright (c) 2013-2014, Jeffrey Wilcke. All rights reserved. +// +// This library 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 2.1 of the License, or (at your option) any later version. +// +// This library 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 this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301 USA + +package main + +import ( + "bufio" + "fmt" + "math/big" + "os" + "os/signal" + "path/filepath" + "strings" + + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/common/docserver" + re "github.com/ethereum/go-ethereum/jsre" + "github.com/ethereum/go-ethereum/rpc" + "github.com/peterh/liner" + "github.com/robertkrimen/otto" +) + +type prompter interface { + AppendHistory(string) + Prompt(p string) (string, error) + PasswordPrompt(p string) (string, error) +} + +type dumbterm struct{ r *bufio.Reader } + +func (r dumbterm) Prompt(p string) (string, error) { + fmt.Print(p) + line, err := r.r.ReadString('\n') + return strings.TrimSuffix(line, "\n"), err +} + +func (r dumbterm) PasswordPrompt(p string) (string, error) { + fmt.Println("!! Unsupported terminal, password will echo.") + fmt.Print(p) + input, err := bufio.NewReader(os.Stdin).ReadString('\n') + fmt.Println() + return input, err +} + +func (r dumbterm) AppendHistory(string) {} + +type jsre struct { + re *re.JSRE + wait chan *big.Int + ps1 string + atexit func() + datadir string + prompter +} + +func newJSRE(libPath, ipcpath string) *jsre { + js := &jsre{ps1: "> "} + js.wait = make(chan *big.Int) + + // update state in separare forever blocks + js.re = re.New(libPath) + js.apiBindings(ipcpath) + + if !liner.TerminalSupported() { + js.prompter = dumbterm{bufio.NewReader(os.Stdin)} + } else { + lr := liner.NewLiner() + js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) }) + lr.SetCtrlCAborts(true) + js.prompter = lr + js.atexit = func() { + js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) }) + lr.Close() + close(js.wait) + } + } + return js +} + +func (js *jsre) apiBindings(ipcpath string) { + ethApi := rpc.NewEthereumApi(nil) + jeth := rpc.NewJeth(ethApi, js.re, ipcpath) + + js.re.Set("jeth", struct{}{}) + t, _ := js.re.Get("jeth") + jethObj := t.Object() + jethObj.Set("send", jeth.SendIpc) + jethObj.Set("sendAsync", jeth.SendIpc) + + err := js.re.Compile("bignumber.js", re.BigNumber_JS) + if err != nil { + utils.Fatalf("Error loading bignumber.js: %v", err) + } + + err = js.re.Compile("ethereum.js", re.Web3_JS) + if err != nil { + utils.Fatalf("Error loading web3.js: %v", err) + } + + _, err = js.re.Eval("var web3 = require('web3');") + if err != nil { + utils.Fatalf("Error requiring web3: %v", err) + } + + _, err = js.re.Eval("web3.setProvider(jeth)") + if err != nil { + utils.Fatalf("Error setting web3 provider: %v", err) + } + _, err = js.re.Eval(` +var eth = web3.eth; + `) + + if err != nil { + utils.Fatalf("Error setting namespaces: %v", err) + } + + js.re.Eval(globalRegistrar + "registrar = GlobalRegistrar.at(\"" + globalRegistrarAddr + "\");") +} + +var ds, _ = docserver.New("/") + +/* +func (self *jsre) ConfirmTransaction(tx string) bool { + if self.ethereum.NatSpec { + notice := natspec.GetNotice(self.xeth, tx, ds) + fmt.Println(notice) + answer, _ := self.Prompt("Confirm Transaction [y/n]") + return strings.HasPrefix(strings.Trim(answer, " "), "y") + } else { + return true + } +} + +func (self *jsre) UnlockAccount(addr []byte) bool { + fmt.Printf("Please unlock account %x.\n", addr) + pass, err := self.PasswordPrompt("Passphrase: ") + if err != nil { + return false + } + // TODO: allow retry + if err := self.ethereum.AccountManager().Unlock(common.BytesToAddress(addr), pass); err != nil { + return false + } else { + fmt.Println("Account is now unlocked for this session.") + return true + } +} +*/ + +func (self *jsre) exec(filename string) error { + if err := self.re.Exec(filename); err != nil { + self.re.Stop(false) + return fmt.Errorf("Javascript Error: %v", err) + } + self.re.Stop(true) + return nil +} + +// show summary of current geth instance +func (self *jsre) welcome() { + self.re.Eval(` + console.log('Connected to ' + web3.version.client); + `) +} + +func (self *jsre) interactive() { + // Read input lines. + prompt := make(chan string) + inputln := make(chan string) + go func() { + defer close(inputln) + for { + line, err := self.Prompt(<-prompt) + if err != nil { + return + } + inputln <- line + } + }() + // Wait for Ctrl-C, too. + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt) + + defer func() { + if self.atexit != nil { + self.atexit() + } + self.re.Stop(false) + }() + for { + prompt <- self.ps1 + select { + case <-sig: + fmt.Println("caught interrupt, exiting") + return + case input, ok := <-inputln: + if !ok || indentCount <= 0 && input == "exit" { + return + } + if input == "" { + continue + } + str += input + "\n" + self.setIndent() + if indentCount <= 0 { + hist := str[:len(str)-1] + self.AppendHistory(hist) + self.parseInput(str) + str = "" + } + } + } +} + +func (self *jsre) withHistory(op func(*os.File)) { + hist, err := os.OpenFile(filepath.Join(self.datadir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm) + if err != nil { + fmt.Printf("unable to open history file: %v\n", err) + return + } + op(hist) + hist.Close() +} + +func (self *jsre) parseInput(code string) { + defer func() { + if r := recover(); r != nil { + fmt.Println("[native] error", r) + } + }() + value, err := self.re.Run(code) + if err != nil { + if ottoErr, ok := err.(*otto.Error); ok { + fmt.Println(ottoErr.String()) + } else { + fmt.Println(err) + } + return + } + self.printValue(value) +} + +var indentCount = 0 +var str = "" + +func (self *jsre) setIndent() { + open := strings.Count(str, "{") + open += strings.Count(str, "(") + closed := strings.Count(str, "}") + closed += strings.Count(str, ")") + indentCount = open - closed + if indentCount <= 0 { + self.ps1 = "> " + } else { + self.ps1 = strings.Join(make([]string, indentCount*2), "..") + self.ps1 += " " + } +} + +func (self *jsre) printValue(v interface{}) { + val, err := self.re.PrettyPrint(v) + if err == nil { + fmt.Printf("%v", val) + } +} diff --git a/cmd/console/main.go b/cmd/console/main.go new file mode 100644 index 000000000..781f1f8cb --- /dev/null +++ b/cmd/console/main.go @@ -0,0 +1,101 @@ +/* + 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 . +*/ +/** + * @authors + * Jeffrey Wilcke + */ +package main + +import ( + "fmt" + "io" + "os" + + "github.com/mattn/go-colorable" + "github.com/mattn/go-isatty" + "github.com/codegangsta/cli" + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/logger" +) + +const ( + ClientIdentifier = "Geth console" + Version = "0.9.27" +) + +var ( + gitCommit string // set via linker flag + nodeNameVersion string + app = utils.NewApp(Version, "the ether console") +) + +func init() { + if gitCommit == "" { + nodeNameVersion = Version + } else { + nodeNameVersion = Version + "-" + gitCommit[:8] + } + + app.Action = run + app.Flags = []cli.Flag{ + utils.IPCDisabledFlag, + utils.IPCPathFlag, + utils.VerbosityFlag, + utils.JSpathFlag, + } + + app.Before = func(ctx *cli.Context) error { + utils.SetupLogger(ctx) + return nil + } +} + +func main() { + // Wrap the standard output with a colorified stream (windows) + if isatty.IsTerminal(os.Stdout.Fd()) { + if pr, pw, err := os.Pipe(); err == nil { + go io.Copy(colorable.NewColorableStdout(), pr) + os.Stdout = pw + } + } + + var interrupted = false + utils.RegisterInterrupt(func(os.Signal) { + interrupted = true + }) + utils.HandleInterrupt() + + if err := app.Run(os.Args); err != nil { + fmt.Fprintln(os.Stderr, "Error: ", err) + } + + // we need to run the interrupt callbacks in case gui is closed + // this skips if we got here by actual interrupt stopping the GUI + if !interrupted { + utils.RunInterruptCallbacks(os.Interrupt) + } + logger.Flush() +} + +func run(ctx *cli.Context) { + jspath := ctx.GlobalString(utils.JSpathFlag.Name) + ipcpath := ctx.GlobalString(utils.IPCPathFlag.Name) + + repl := newJSRE(jspath, ipcpath) + repl.welcome() + repl.interactive() +} -- cgit v1.2.3 From faab931ce1282dea50c8fdf0577c42ee67f69828 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 8 Jun 2015 19:51:38 +0200 Subject: only load supported api's --- cmd/console/js.go | 82 +++++++++++++++++++++++++++++++++++++++++++++++++---- cmd/console/main.go | 8 +++--- 2 files changed, 81 insertions(+), 9 deletions(-) (limited to 'cmd') diff --git a/cmd/console/js.go b/cmd/console/js.go index 8b9137add..ea0961a39 100644 --- a/cmd/console/js.go +++ b/cmd/console/js.go @@ -26,12 +26,18 @@ import ( "path/filepath" "strings" + "encoding/json" + "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common/docserver" re "github.com/ethereum/go-ethereum/jsre" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/rpc/codec" + "github.com/ethereum/go-ethereum/rpc/comms" + "github.com/ethereum/go-ethereum/rpc/shared" "github.com/peterh/liner" "github.com/robertkrimen/otto" + "github.com/ethereum/go-ethereum/rpc/api" ) type prompter interface { @@ -120,9 +126,27 @@ func (js *jsre) apiBindings(ipcpath string) { if err != nil { utils.Fatalf("Error setting web3 provider: %v", err) } - _, err = js.re.Eval(` -var eth = web3.eth; - `) + + apis, err := js.suportedApis(ipcpath) + if err != nil { + utils.Fatalf("Unable to determine supported api's: %v", err) + } + + // load only supported API's in javascript runtime + shortcuts := "var eth = web3.eth; " + for _, apiName := range apis { + if apiName == api.Web3ApiName || apiName == api.EthApiName { + continue // manually mapped + } + + if err = js.re.Compile(fmt.Sprintf("%s.js", apiName), api.Javascript(apiName)); err == nil { + shortcuts += fmt.Sprintf("var %s = web3.%s; ", apiName, apiName) + } else { + utils.Fatalf("Error loading %s.js: %v", apiName, err) + } + } + + _, err = js.re.Eval(shortcuts) if err != nil { utils.Fatalf("Error setting namespaces: %v", err) @@ -170,11 +194,59 @@ func (self *jsre) exec(filename string) error { return nil } +func (self *jsre) suportedApis(ipcpath string) ([]string, error) { + config := comms.IpcConfig{ + Endpoint: ipcpath, + } + + client, err := comms.NewIpcClient(config, codec.JSON) + if err != nil { + return nil, err + } + + req := shared.Request{ + Id: 1, + Jsonrpc: "2.0", + Method: "support_apis", + } + + err = client.Send(req) + if err != nil { + return nil, err + } + + res, err := client.Recv() + if err != nil { + return nil, err + } + + if sucRes, ok := res.(shared.SuccessResponse); ok { + data, _ := json.Marshal(sucRes.Result) + apis := make([]string, 0) + err = json.Unmarshal(data, &apis) + if err == nil { + return apis, nil + } + } + + return nil, fmt.Errorf("Unable to determine supported API's") +} + // show summary of current geth instance -func (self *jsre) welcome() { +func (self *jsre) welcome(ipcpath string) { self.re.Eval(` - console.log('Connected to ' + web3.version.client); + console.log(' Connected to: ' + web3.version.client); `) + + if apis, err := self.suportedApis(ipcpath); err == nil { + apisStr := "" + for _, api := range apis { + apisStr += api + " " + } + self.re.Eval(fmt.Sprintf(`console.log("Available api's: %s");`, apisStr)) + } else { + utils.Fatalf("unable to determine supported api's - %v", err) + } } func (self *jsre) interactive() { diff --git a/cmd/console/main.go b/cmd/console/main.go index 781f1f8cb..9020a12fe 100644 --- a/cmd/console/main.go +++ b/cmd/console/main.go @@ -25,11 +25,11 @@ import ( "io" "os" - "github.com/mattn/go-colorable" - "github.com/mattn/go-isatty" "github.com/codegangsta/cli" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/logger" + "github.com/mattn/go-colorable" + "github.com/mattn/go-isatty" ) const ( @@ -40,7 +40,7 @@ const ( var ( gitCommit string // set via linker flag nodeNameVersion string - app = utils.NewApp(Version, "the ether console") + app = utils.NewApp(Version, "the ether console") ) func init() { @@ -96,6 +96,6 @@ func run(ctx *cli.Context) { ipcpath := ctx.GlobalString(utils.IPCPathFlag.Name) repl := newJSRE(jspath, ipcpath) - repl.welcome() + repl.welcome(ipcpath) repl.interactive() } -- cgit v1.2.3 From c6c443385b3e9998d3090785e4287e3836c70219 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Wed, 10 Jun 2015 10:24:22 +0200 Subject: changed console welcome message --- cmd/console/js.go | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'cmd') diff --git a/cmd/console/js.go b/cmd/console/js.go index ea0961a39..4229a95a2 100644 --- a/cmd/console/js.go +++ b/cmd/console/js.go @@ -234,18 +234,15 @@ func (self *jsre) suportedApis(ipcpath string) ([]string, error) { // show summary of current geth instance func (self *jsre) welcome(ipcpath string) { - self.re.Eval(` - console.log(' Connected to: ' + web3.version.client); - `) - - if apis, err := self.suportedApis(ipcpath); err == nil { - apisStr := "" - for _, api := range apis { - apisStr += api + " " - } - self.re.Eval(fmt.Sprintf(`console.log("Available api's: %s");`, apisStr)) - } else { - utils.Fatalf("unable to determine supported api's - %v", err) + self.re.Eval(`console.log('instance: ' + web3.version.client);`) + self.re.Eval(`console.log("coinbase: " + eth.coinbase);`) + self.re.Eval(`var lastBlockTimestamp = 1000 * eth.getBlock(eth.blockNumber).timestamp`) + self.re.Eval(`console.log("at block: " + eth.blockNumber + " (" + new Date(lastBlockTimestamp).toLocaleDateString() + + " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`) + + if modules, err := self.suportedApis(ipcpath); err == nil { + self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(modules, " "))) + self.re.Eval(`console.log(" modules: " + modules);`) } } -- cgit v1.2.3 From bd38428f33b127e9c60d26127695e50c55798fcd Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Wed, 10 Jun 2015 11:29:52 +0200 Subject: cleanup of javascript API --- cmd/console/js.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/console/js.go b/cmd/console/js.go index 4229a95a2..76695cabd 100644 --- a/cmd/console/js.go +++ b/cmd/console/js.go @@ -32,12 +32,12 @@ import ( "github.com/ethereum/go-ethereum/common/docserver" re "github.com/ethereum/go-ethereum/jsre" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/comms" "github.com/ethereum/go-ethereum/rpc/shared" "github.com/peterh/liner" "github.com/robertkrimen/otto" - "github.com/ethereum/go-ethereum/rpc/api" ) type prompter interface { @@ -235,6 +235,7 @@ func (self *jsre) suportedApis(ipcpath string) ([]string, error) { // show summary of current geth instance func (self *jsre) welcome(ipcpath string) { self.re.Eval(`console.log('instance: ' + web3.version.client);`) + self.re.Eval(`console.log(' datadir: ' + admin.datadir);`) self.re.Eval(`console.log("coinbase: " + eth.coinbase);`) self.re.Eval(`var lastBlockTimestamp = 1000 * eth.getBlock(eth.blockNumber).timestamp`) self.re.Eval(`console.log("at block: " + eth.blockNumber + " (" + new Date(lastBlockTimestamp).toLocaleDateString() -- cgit v1.2.3 From 1b59f890955c3658516daa958d0e4732004a78b7 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 8 Jun 2015 12:43:58 +0200 Subject: added console command --- cmd/geth/main.go | 2 ++ 1 file changed, 2 insertions(+) (limited to 'cmd') diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 8e55b310c..9e4083251 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -307,6 +307,7 @@ func console(ctx *cli.Context) { repl := newJSRE( ethereum, ctx.String(utils.JSpathFlag.Name), + ctx.GlobalString(utils.IPCPathFlag.Name), ctx.GlobalString(utils.RPCCORSDomainFlag.Name), ctx.GlobalString(utils.IPCPathFlag.Name), true, @@ -329,6 +330,7 @@ func execJSFiles(ctx *cli.Context) { repl := newJSRE( ethereum, ctx.String(utils.JSpathFlag.Name), + ctx.GlobalString(utils.IPCPathFlag.Name), ctx.GlobalString(utils.RPCCORSDomainFlag.Name), ctx.GlobalString(utils.IPCPathFlag.Name), false, -- cgit v1.2.3 From 594a34a88d8e66e82f5333b66f83561f0c0c5bd4 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 8 Jun 2015 13:21:24 +0200 Subject: changed send methods for backwards compatability in geth console --- cmd/geth/main.go | 2 -- 1 file changed, 2 deletions(-) (limited to 'cmd') diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 9e4083251..8e55b310c 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -307,7 +307,6 @@ func console(ctx *cli.Context) { repl := newJSRE( ethereum, ctx.String(utils.JSpathFlag.Name), - ctx.GlobalString(utils.IPCPathFlag.Name), ctx.GlobalString(utils.RPCCORSDomainFlag.Name), ctx.GlobalString(utils.IPCPathFlag.Name), true, @@ -330,7 +329,6 @@ func execJSFiles(ctx *cli.Context) { repl := newJSRE( ethereum, ctx.String(utils.JSpathFlag.Name), - ctx.GlobalString(utils.IPCPathFlag.Name), ctx.GlobalString(utils.RPCCORSDomainFlag.Name), ctx.GlobalString(utils.IPCPathFlag.Name), false, -- cgit v1.2.3 From aa258dcc5f01a05c81075be999c83446862abb42 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 8 Jun 2015 19:14:42 +0200 Subject: added console binary --- cmd/console/js.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 5 deletions(-) (limited to 'cmd') diff --git a/cmd/console/js.go b/cmd/console/js.go index 76695cabd..633b79315 100644 --- a/cmd/console/js.go +++ b/cmd/console/js.go @@ -28,6 +28,8 @@ import ( "encoding/json" + "sort" + "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common/docserver" re "github.com/ethereum/go-ethereum/jsre" @@ -73,6 +75,79 @@ type jsre struct { prompter } +var ( + loadedModulesMethods map[string][]string +) + +func loadAutoCompletion(js *jsre, ipcpath string) { + modules, err := js.suportedApis(ipcpath) + if err != nil { + utils.Fatalf("Unable to determine supported modules - %v", err) + } + + fmt.Printf("load autocompletion %v", modules) + + loadedModulesMethods = make(map[string][]string) + for module, _ := range modules { + loadedModulesMethods[module] = api.AutoCompletion[module] + } +} + +func keywordCompleter(line string) []string { + results := make([]string, 0) + + if strings.Contains(line, ".") { + elements := strings.Split(line, ".") + if len(elements) == 2 { + module := elements[0] + partialMethod := elements[1] + if methods, found := loadedModulesMethods[module]; found { + for _, method := range methods { + if strings.HasPrefix(method, partialMethod) { // e.g. debug.se + results = append(results, module+"."+method) + } + } + } + } + } else { + for module, methods := range loadedModulesMethods { + if line == module { // user typed in full module name, show all methods + for _, method := range methods { + results = append(results, module+"."+method) + } + } else if strings.HasPrefix(module, line) { // partial method name, e.g. admi + results = append(results, module) + } + } + } + return results +} + +func apiWordCompleter(line string, pos int) (head string, completions []string, tail string) { + if len(line) == 0 { + return "", nil, "" + } + + i := 0 + for i = pos - 1; i > 0; i-- { + if line[i] == '.' || (line[i] >= 'a' && line[i] <= 'z') || (line[i] >= 'A' && line[i] <= 'Z') { + continue + } + if i >= 3 && line[i] == '3' && line[i-3] == 'w' && line[i-2] == 'e' && line[i-1] == 'b' { + continue + } + i += 1 + break + } + + begin := line[:i] + keyword := line[i:pos] + end := line[pos:] + + completionWords := keywordCompleter(keyword) + return begin, completionWords, end +} + func newJSRE(libPath, ipcpath string) *jsre { js := &jsre{ps1: "> "} js.wait = make(chan *big.Int) @@ -87,6 +162,9 @@ func newJSRE(libPath, ipcpath string) *jsre { lr := liner.NewLiner() js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) }) lr.SetCtrlCAborts(true) + loadAutoCompletion(js, ipcpath) + 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) }) @@ -134,7 +212,7 @@ func (js *jsre) apiBindings(ipcpath string) { // load only supported API's in javascript runtime shortcuts := "var eth = web3.eth; " - for _, apiName := range apis { + for apiName, _ := range apis { if apiName == api.Web3ApiName || apiName == api.EthApiName { continue // manually mapped } @@ -194,7 +272,7 @@ func (self *jsre) exec(filename string) error { return nil } -func (self *jsre) suportedApis(ipcpath string) ([]string, error) { +func (self *jsre) suportedApis(ipcpath string) (map[string]string, error) { config := comms.IpcConfig{ Endpoint: ipcpath, } @@ -207,7 +285,7 @@ func (self *jsre) suportedApis(ipcpath string) ([]string, error) { req := shared.Request{ Id: 1, Jsonrpc: "2.0", - Method: "support_apis", + Method: "modules", } err = client.Send(req) @@ -222,7 +300,7 @@ func (self *jsre) suportedApis(ipcpath string) ([]string, error) { if sucRes, ok := res.(shared.SuccessResponse); ok { data, _ := json.Marshal(sucRes.Result) - apis := make([]string, 0) + apis := make(map[string]string) err = json.Unmarshal(data, &apis) if err == nil { return apis, nil @@ -242,7 +320,13 @@ func (self *jsre) welcome(ipcpath string) { + " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`) if modules, err := self.suportedApis(ipcpath); err == nil { - self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(modules, " "))) + loadedModules := make([]string, 0) + for api, version := range modules { + loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version)) + } + sort.Strings(loadedModules) + + self.re.Eval(fmt.Sprintf("var modules = '%s';", strings.Join(loadedModules, " "))) self.re.Eval(`console.log(" modules: " + modules);`) } } -- cgit v1.2.3 From ebaa9b9feb0325de33c69993cd9c215775618c7b Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Thu, 11 Jun 2015 14:54:03 +0200 Subject: removed binary files --- cmd/console/console | Bin 19332472 -> 0 bytes cmd/console/history | 7 ------- 2 files changed, 7 deletions(-) delete mode 100755 cmd/console/console delete mode 100755 cmd/console/history (limited to 'cmd') diff --git a/cmd/console/console b/cmd/console/console deleted file mode 100755 index 113fb5dac..000000000 Binary files a/cmd/console/console and /dev/null differ diff --git a/cmd/console/history b/cmd/console/history deleted file mode 100755 index 728b6994a..000000000 --- a/cmd/console/history +++ /dev/null @@ -1,7 +0,0 @@ -eth.accounts -help -eth -eth.getBlock(21) -net -admin -eth -- cgit v1.2.3 From ec6a7b35f68d4fd0fbf8e59f70096765cff4bffc Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Thu, 11 Jun 2015 15:00:33 +0200 Subject: removed obsolete print statement --- cmd/console/js.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/console/js.go b/cmd/console/js.go index 633b79315..5aff8acfd 100644 --- a/cmd/console/js.go +++ b/cmd/console/js.go @@ -84,9 +84,7 @@ func loadAutoCompletion(js *jsre, ipcpath string) { if err != nil { utils.Fatalf("Unable to determine supported modules - %v", err) } - - fmt.Printf("load autocompletion %v", modules) - + loadedModulesMethods = make(map[string][]string) for module, _ := range modules { loadedModulesMethods[module] = api.AutoCompletion[module] -- cgit v1.2.3 From b3c07f167f8b82d1079abe6e15cd1f480712b030 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Thu, 11 Jun 2015 15:06:12 +0200 Subject: fixed incomplete merge action --- cmd/console/js.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/console/js.go b/cmd/console/js.go index 5aff8acfd..a5fdaacc2 100644 --- a/cmd/console/js.go +++ b/cmd/console/js.go @@ -84,7 +84,7 @@ func loadAutoCompletion(js *jsre, ipcpath string) { if err != nil { utils.Fatalf("Unable to determine supported modules - %v", err) } - + loadedModulesMethods = make(map[string][]string) for module, _ := range modules { loadedModulesMethods[module] = api.AutoCompletion[module] -- cgit v1.2.3