aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorJeffrey Wilcke <jeffrey@ethereum.org>2015-06-23 22:44:03 +0800
committerJeffrey Wilcke <jeffrey@ethereum.org>2015-06-23 22:44:03 +0800
commit6b5532ab0d0e88f27af539840c58cbd6de13de90 (patch)
tree84f1856e1b3fb2fd927e6ef9c59983e4fb347a8c /cmd
parent139439dcdc14e448bfdbd509bb135faa92337a28 (diff)
parent2b3957f3737b56622e38425a52caea2a836f8b63 (diff)
downloadgo-tangerine-6b5532ab0d0e88f27af539840c58cbd6de13de90.tar
go-tangerine-6b5532ab0d0e88f27af539840c58cbd6de13de90.tar.gz
go-tangerine-6b5532ab0d0e88f27af539840c58cbd6de13de90.tar.bz2
go-tangerine-6b5532ab0d0e88f27af539840c58cbd6de13de90.tar.lz
go-tangerine-6b5532ab0d0e88f27af539840c58cbd6de13de90.tar.xz
go-tangerine-6b5532ab0d0e88f27af539840c58cbd6de13de90.tar.zst
go-tangerine-6b5532ab0d0e88f27af539840c58cbd6de13de90.zip
Merge pull request #1279 from bas-vk/rpc-http
Integrate console and remove old rpc package structure
Diffstat (limited to 'cmd')
-rw-r--r--cmd/console/admin.go9
-rw-r--r--cmd/console/contracts.go6
-rw-r--r--cmd/console/js.go454
-rw-r--r--cmd/console/main.go103
-rw-r--r--cmd/geth/admin.go937
-rw-r--r--cmd/geth/js.go225
-rw-r--r--cmd/geth/js_test.go19
-rw-r--r--cmd/geth/main.go71
-rw-r--r--cmd/utils/flags.go27
9 files changed, 307 insertions, 1544 deletions
diff --git a/cmd/console/admin.go b/cmd/console/admin.go
deleted file mode 100644
index dee88e3a0..000000000
--- a/cmd/console/admin.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package main
-
-/*
-node admin bindings
-*/
-
-func (js *jsre) adminBindings() {
-
-}
diff --git a/cmd/console/contracts.go b/cmd/console/contracts.go
deleted file mode 100644
index 1f27838d1..000000000
--- a/cmd/console/contracts.go
+++ /dev/null
@@ -1,6 +0,0 @@
-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/js.go b/cmd/console/js.go
deleted file mode 100644
index 15ea9bedd..000000000
--- a/cmd/console/js.go
+++ /dev/null
@@ -1,454 +0,0 @@
-// 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"
-
- "encoding/json"
-
- "sort"
-
- "github.com/codegangsta/cli"
- "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/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"
-)
-
-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
-}
-
-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)
- }
-
- 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)
-
- // 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)
- 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) })
- 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)
- }
-
- 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)
- }
-
- 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
-}
-
-func (self *jsre) suportedApis(ipcpath string) (map[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: "modules",
- }
-
- 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(map[string]string)
- 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(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()
- + " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`)
-
- if modules, err := self.suportedApis(ipcpath); err == nil {
- 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);`)
- }
-}
-
-func (self *jsre) batch(args cli.Args) {
- statement := strings.Join(args, " ")
- val, err := self.re.Run(statement)
-
- if err != nil {
- fmt.Printf("error: %v", err)
- } else if val.IsDefined() && val.IsObject() {
- obj, _ := self.re.Get("ret_result")
- fmt.Printf("%v", obj)
- } else if val.IsDefined() {
- fmt.Printf("%v", val)
- }
-
- if self.atexit != nil {
- self.atexit()
- }
-
- self.re.Stop(false)
-}
-
-func (self *jsre) interactive(ipcpath string) {
- self.welcome(ipcpath)
-
- // 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
deleted file mode 100644
index 00a9ca9c4..000000000
--- a/cmd/console/main.go
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- 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/>.
-*/
-/**
- * @authors
- * Jeffrey Wilcke <i@jev.io>
- */
-package main
-
-import (
- "fmt"
- "io"
- "os"
-
- "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 (
- ClientIdentifier = "Geth console"
- Version = "0.9.27"
-)
-
-var (
- gitCommit string // set via linker flag
- nodeNameVersion string
- app = utils.NewApp(Version, "the geth console")
-)
-
-func init() {
- if gitCommit == "" {
- nodeNameVersion = Version
- } else {
- nodeNameVersion = Version + "-" + gitCommit[:8]
- }
-
- app.Action = run
- app.Flags = []cli.Flag{
- 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 := utils.IpcSocketPath(ctx)
- repl := newJSRE(jspath, ipcpath)
-
- if ctx.Args().Present() {
- repl.batch(ctx.Args())
- } else {
- repl.interactive(ipcpath)
- }
-}
diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go
deleted file mode 100644
index 33ef69792..000000000
--- a/cmd/geth/admin.go
+++ /dev/null
@@ -1,937 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "math/big"
- "strconv"
- "time"
-
- "github.com/ethereum/ethash"
- "github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/cmd/utils"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/compiler"
- "github.com/ethereum/go-ethereum/common/natspec"
- "github.com/ethereum/go-ethereum/common/resolver"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/logger/glog"
- "github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/xeth"
- "github.com/robertkrimen/otto"
- "gopkg.in/fatih/set.v0"
-)
-
-/*
-node admin bindings
-*/
-
-func (js *jsre) adminBindings() {
- ethO, _ := js.re.Get("eth")
- eth := ethO.Object()
- eth.Set("pendingTransactions", js.pendingTransactions)
- eth.Set("resend", js.resend)
- eth.Set("sign", js.sign)
-
- js.re.Set("admin", struct{}{})
- t, _ := js.re.Get("admin")
- admin := t.Object()
- admin.Set("addPeer", js.addPeer)
- admin.Set("startRPC", js.startRPC)
- admin.Set("stopRPC", js.stopRPC)
- admin.Set("nodeInfo", js.nodeInfo)
- admin.Set("peers", js.peers)
- admin.Set("newAccount", js.newAccount)
- admin.Set("unlock", js.unlock)
- admin.Set("import", js.importChain)
- admin.Set("export", js.exportChain)
- admin.Set("verbosity", js.verbosity)
- admin.Set("progress", js.syncProgress)
- admin.Set("setSolc", js.setSolc)
-
- admin.Set("contractInfo", struct{}{})
- t, _ = admin.Get("contractInfo")
- cinfo := t.Object()
- // newRegistry officially not documented temporary option
- cinfo.Set("start", js.startNatSpec)
- cinfo.Set("stop", js.stopNatSpec)
- cinfo.Set("newRegistry", js.newRegistry)
- cinfo.Set("get", js.getContractInfo)
- cinfo.Set("register", js.register)
- cinfo.Set("registerUrl", js.registerUrl)
- // cinfo.Set("verify", js.verify)
-
- admin.Set("miner", struct{}{})
- t, _ = admin.Get("miner")
- miner := t.Object()
- miner.Set("start", js.startMining)
- miner.Set("stop", js.stopMining)
- miner.Set("hashrate", js.hashrate)
- miner.Set("setExtra", js.setExtra)
- miner.Set("setGasPrice", js.setGasPrice)
- miner.Set("startAutoDAG", js.startAutoDAG)
- miner.Set("stopAutoDAG", js.stopAutoDAG)
- miner.Set("makeDAG", js.makeDAG)
-
- admin.Set("txPool", struct{}{})
- t, _ = admin.Get("txPool")
- txPool := t.Object()
- txPool.Set("pending", js.allPendingTransactions)
- txPool.Set("queued", js.allQueuedTransactions)
-
- admin.Set("debug", struct{}{})
- t, _ = admin.Get("debug")
- debug := t.Object()
- js.re.Set("sleep", js.sleep)
- debug.Set("backtrace", js.backtrace)
- debug.Set("printBlock", js.printBlock)
- debug.Set("dumpBlock", js.dumpBlock)
- debug.Set("getBlockRlp", js.getBlockRlp)
- debug.Set("setHead", js.setHead)
- debug.Set("processBlock", js.debugBlock)
- debug.Set("seedhash", js.seedHash)
- debug.Set("insertBlock", js.insertBlockRlp)
- // undocumented temporary
- debug.Set("waitForBlocks", js.waitForBlocks)
-}
-
-// generic helper to getBlock by Number/Height or Hex depending on autodetected input
-// if argument is missing the current block is returned
-// if block is not found or there is problem with decoding
-// the appropriate value is returned and block is guaranteed to be nil
-func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
- var block *types.Block
- if len(call.ArgumentList) > 0 {
- if call.Argument(0).IsNumber() {
- num, _ := call.Argument(0).ToInteger()
- block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num))
- } else if call.Argument(0).IsString() {
- hash, _ := call.Argument(0).ToString()
- block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
- } else {
- return nil, errors.New("invalid argument for dump. Either hex string or number")
- }
- } else {
- block = js.ethereum.ChainManager().CurrentBlock()
- }
-
- if block == nil {
- return nil, errors.New("block not found")
- }
- return block, nil
-}
-
-func (js *jsre) seedHash(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) > 0 {
- if call.Argument(0).IsNumber() {
- num, _ := call.Argument(0).ToInteger()
- hash, err := ethash.GetSeedHash(uint64(num))
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- v, _ := call.Otto.ToValue(fmt.Sprintf("0x%x", hash))
- return v
- } else {
- fmt.Println("arg not a number")
- }
- } else {
- fmt.Println("requires number argument")
- }
-
- return otto.UndefinedValue()
-}
-
-func (js *jsre) allPendingTransactions(call otto.FunctionCall) otto.Value {
- txs := js.ethereum.TxPool().GetTransactions()
-
- ltxs := make([]*tx, len(txs))
- for i, tx := range txs {
- // no need to check err
- ltxs[i] = newTx(tx)
- }
-
- v, _ := call.Otto.ToValue(ltxs)
- return v
-}
-
-func (js *jsre) allQueuedTransactions(call otto.FunctionCall) otto.Value {
- txs := js.ethereum.TxPool().GetQueuedTransactions()
-
- ltxs := make([]*tx, len(txs))
- for i, tx := range txs {
- // no need to check err
- ltxs[i] = newTx(tx)
- }
-
- v, _ := call.Otto.ToValue(ltxs)
- return v
-}
-
-func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value {
- txs := js.ethereum.TxPool().GetTransactions()
-
- // grab the accounts from the account manager. This will help with determening which
- // transactions should be returned.
- accounts, err := js.ethereum.AccountManager().Accounts()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- // Add the accouns to a new set
- accountSet := set.New()
- for _, account := range accounts {
- accountSet.Add(account.Address)
- }
-
- //ltxs := make([]*tx, len(txs))
- var ltxs []*tx
- for _, tx := range txs {
- if from, _ := tx.From(); accountSet.Has(from) {
- ltxs = append(ltxs, newTx(tx))
- }
- }
-
- v, _ := call.Otto.ToValue(ltxs)
- return v
-}
-
-func (js *jsre) resend(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) == 0 {
- fmt.Println("first argument must be a transaction")
- return otto.FalseValue()
- }
-
- v, err := call.Argument(0).Export()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- if tx, ok := v.(*tx); ok {
- gl, gp := tx.GasLimit, tx.GasPrice
- if len(call.ArgumentList) > 1 {
- gp = call.Argument(1).String()
- }
- if len(call.ArgumentList) > 2 {
- gl = call.Argument(2).String()
- }
-
- ret, err := js.xeth.Transact(tx.From, tx.To, tx.Nonce, tx.Value, gl, gp, tx.Data)
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx})
-
- v, _ := call.Otto.ToValue(ret)
- return v
- }
-
- fmt.Println("first argument must be a transaction")
- return otto.FalseValue()
-}
-
-func (js *jsre) sign(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) != 2 {
- fmt.Println("requires 2 arguments: eth.sign(signer, data)")
- return otto.UndefinedValue()
- }
- signer, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- data, err := call.Argument(1).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- signed, err := js.xeth.Sign(signer, data, false)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- v, _ := call.Otto.ToValue(signed)
- return v
-}
-
-func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
- block, err := js.getBlock(call)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- tstart := time.Now()
- old := vm.Debug
-
- if len(call.ArgumentList) > 1 {
- vm.Debug, _ = call.Argument(1).ToBoolean()
- }
-
- _, err = js.ethereum.BlockProcessor().RetryProcess(block)
- if err != nil {
- fmt.Println(err)
- r, _ := call.Otto.ToValue(map[string]interface{}{"success": false, "time": time.Since(tstart).Seconds()})
- return r
- }
- vm.Debug = old
-
- r, _ := call.Otto.ToValue(map[string]interface{}{"success": true, "time": time.Since(tstart).Seconds()})
- return r
-}
-
-func (js *jsre) insertBlockRlp(call otto.FunctionCall) otto.Value {
- tstart := time.Now()
-
- var block types.Block
- if call.Argument(0).IsString() {
- blockRlp, _ := call.Argument(0).ToString()
- err := rlp.DecodeBytes(common.Hex2Bytes(blockRlp), &block)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- }
-
- old := vm.Debug
- vm.Debug = true
- _, err := js.ethereum.BlockProcessor().RetryProcess(&block)
- if err != nil {
- fmt.Println(err)
- r, _ := call.Otto.ToValue(map[string]interface{}{"success": false, "time": time.Since(tstart).Seconds()})
- return r
- }
- vm.Debug = old
-
- r, _ := call.Otto.ToValue(map[string]interface{}{"success": true, "time": time.Since(tstart).Seconds()})
- return r
-}
-
-func (js *jsre) setHead(call otto.FunctionCall) otto.Value {
- block, err := js.getBlock(call)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- js.ethereum.ChainManager().SetHead(block)
- return otto.UndefinedValue()
-}
-
-func (js *jsre) syncProgress(call otto.FunctionCall) otto.Value {
- pending, cached, importing, eta := js.ethereum.Downloader().Stats()
- v, _ := call.Otto.ToValue(map[string]interface{}{
- "pending": pending,
- "cached": cached,
- "importing": importing,
- "estimate": (eta / time.Second * time.Second).String(),
- })
- return v
-}
-
-func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
- block, err := js.getBlock(call)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- encoded, _ := rlp.EncodeToBytes(block)
- v, _ := call.Otto.ToValue(fmt.Sprintf("%x", encoded))
- return v
-}
-
-func (js *jsre) setExtra(call otto.FunctionCall) otto.Value {
- extra, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- if len(extra) > 1024 {
- fmt.Println("error: cannot exceed 1024 bytes")
- return otto.UndefinedValue()
- }
-
- js.ethereum.Miner().SetExtra([]byte(extra))
- return otto.UndefinedValue()
-}
-
-func (js *jsre) setGasPrice(call otto.FunctionCall) otto.Value {
- gasPrice, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- js.ethereum.Miner().SetGasPrice(common.String2Big(gasPrice))
- return otto.UndefinedValue()
-}
-
-func (js *jsre) hashrate(call otto.FunctionCall) otto.Value {
- v, _ := call.Otto.ToValue(js.ethereum.Miner().HashRate())
- return v
-}
-
-func (js *jsre) makeDAG(call otto.FunctionCall) otto.Value {
- blockNumber, err := call.Argument(1).ToInteger()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- err = ethash.MakeDAG(uint64(blockNumber), "")
- if err != nil {
- return otto.FalseValue()
- }
- return otto.TrueValue()
-}
-
-func (js *jsre) startAutoDAG(otto.FunctionCall) otto.Value {
- js.ethereum.StartAutoDAG()
- return otto.TrueValue()
-}
-
-func (js *jsre) stopAutoDAG(otto.FunctionCall) otto.Value {
- js.ethereum.StopAutoDAG()
- return otto.TrueValue()
-}
-
-func (js *jsre) backtrace(call otto.FunctionCall) otto.Value {
- tracestr, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- glog.GetTraceLocation().Set(tracestr)
-
- return otto.UndefinedValue()
-}
-
-func (js *jsre) verbosity(call otto.FunctionCall) otto.Value {
- v, err := call.Argument(0).ToInteger()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- glog.SetV(int(v))
- return otto.UndefinedValue()
-}
-
-func (js *jsre) startMining(call otto.FunctionCall) otto.Value {
- var (
- threads int64
- err error
- )
-
- if len(call.ArgumentList) > 0 {
- threads, err = call.Argument(0).ToInteger()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- } else {
- threads = int64(js.ethereum.MinerThreads)
- }
-
- // switch on DAG autogeneration when miner starts
- js.ethereum.StartAutoDAG()
-
- err = js.ethereum.StartMining(int(threads))
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- return otto.TrueValue()
-}
-
-func (js *jsre) stopMining(call otto.FunctionCall) otto.Value {
- js.ethereum.StopMining()
- js.ethereum.StopAutoDAG()
- return otto.TrueValue()
-}
-
-func (js *jsre) startRPC(call otto.FunctionCall) otto.Value {
- addr, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- port, err := call.Argument(1).ToInteger()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- corsDomain := js.corsDomain
- if len(call.ArgumentList) > 2 {
- corsDomain, err = call.Argument(2).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- }
-
- config := rpc.RpcConfig{
- ListenAddress: addr,
- ListenPort: uint(port),
- CorsDomain: corsDomain,
- }
-
- xeth := xeth.New(js.ethereum, nil)
- err = rpc.Start(xeth, config)
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- return otto.TrueValue()
-}
-
-func (js *jsre) stopRPC(call otto.FunctionCall) otto.Value {
- if rpc.Stop() == nil {
- return otto.TrueValue()
- }
- return otto.FalseValue()
-}
-
-func (js *jsre) addPeer(call otto.FunctionCall) otto.Value {
- nodeURL, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- err = js.ethereum.AddPeer(nodeURL)
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- return otto.TrueValue()
-}
-
-func (js *jsre) unlock(call otto.FunctionCall) otto.Value {
- addr, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- seconds, err := call.Argument(2).ToInteger()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- if seconds == 0 {
- seconds = accounts.DefaultAccountUnlockDuration
- }
-
- arg := call.Argument(1)
- var passphrase string
- if arg.IsUndefined() {
- fmt.Println("Please enter a passphrase now.")
- passphrase, err = utils.PromptPassword("Passphrase: ", true)
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- } else {
- passphrase, err = arg.ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- }
- am := js.ethereum.AccountManager()
- err = am.TimedUnlock(common.HexToAddress(addr), passphrase, time.Duration(seconds)*time.Second)
- if err != nil {
- fmt.Printf("Unlock account failed '%v'\n", err)
- return otto.FalseValue()
- }
- return otto.TrueValue()
-}
-
-func (js *jsre) newAccount(call otto.FunctionCall) otto.Value {
- arg := call.Argument(0)
- var passphrase string
- if arg.IsUndefined() {
- fmt.Println("The new account will be encrypted with a passphrase.")
- fmt.Println("Please enter a passphrase now.")
- auth, err := utils.PromptPassword("Passphrase: ", true)
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- if auth != confirm {
- fmt.Println("Passphrases did not match.")
- return otto.FalseValue()
- }
- passphrase = auth
- } else {
- var err error
- passphrase, err = arg.ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- }
- acct, err := js.ethereum.AccountManager().NewAccount(passphrase)
- if err != nil {
- fmt.Printf("Could not create the account: %v", err)
- return otto.UndefinedValue()
- }
- v, _ := call.Otto.ToValue(acct.Address.Hex())
- return v
-}
-
-func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value {
- v, _ := call.Otto.ToValue(js.ethereum.NodeInfo())
- return v
-}
-
-func (js *jsre) peers(call otto.FunctionCall) otto.Value {
- v, _ := call.Otto.ToValue(js.ethereum.PeersInfo())
- return v
-}
-
-func (js *jsre) importChain(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) == 0 {
- fmt.Println("require file name. admin.importChain(filename)")
- return otto.FalseValue()
- }
- fn, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- if err := utils.ImportChain(js.ethereum.ChainManager(), fn); err != nil {
- fmt.Println("Import error: ", err)
- return otto.FalseValue()
- }
- return otto.TrueValue()
-}
-
-func (js *jsre) exportChain(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) == 0 {
- fmt.Println("require file name: admin.exportChain(filename)")
- return otto.FalseValue()
- }
-
- fn, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- if err := utils.ExportChain(js.ethereum.ChainManager(), fn); err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- return otto.TrueValue()
-}
-
-func (js *jsre) printBlock(call otto.FunctionCall) otto.Value {
- block, err := js.getBlock(call)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- fmt.Println(block)
-
- return otto.UndefinedValue()
-}
-
-func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
- block, err := js.getBlock(call)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- statedb := state.New(block.Root(), js.ethereum.StateDb())
- dump := statedb.RawDump()
- v, _ := call.Otto.ToValue(dump)
- return v
-}
-
-func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) > 2 {
- fmt.Println("requires 0, 1 or 2 arguments: admin.debug.waitForBlock(minHeight, timeout)")
- return otto.FalseValue()
- }
- var n, timeout int64
- var timer <-chan time.Time
- var height *big.Int
- var err error
- args := len(call.ArgumentList)
- if args == 2 {
- timeout, err = call.Argument(1).ToInteger()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- timer = time.NewTimer(time.Duration(timeout) * time.Second).C
- }
- if args >= 1 {
- n, err = call.Argument(0).ToInteger()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- height = big.NewInt(n)
- }
-
- if args == 0 {
- height = js.xeth.CurrentBlock().Number()
- height.Add(height, common.Big1)
- }
-
- wait := js.wait
- js.wait <- height
- select {
- case <-timer:
- // if times out make sure the xeth loop does not block
- go func() {
- select {
- case wait <- nil:
- case <-wait:
- }
- }()
- return otto.UndefinedValue()
- case height = <-wait:
- }
- v, _ := call.Otto.ToValue(height.Uint64())
- return v
-}
-
-func (js *jsre) sleep(call otto.FunctionCall) otto.Value {
- sec, err := call.Argument(0).ToInteger()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- time.Sleep(time.Duration(sec) * time.Second)
- return otto.UndefinedValue()
-}
-
-func (js *jsre) setSolc(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) != 1 {
- fmt.Println("needs 1 argument: admin.contractInfo.setSolc(solcPath)")
- return otto.FalseValue()
- }
- solcPath, err := call.Argument(0).ToString()
- if err != nil {
- return otto.FalseValue()
- }
- solc, err := js.xeth.SetSolc(solcPath)
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
- fmt.Println(solc.Info())
- return otto.TrueValue()
-}
-
-func (js *jsre) register(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) != 4 {
- fmt.Println("requires 4 arguments: admin.contractInfo.register(fromaddress, contractaddress, contract, filename)")
- return otto.UndefinedValue()
- }
- sender, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- address, err := call.Argument(1).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- raw, err := call.Argument(2).Export()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- jsonraw, err := json.Marshal(raw)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- var contract compiler.Contract
- err = json.Unmarshal(jsonraw, &contract)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- filename, err := call.Argument(3).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- contenthash, err := compiler.ExtractInfo(&contract, filename)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- // sender and contract address are passed as hex strings
- codeb := js.xeth.CodeAtBytes(address)
- codehash := common.BytesToHash(crypto.Sha3(codeb))
-
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- registry := resolver.New(js.xeth)
-
- _, err = registry.RegisterContentHash(common.HexToAddress(sender), codehash, contenthash)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
-
- v, _ := call.Otto.ToValue(contenthash.Hex())
- return v
-}
-
-func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) != 3 {
- fmt.Println("requires 3 arguments: admin.contractInfo.register(fromaddress, contenthash, filename)")
- return otto.FalseValue()
- }
- sender, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- contenthash, err := call.Argument(1).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- url, err := call.Argument(2).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- registry := resolver.New(js.xeth)
-
- _, err = registry.RegisterUrl(common.HexToAddress(sender), common.HexToHash(contenthash), url)
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- return otto.TrueValue()
-}
-
-func (js *jsre) getContractInfo(call otto.FunctionCall) otto.Value {
- if len(call.ArgumentList) != 1 {
- fmt.Println("requires 1 argument: admin.contractInfo.register(contractaddress)")
- return otto.FalseValue()
- }
- addr, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- infoDoc, err := natspec.FetchDocsForContract(addr, js.xeth, ds)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- var info compiler.ContractInfo
- err = json.Unmarshal(infoDoc, &info)
- if err != nil {
- fmt.Println(err)
- return otto.UndefinedValue()
- }
- v, _ := call.Otto.ToValue(info)
- return v
-}
-
-func (js *jsre) startNatSpec(call otto.FunctionCall) otto.Value {
- js.ethereum.NatSpec = true
- return otto.TrueValue()
-}
-
-func (js *jsre) stopNatSpec(call otto.FunctionCall) otto.Value {
- js.ethereum.NatSpec = false
- return otto.TrueValue()
-}
-
-func (js *jsre) newRegistry(call otto.FunctionCall) otto.Value {
-
- if len(call.ArgumentList) != 1 {
- fmt.Println("requires 1 argument: admin.contractInfo.newRegistry(adminaddress)")
- return otto.FalseValue()
- }
- addr, err := call.Argument(0).ToString()
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- registry := resolver.New(js.xeth)
- err = registry.CreateContracts(common.HexToAddress(addr))
- if err != nil {
- fmt.Println(err)
- return otto.FalseValue()
- }
-
- return otto.TrueValue()
-}
-
-// internal transaction type which will allow us to resend transactions using `eth.resend`
-type tx struct {
- tx *types.Transaction
-
- To string
- From string
- Nonce string
- Value string
- Data string
- GasLimit string
- GasPrice string
-}
-
-func newTx(t *types.Transaction) *tx {
- from, _ := t.From()
- var to string
- if t := t.To(); t != nil {
- to = t.Hex()
- }
-
- return &tx{
- tx: t,
- To: to,
- From: from.Hex(),
- Value: t.Amount.String(),
- Nonce: strconv.Itoa(int(t.Nonce())),
- Data: "0x" + common.Bytes2Hex(t.Data()),
- GasLimit: t.GasLimit.String(),
- GasPrice: t.GasPrice().String(),
- }
-}
diff --git a/cmd/geth/js.go b/cmd/geth/js.go
index 7e6e10ca9..01840ebd9 100644
--- a/cmd/geth/js.go
+++ b/cmd/geth/js.go
@@ -26,6 +26,8 @@ import (
"path/filepath"
"strings"
+ "sort"
+
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/docserver"
@@ -33,9 +35,13 @@ import (
"github.com/ethereum/go-ethereum/eth"
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/xeth"
"github.com/peterh/liner"
"github.com/robertkrimen/otto"
+ "github.com/ethereum/go-ethereum/rpc/shared"
)
type prompter interface {
@@ -70,10 +76,104 @@ type jsre struct {
ps1 string
atexit func()
corsDomain string
+ client comms.EthereumClient
prompter
}
-func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain, ipcpath string, interactive bool, f xeth.Frontend) *jsre {
+var (
+ loadedModulesMethods map[string][]string
+)
+
+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 newLightweightJSRE(libPath string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
+ js := &jsre{ps1: "> "}
+ js.wait = make(chan *big.Int)
+ js.client = client
+
+ if f == nil {
+ f = js
+ }
+
+ // update state in separare forever blocks
+ js.re = re.New(libPath)
+ if err := js.apiBindings(f); err != nil {
+ utils.Fatalf("Unable to initialize console - %v", err)
+ }
+
+ if !liner.TerminalSupported() || !interactive {
+ js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
+ } else {
+ lr := liner.NewLiner()
+ js.withHistory(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) })
+ lr.Close()
+ close(js.wait)
+ }
+ }
+ return js
+}
+
+func newJSRE(ethereum *eth.Ethereum, libPath, 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
@@ -82,10 +182,18 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain, ipcpath string, intera
}
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 {
+ clt.Initialize(api.Merge(offeredApis...))
+ }
+ }
+
// update state in separare forever blocks
js.re = re.New(libPath)
- js.apiBindings(ipcpath, f)
- js.adminBindings()
+ if err := js.apiBindings(f); err != nil {
+ utils.Fatalf("Unable to connect - %v", err)
+ }
if !liner.TerminalSupported() || !interactive {
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
@@ -93,6 +201,9 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain, ipcpath string, intera
lr := liner.NewLiner()
js.withHistory(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) })
@@ -103,11 +214,76 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain, ipcpath string, intera
return js
}
-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, ipcpath)
+func (self *jsre) loadAutoCompletion() {
+ if modules, err := self.supportedApis(); err == nil {
+ loadedModulesMethods = make(map[string][]string)
+ for module, _ := range modules {
+ loadedModulesMethods[module] = api.AutoCompletion[module]
+ }
+ }
+}
+
+func (self *jsre) batch(statement string) {
+ val, err := self.re.Run(statement)
+
+ if err != nil {
+ fmt.Printf("error: %v", err)
+ } else if val.IsDefined() && val.IsObject() {
+ obj, _ := self.re.Get("ret_result")
+ fmt.Printf("%v", obj)
+ } else if val.IsDefined() {
+ fmt.Printf("%v", val)
+ }
+
+ if self.atexit != nil {
+ self.atexit()
+ }
+
+ self.re.Stop(false)
+}
+
+// show summary of current geth instance
+func (self *jsre) welcome() {
+ 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()
+ + " " + new Date(lastBlockTimestamp).toLocaleTimeString() + ")");`)
+
+ if modules, err := self.supportedApis(); err == nil {
+ 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);`)
+ }
+}
+
+func (self *jsre) supportedApis() (map[string]string, error) {
+ return self.client.SupportedModules()
+}
+
+func (js *jsre) apiBindings(f xeth.Frontend) error {
+ apis, err := js.supportedApis()
+ if err != nil {
+ return err
+ }
+
+ apiNames := make([]string, 0, len(apis))
+ for a, _ := range apis {
+ apiNames = append(apiNames, a)
+ }
+
+ apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.ethereum)
+ if err != nil {
+ utils.Fatalf("Unable to determine supported api's: %v", err)
+ }
+ jeth := rpc.NewJeth(api.Merge(apiImpl...), js.re, js.client)
js.re.Set("jeth", struct{}{})
t, _ := js.re.Get("jeth")
jethObj := t.Object()
@@ -115,14 +291,14 @@ func (js *jsre) apiBindings(ipcpath string, f xeth.Frontend) {
jethObj.Set("send", jeth.Send)
jethObj.Set("sendAsync", jeth.Send)
- err := js.re.Compile("bignumber.js", re.BigNumber_JS)
+ 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 ethereum.js: %v", err)
+ utils.Fatalf("Error loading web3.js: %v", err)
}
_, err = js.re.Eval("var web3 = require('web3');")
@@ -134,17 +310,29 @@ func (js *jsre) apiBindings(ipcpath string, f xeth.Frontend) {
if err != nil {
utils.Fatalf("Error setting web3 provider: %v", err)
}
- _, err = js.re.Eval(`
-var eth = web3.eth;
-var shh = web3.shh;
-var db = web3.db;
-var net = web3.net;
- `)
+
+ // load only supported API's in javascript runtime
+ shortcuts := "var eth = web3.eth; "
+ for _, apiName := range apiNames {
+ if apiName == shared.Web3ApiName {
+ 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)
}
js.re.Eval(globalRegistrar + "registrar = GlobalRegistrar.at(\"" + globalRegistrarAddr + "\");")
+ return nil
}
var ds, _ = docserver.New("/")
@@ -234,7 +422,12 @@ func (self *jsre) interactive() {
}
func (self *jsre) withHistory(op func(*os.File)) {
- hist, err := os.OpenFile(filepath.Join(self.ethereum.DataDir, "history"), os.O_RDWR|os.O_CREATE, os.ModePerm)
+ datadir := common.DefaultDataDir()
+ if self.ethereum != nil {
+ datadir = self.ethereum.DataDir
+ }
+
+ 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)
return
diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go
index 20bde01f3..cfbe26bee 100644
--- a/cmd/geth/js_test.go
+++ b/cmd/geth/js_test.go
@@ -20,6 +20,8 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/rpc/comms"
+ "github.com/ethereum/go-ethereum/rpc/codec"
)
const (
@@ -105,7 +107,8 @@ 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)
+ client := comms.NewInProcClient(codec.JSON)
+ repl := newJSRE(ethereum, assetPath, "", client, false, tf)
tf.jsre = repl
return tmp, tf, ethereum
}
@@ -125,7 +128,7 @@ func TestNodeInfo(t *testing.T) {
defer ethereum.Stop()
defer os.RemoveAll(tmp)
want := `{"DiscPort":0,"IP":"0.0.0.0","ListenAddr":"","Name":"test","NodeID":"4cb2fc32924e94277bf94b5e4c983beedb2eabd5a0bc941db32202735c6625d020ca14a5963d1738af43b6ac0a711d61b1a06de931a499fe2aa0b1a132a902b5","NodeUrl":"enode://4cb2fc32924e94277bf94b5e4c983beedb2eabd5a0bc941db32202735c6625d020ca14a5963d1738af43b6ac0a711d61b1a06de931a499fe2aa0b1a132a902b5@0.0.0.0:0","TCPPort":0,"Td":"131072"}`
- checkEvalJSON(t, repl, `admin.nodeInfo()`, want)
+ checkEvalJSON(t, repl, `admin.nodeInfo`, want)
}
func TestAccounts(t *testing.T) {
@@ -139,7 +142,7 @@ func TestAccounts(t *testing.T) {
checkEvalJSON(t, repl, `eth.accounts`, `["`+testAddress+`"]`)
checkEvalJSON(t, repl, `eth.coinbase`, `"`+testAddress+`"`)
- val, err := repl.re.Run(`admin.newAccount("password")`)
+ val, err := repl.re.Run(`personal.newAccount("password")`)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
@@ -161,7 +164,7 @@ func TestBlockChain(t *testing.T) {
defer ethereum.Stop()
defer os.RemoveAll(tmp)
// get current block dump before export/import.
- val, err := repl.re.Run("JSON.stringify(admin.debug.dumpBlock())")
+ val, err := repl.re.Run("JSON.stringify(debug.dumpBlock(eth.blockNumber))")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
@@ -178,14 +181,14 @@ func TestBlockChain(t *testing.T) {
ethereum.ChainManager().Reset()
- checkEvalJSON(t, repl, `admin.export(`+tmpfileq+`)`, `true`)
+ checkEvalJSON(t, repl, `admin.exportChain(`+tmpfileq+`)`, `true`)
if _, err := os.Stat(tmpfile); err != nil {
t.Fatal(err)
}
// check import, verify that dumpBlock gives the same result.
- checkEvalJSON(t, repl, `admin.import(`+tmpfileq+`)`, `true`)
- checkEvalJSON(t, repl, `admin.debug.dumpBlock()`, beforeExport)
+ checkEvalJSON(t, repl, `admin.importChain(`+tmpfileq+`)`, `true`)
+ checkEvalJSON(t, repl, `debug.dumpBlock(eth.blockNumber)`, beforeExport)
}
func TestMining(t *testing.T) {
@@ -207,7 +210,7 @@ func TestRPC(t *testing.T) {
defer ethereum.Stop()
defer os.RemoveAll(tmp)
- checkEvalJSON(t, repl, `admin.startRPC("127.0.0.1", 5004)`, `true`)
+ checkEvalJSON(t, repl, `admin.startRPC("127.0.0.1", 5004, "*", "web3,eth,net")`, `true`)
}
func TestCheckTestAccountBalance(t *testing.T) {
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 89aae43e5..02ec63300 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -38,6 +38,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/rpc/codec"
+ "github.com/ethereum/go-ethereum/rpc/comms"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
)
@@ -202,6 +204,16 @@ nodes.
The Geth console is an interactive shell for the JavaScript runtime environment
which exposes a node admin interface as well as the Ðapp JavaScript API.
See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
+`},
+ {
+ Action: attach,
+ Name: "attach",
+ Usage: `Geth Console: interactive JavaScript environment (connect to node)`,
+ Description: `
+The Geth console is an interactive shell for the JavaScript runtime environment
+which exposes a node admin interface as well as the Ðapp JavaScript API.
+See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console.
+This command allows to open a console on a running geth node.
`,
},
{
@@ -239,9 +251,11 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.RPCEnabledFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
+ utils.RpcApiFlag,
utils.IPCDisabledFlag,
utils.IPCApiFlag,
utils.IPCPathFlag,
+ utils.ExecFlag,
utils.WhisperEnabledFlag,
utils.VMDebugFlag,
utils.ProtocolVersionFlag,
@@ -294,6 +308,44 @@ func run(ctx *cli.Context) {
ethereum.WaitForShutdown()
}
+func attach(ctx *cli.Context) {
+ // 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 client comms.EthereumClient
+ var err error
+ if ctx.Args().Present() {
+ client, err = comms.ClientFromEndpoint(ctx.Args().First(), codec.JSON)
+ } else {
+ cfg := comms.IpcConfig{
+ Endpoint: ctx.GlobalString(utils.IPCPathFlag.Name),
+ }
+ client, err = comms.NewIpcClient(cfg, codec.JSON)
+ }
+
+ if err != nil {
+ utils.Fatalf("Unable to attach to geth node - %v", err)
+ }
+
+ repl := newLightweightJSRE(
+ ctx.GlobalString(utils.JSpathFlag.Name),
+ client,
+ true,
+ nil)
+
+ if ctx.GlobalString(utils.ExecFlag.Name) != "" {
+ repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
+ } else {
+ repl.welcome()
+ repl.interactive()
+ }
+}
+
func console(ctx *cli.Context) {
// Wrap the standard output with a colorified stream (windows)
if isatty.IsTerminal(os.Stdout.Fd()) {
@@ -309,16 +361,24 @@ func console(ctx *cli.Context) {
utils.Fatalf("%v", err)
}
+ client := comms.NewInProcClient(codec.JSON)
+
startEth(ctx, ethereum)
repl := newJSRE(
ethereum,
- ctx.String(utils.JSpathFlag.Name),
+ ctx.GlobalString(utils.JSpathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
- utils.IpcSocketPath(ctx),
+ client,
true,
nil,
)
- repl.interactive()
+
+ if ctx.GlobalString(utils.ExecFlag.Name) != "" {
+ repl.batch(ctx.GlobalString(utils.ExecFlag.Name))
+ } else {
+ repl.welcome()
+ repl.interactive()
+ }
ethereum.Stop()
ethereum.WaitForShutdown()
@@ -331,12 +391,13 @@ func execJSFiles(ctx *cli.Context) {
utils.Fatalf("%v", err)
}
+ client := comms.NewInProcClient(codec.JSON)
startEth(ctx, ethereum)
repl := newJSRE(
ethereum,
- ctx.String(utils.JSpathFlag.Name),
+ ctx.GlobalString(utils.JSpathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
- utils.IpcSocketPath(ctx),
+ client,
false,
nil,
)
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 696dbd142..15a577a07 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -22,7 +22,6 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/p2p/nat"
- "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"
@@ -209,20 +208,29 @@ var (
Usage: "Domain on which to send Access-Control-Allow-Origin header",
Value: "",
}
+ RpcApiFlag = cli.StringFlag{
+ Name: "rpcapi",
+ Usage: "Specify the API's which are offered over the HTTP RPC interface",
+ Value: comms.DefaultHttpRpcApis,
+ }
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,
+ Usage: "Specify the API's which are offered over the IPC interface",
+ Value: comms.DefaultIpcApis,
}
IPCPathFlag = DirectoryFlag{
Name: "ipcpath",
Usage: "Filename for IPC socket/pipe",
Value: DirectoryString{common.DefaultIpcPath()},
}
+ ExecFlag = cli.StringFlag{
+ Name: "exec",
+ Usage: "Execute javascript statement (only in combination with console/attach)",
+ }
// Network Settings
MaxPeersFlag = cli.IntFlag{
Name: "maxpeers",
@@ -453,18 +461,25 @@ func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error {
return err
}
- return comms.StartIpc(config, codec, apis...)
+ return comms.StartIpc(config, codec, api.Merge(apis...))
}
func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error {
- config := rpc.RpcConfig{
+ config := comms.HttpConfig{
ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name),
ListenPort: uint(ctx.GlobalInt(RPCPortFlag.Name)),
CorsDomain: ctx.GlobalString(RPCCORSDomainFlag.Name),
}
xeth := xeth.New(eth, nil)
- return rpc.Start(xeth, config)
+ codec := codec.JSON
+
+ apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, eth)
+ if err != nil {
+ return err
+ }
+
+ return comms.StartHttp(config, codec, api.Merge(apis...))
}
func StartPProf(ctx *cli.Context) {