From 15f491e5007d1507f20d0edce36cc9c0bd5cbd37 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 4 Mar 2015 12:18:26 +0100 Subject: [PATCH] Clean up REPL --- cmd/ethereum/cmd.go | 51 +++++------- cmd/ethereum/flags.go | 1 + cmd/ethereum/main.go | 8 +- cmd/ethereum/repl/repl.go | 104 +++++++++++++++++++++++- eth/protocol.go | 3 +- javascript/javascript_runtime.go | 135 +++---------------------------- javascript/types.go | 5 +- 7 files changed, 141 insertions(+), 166 deletions(-) diff --git a/cmd/ethereum/cmd.go b/cmd/ethereum/cmd.go index 8ffd868ed..7bb7c3ef7 100644 --- a/cmd/ethereum/cmd.go +++ b/cmd/ethereum/cmd.go @@ -1,43 +1,31 @@ -/* - This file is part of go-ethereum +// 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 - 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 ( "io/ioutil" "os" - "github.com/ethereum/go-ethereum/cmd/ethereum/repl" - "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/javascript" + "github.com/ethereum/go-ethereum/xeth" ) -func InitJsConsole(ethereum *eth.Ethereum) { - repl := ethrepl.NewJSRepl(ethereum) - go repl.Start() - utils.RegisterInterrupt(func(os.Signal) { - repl.Stop() - }) -} - func ExecJsFile(ethereum *eth.Ethereum, InputFile string) { file, err := os.Open(InputFile) if err != nil { @@ -47,9 +35,6 @@ func ExecJsFile(ethereum *eth.Ethereum, InputFile string) { if err != nil { clilogger.Fatalln(err) } - re := javascript.NewJSRE(ethereum) - utils.RegisterInterrupt(func(os.Signal) { - re.Stop() - }) + re := javascript.NewJSRE(xeth.New(ethereum)) re.Run(string(content)) } diff --git a/cmd/ethereum/flags.go b/cmd/ethereum/flags.go index 0866ef3dd..a3004f503 100644 --- a/cmd/ethereum/flags.go +++ b/cmd/ethereum/flags.go @@ -120,6 +120,7 @@ func Init() { flag.BoolVar(&StartMining, "mine", false, "start mining") flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console") flag.BoolVar(&PrintVersion, "version", false, "prints version number") + flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads") // Network stuff var ( diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go index ff306b10f..b9e69f700 100644 --- a/cmd/ethereum/main.go +++ b/cmd/ethereum/main.go @@ -26,6 +26,7 @@ import ( "runtime" "time" + "github.com/ethereum/go-ethereum/cmd/ethereum/repl" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" @@ -137,7 +138,12 @@ func main() { } if StartJsConsole { - InitJsConsole(ethereum) + repl := ethrepl.NewJSRepl(ethereum) + repl.Start() + utils.RegisterInterrupt(func(os.Signal) { + repl.Stop() + }) + } else if len(InputFile) > 0 { ExecJsFile(ethereum, InputFile) } diff --git a/cmd/ethereum/repl/repl.go b/cmd/ethereum/repl/repl.go index 11b812617..ec1aa6918 100644 --- a/cmd/ethereum/repl/repl.go +++ b/cmd/ethereum/repl/repl.go @@ -24,10 +24,14 @@ import ( "os" "path" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/javascript" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/state" + "github.com/ethereum/go-ethereum/xeth" + "github.com/obscuren/otto" ) var repllogger = logger.NewLogger("REPL") @@ -38,7 +42,9 @@ type Repl interface { } type JSRepl struct { - re *javascript.JSRE + re *javascript.JSRE + ethereum *eth.Ethereum + xeth *xeth.XEth prompt string @@ -53,7 +59,11 @@ func NewJSRepl(ethereum *eth.Ethereum) *JSRepl { panic(err) } - return &JSRepl{re: javascript.NewJSRE(ethereum), prompt: "> ", history: hist} + xeth := xeth.New(ethereum) + repl := &JSRepl{re: javascript.NewJSRE(xeth), xeth: xeth, ethereum: ethereum, prompt: "> ", history: hist} + repl.initStdFuncs() + + return repl } func (self *JSRepl) Start() { @@ -80,7 +90,6 @@ func (self *JSRepl) Start() { func (self *JSRepl) Stop() { if self.running { self.running = false - self.re.Stop() repllogger.Infoln("exit JS Console") self.history.Close() } @@ -101,3 +110,92 @@ func (self *JSRepl) parseInput(code string) { self.PrintValue(value) } + +func (self *JSRepl) initStdFuncs() { + t, _ := self.re.Vm.Get("eth") + eth := t.Object() + eth.Set("connect", self.connect) + eth.Set("stopMining", self.stopMining) + eth.Set("startMining", self.startMining) + eth.Set("dump", self.dump) + eth.Set("export", self.export) +} + +/* + * The following methods are natively implemented javascript functions + */ + +func (self *JSRepl) dump(call otto.FunctionCall) otto.Value { + var block *types.Block + + if len(call.ArgumentList) > 0 { + if call.Argument(0).IsNumber() { + num, _ := call.Argument(0).ToInteger() + block = self.ethereum.ChainManager().GetBlockByNumber(uint64(num)) + } else if call.Argument(0).IsString() { + hash, _ := call.Argument(0).ToString() + block = self.ethereum.ChainManager().GetBlock(ethutil.Hex2Bytes(hash)) + } else { + fmt.Println("invalid argument for dump. Either hex string or number") + } + + if block == nil { + fmt.Println("block not found") + + return otto.UndefinedValue() + } + + } else { + block = self.ethereum.ChainManager().CurrentBlock() + } + + statedb := state.New(block.Root(), self.ethereum.Db()) + + v, _ := self.re.Vm.ToValue(statedb.RawDump()) + + return v +} + +func (self *JSRepl) stopMining(call otto.FunctionCall) otto.Value { + self.xeth.Miner().Stop() + + return otto.TrueValue() +} + +func (self *JSRepl) startMining(call otto.FunctionCall) otto.Value { + self.xeth.Miner().Start() + return otto.TrueValue() +} + +func (self *JSRepl) connect(call otto.FunctionCall) otto.Value { + nodeURL, err := call.Argument(0).ToString() + if err != nil { + return otto.FalseValue() + } + if err := self.ethereum.SuggestPeer(nodeURL); err != nil { + return otto.FalseValue() + } + return otto.TrueValue() +} + +func (self *JSRepl) export(call otto.FunctionCall) otto.Value { + if len(call.ArgumentList) == 0 { + fmt.Println("err: require file name") + return otto.FalseValue() + } + + fn, err := call.Argument(0).ToString() + if err != nil { + fmt.Println(err) + return otto.FalseValue() + } + + data := self.ethereum.ChainManager().Export() + + if err := ethutil.WriteFile(fn, data); err != nil { + fmt.Println(err) + return otto.FalseValue() + } + + return otto.TrueValue() +} diff --git a/eth/protocol.go b/eth/protocol.go index d394ba739..663af43fe 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -15,7 +15,7 @@ import ( ) const ( - ProtocolVersion = 55 + ProtocolVersion = 56 NetworkId = 0 ProtocolLength = uint64(8) ProtocolMaxMsgSize = 10 * 1024 * 1024 @@ -250,6 +250,7 @@ func (self *ethProtocol) handle() error { return self.protoError(ErrDecode, "msg %v: %v", msg, err) } hash := request.Block.Hash() + fmt.Println("received block: %x", hash) _, chainHead, _ := self.chainManager.Status() jsonlogger.LogJson(&logger.EthChainReceivedNewBlock{ diff --git a/javascript/javascript_runtime.go b/javascript/javascript_runtime.go index 893ad5d33..36b14a057 100644 --- a/javascript/javascript_runtime.go +++ b/javascript/javascript_runtime.go @@ -6,14 +6,7 @@ import ( "os" "path" "path/filepath" - - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/ethutil" - "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/xeth" "github.com/obscuren/otto" ) @@ -21,11 +14,8 @@ import ( var jsrelogger = logger.NewLogger("JSRE") type JSRE struct { - ethereum *eth.Ethereum - Vm *otto.Otto - xeth *xeth.XEth - - events event.Subscription + Vm *otto.Otto + xeth *xeth.XEth objectCb map[string][]otto.Value } @@ -44,12 +34,10 @@ func (jsre *JSRE) LoadIntFile(file string) { jsre.LoadExtFile(path.Join(assetPath, file)) } -func NewJSRE(ethereum *eth.Ethereum) *JSRE { +func NewJSRE(xeth *xeth.XEth) *JSRE { re := &JSRE{ - ethereum, otto.New(), - xeth.New(ethereum), - nil, + xeth, make(map[string][]otto.Value), } @@ -59,14 +47,7 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE { // Load extra javascript files re.LoadIntFile("bignumber.min.js") - // Subscribe to events - mux := ethereum.EventMux() - re.events = mux.Subscribe(core.NewBlockEvent{}) - - // We have to make sure that, whoever calls this, calls "Stop" - go re.mainLoop() - - re.Bind("eth", &JSEthereum{re.xeth, re.Vm, ethereum}) + re.Bind("eth", &JSEthereum{re.xeth, re.Vm}) re.initStdFuncs() @@ -83,6 +64,12 @@ func (self *JSRE) Run(code string) (otto.Value, error) { return self.Vm.Run(code) } +func (self *JSRE) initStdFuncs() { + t, _ := self.Vm.Get("eth") + eth := t.Object() + eth.Set("require", self.require) +} + func (self *JSRE) Require(file string) error { if len(filepath.Ext(file)) == 0 { file += ".js" @@ -99,84 +86,6 @@ func (self *JSRE) Require(file string) error { return nil } -func (self *JSRE) Stop() { - self.events.Unsubscribe() - jsrelogger.Infoln("stopped") -} - -func (self *JSRE) mainLoop() { - for _ = range self.events.Chan() { - } -} - -func (self *JSRE) initStdFuncs() { - t, _ := self.Vm.Get("eth") - eth := t.Object() - eth.Set("connect", self.connect) - eth.Set("require", self.require) - eth.Set("stopMining", self.stopMining) - eth.Set("startMining", self.startMining) - eth.Set("dump", self.dump) - eth.Set("export", self.export) -} - -/* - * The following methods are natively implemented javascript functions - */ - -func (self *JSRE) dump(call otto.FunctionCall) otto.Value { - var block *types.Block - - if len(call.ArgumentList) > 0 { - if call.Argument(0).IsNumber() { - num, _ := call.Argument(0).ToInteger() - block = self.ethereum.ChainManager().GetBlockByNumber(uint64(num)) - } else if call.Argument(0).IsString() { - hash, _ := call.Argument(0).ToString() - block = self.ethereum.ChainManager().GetBlock(ethutil.Hex2Bytes(hash)) - } else { - fmt.Println("invalid argument for dump. Either hex string or number") - } - - if block == nil { - fmt.Println("block not found") - - return otto.UndefinedValue() - } - - } else { - block = self.ethereum.ChainManager().CurrentBlock() - } - - statedb := state.New(block.Root(), self.ethereum.Db()) - - v, _ := self.Vm.ToValue(statedb.RawDump()) - - return v -} - -func (self *JSRE) stopMining(call otto.FunctionCall) otto.Value { - self.xeth.Miner().Stop() - - return otto.TrueValue() -} - -func (self *JSRE) startMining(call otto.FunctionCall) otto.Value { - self.xeth.Miner().Start() - return otto.TrueValue() -} - -func (self *JSRE) connect(call otto.FunctionCall) otto.Value { - nodeURL, err := call.Argument(0).ToString() - if err != nil { - return otto.FalseValue() - } - if err := self.ethereum.SuggestPeer(nodeURL); err != nil { - return otto.FalseValue() - } - return otto.TrueValue() -} - func (self *JSRE) require(call otto.FunctionCall) otto.Value { file, err := call.Argument(0).ToString() if err != nil { @@ -191,25 +100,3 @@ func (self *JSRE) require(call otto.FunctionCall) otto.Value { return t } - -func (self *JSRE) export(call otto.FunctionCall) otto.Value { - if len(call.ArgumentList) == 0 { - fmt.Println("err: require file name") - return otto.FalseValue() - } - - fn, err := call.Argument(0).ToString() - if err != nil { - fmt.Println(err) - return otto.FalseValue() - } - - data := self.ethereum.ChainManager().Export() - - if err := ethutil.WriteFile(fn, data); err != nil { - fmt.Println(err) - return otto.FalseValue() - } - - return otto.TrueValue() -} diff --git a/javascript/types.go b/javascript/types.go index b4da160fc..77e209d19 100644 --- a/javascript/types.go +++ b/javascript/types.go @@ -2,8 +2,6 @@ package javascript import ( "fmt" - - "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/xeth" @@ -55,8 +53,7 @@ func NewJSLog(log state.Log) JSLog { type JSEthereum struct { *xeth.XEth - vm *otto.Otto - ethereum *eth.Ethereum + vm *otto.Otto } func (self *JSEthereum) Block(v interface{}) otto.Value {