CLI:
- js subcommand for vm - console for Frontier console interactive REPL - jspath in cli - integrate jeth apiBindings
This commit is contained in:
parent
16ecb1e2ea
commit
7279a485c2
@ -20,18 +20,16 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethutil"
|
re "github.com/ethereum/go-ethereum/jsre"
|
||||||
"github.com/ethereum/go-ethereum/javascript"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/state"
|
|
||||||
"github.com/ethereum/go-ethereum/xeth"
|
"github.com/ethereum/go-ethereum/xeth"
|
||||||
"github.com/obscuren/otto"
|
|
||||||
"github.com/peterh/liner"
|
"github.com/peterh/liner"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -59,7 +57,7 @@ func (r dumbterm) PasswordPrompt(p string) (string, error) {
|
|||||||
func (r dumbterm) AppendHistory(string) {}
|
func (r dumbterm) AppendHistory(string) {}
|
||||||
|
|
||||||
type jsre struct {
|
type jsre struct {
|
||||||
re *javascript.JSRE
|
re *re.JSRE
|
||||||
ethereum *eth.Ethereum
|
ethereum *eth.Ethereum
|
||||||
xeth *xeth.XEth
|
xeth *xeth.XEth
|
||||||
ps1 string
|
ps1 string
|
||||||
@ -68,11 +66,11 @@ type jsre struct {
|
|||||||
prompter
|
prompter
|
||||||
}
|
}
|
||||||
|
|
||||||
func newJSRE(ethereum *eth.Ethereum) *jsre {
|
func newJSRE(ethereum *eth.Ethereum, libPath string) *jsre {
|
||||||
js := &jsre{ethereum: ethereum, ps1: "> "}
|
js := &jsre{ethereum: ethereum, ps1: "> "}
|
||||||
js.xeth = xeth.New(ethereum, js)
|
js.xeth = xeth.New(ethereum, js)
|
||||||
js.re = javascript.NewJSRE(js.xeth)
|
js.re = re.New(libPath)
|
||||||
js.initStdFuncs()
|
js.apiBindings()
|
||||||
|
|
||||||
if !liner.TerminalSupported() {
|
if !liner.TerminalSupported() {
|
||||||
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
|
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
|
||||||
@ -89,6 +87,49 @@ func newJSRE(ethereum *eth.Ethereum) *jsre {
|
|||||||
return js
|
return js
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (js *jsre) apiBindings() {
|
||||||
|
|
||||||
|
ethApi := rpc.NewEthereumApi(js.xeth, js.ethereum.DataDir)
|
||||||
|
js.re.Bind("jeth", rpc.NewJeth(ethApi, js.re.ToVal))
|
||||||
|
|
||||||
|
_, err := js.re.Eval(re.BigNumber_JS)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Error loading bignumber.js: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to declare a dummy setTimeout. Otto does not support it
|
||||||
|
_, err = js.re.Eval("setTimeout = function(cb, delay) {};")
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Error defining setTimeout: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = js.re.Eval(re.Ethereum_JS)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Error loading ethereum.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;
|
||||||
|
var shh = web3.shh;
|
||||||
|
var db = web3.db;
|
||||||
|
var net = web3.net;
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Error setting namespaces: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (self *jsre) ConfirmTransaction(tx *types.Transaction) bool {
|
func (self *jsre) ConfirmTransaction(tx *types.Transaction) bool {
|
||||||
p := fmt.Sprintf("Confirm Transaction %v\n[y/n] ", tx)
|
p := fmt.Sprintf("Confirm Transaction %v\n[y/n] ", tx)
|
||||||
answer, _ := self.Prompt(p)
|
answer, _ := self.Prompt(p)
|
||||||
@ -111,15 +152,7 @@ func (self *jsre) UnlockAccount(addr []byte) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *jsre) exec(filename string) error {
|
func (self *jsre) exec(filename string) error {
|
||||||
file, err := os.Open(filename)
|
if err := self.re.Exec(filename); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
content, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := self.re.Run(string(content)); err != nil {
|
|
||||||
return fmt.Errorf("Javascript Error: %v", err)
|
return fmt.Errorf("Javascript Error: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -193,102 +226,8 @@ func (self *jsre) setIndent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *jsre) printValue(v interface{}) {
|
func (self *jsre) printValue(v interface{}) {
|
||||||
method, _ := self.re.Vm.Get("prettyPrint")
|
val, err := self.re.PrettyPrint(v)
|
||||||
v, err := self.re.Vm.ToValue(v)
|
|
||||||
if err == nil {
|
|
||||||
val, err := method.Call(method, v)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Printf("%v", val)
|
fmt.Printf("%v", val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (self *jsre) 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 *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.StateDb())
|
|
||||||
|
|
||||||
v, _ := self.re.Vm.ToValue(statedb.RawDump())
|
|
||||||
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *jsre) stopMining(call otto.FunctionCall) otto.Value {
|
|
||||||
self.ethereum.StopMining()
|
|
||||||
return otto.TrueValue()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *jsre) startMining(call otto.FunctionCall) otto.Value {
|
|
||||||
if err := self.ethereum.StartMining(); err != nil {
|
|
||||||
return otto.FalseValue()
|
|
||||||
}
|
|
||||||
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) 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()
|
|
||||||
}
|
|
||||||
|
@ -89,16 +89,20 @@ Use "ethereum dump 0" to dump the genesis block.
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: runjs,
|
Action: console,
|
||||||
Name: "js",
|
Name: "console",
|
||||||
Usage: `interactive JavaScript console`,
|
Usage: `Ethereum Frontier Console: interactive JavaScript environment`,
|
||||||
Description: `
|
Description: `
|
||||||
In the console, you can use the eth object to interact
|
Frontier Console is an interactive shell for the Ethereum Frontier JavaScript runtime environment which exposes a node admin interface as well as the DAPP JavaScript API.
|
||||||
with the running ethereum stack. The API does not match
|
See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
|
||||||
ethereum.js.
|
`,
|
||||||
|
},
|
||||||
A JavaScript file can be provided as the argument. The
|
{
|
||||||
runtime will execute the file and exit.
|
Action: execJSFiles,
|
||||||
|
Name: "js",
|
||||||
|
Usage: `executes the given JavaScript files in the Ethereum Frontier JavaScript VM`,
|
||||||
|
Description: `
|
||||||
|
The Ethereum Frontier JavaScript VM exposes a node admin interface as well as the DAPP JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -116,6 +120,7 @@ runtime will execute the file and exit.
|
|||||||
utils.UnlockedAccountFlag,
|
utils.UnlockedAccountFlag,
|
||||||
utils.BootnodesFlag,
|
utils.BootnodesFlag,
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
|
utils.JSpathFlag,
|
||||||
utils.ListenPortFlag,
|
utils.ListenPortFlag,
|
||||||
utils.LogFileFlag,
|
utils.LogFileFlag,
|
||||||
utils.LogFormatFlag,
|
utils.LogFormatFlag,
|
||||||
@ -131,6 +136,7 @@ runtime will execute the file and exit.
|
|||||||
utils.RPCPortFlag,
|
utils.RPCPortFlag,
|
||||||
utils.UnencryptedKeysFlag,
|
utils.UnencryptedKeysFlag,
|
||||||
utils.VMDebugFlag,
|
utils.VMDebugFlag,
|
||||||
|
|
||||||
//utils.VMTypeFlag,
|
//utils.VMTypeFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +174,7 @@ func run(ctx *cli.Context) {
|
|||||||
ethereum.WaitForShutdown()
|
ethereum.WaitForShutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
func runjs(ctx *cli.Context) {
|
func console(ctx *cli.Context) {
|
||||||
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
||||||
ethereum, err := eth.New(cfg)
|
ethereum, err := eth.New(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -176,14 +182,26 @@ func runjs(ctx *cli.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startEth(ctx, ethereum)
|
startEth(ctx, ethereum)
|
||||||
repl := newJSRE(ethereum)
|
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name))
|
||||||
if len(ctx.Args()) == 0 {
|
|
||||||
repl.interactive()
|
repl.interactive()
|
||||||
} else {
|
|
||||||
|
ethereum.Stop()
|
||||||
|
ethereum.WaitForShutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
func execJSFiles(ctx *cli.Context) {
|
||||||
|
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
|
||||||
|
ethereum, err := eth.New(cfg)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
startEth(ctx, ethereum)
|
||||||
|
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name))
|
||||||
for _, file := range ctx.Args() {
|
for _, file := range ctx.Args() {
|
||||||
repl.exec(file)
|
repl.exec(file)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ethereum.Stop()
|
ethereum.Stop()
|
||||||
ethereum.WaitForShutdown()
|
ethereum.WaitForShutdown()
|
||||||
}
|
}
|
||||||
|
@ -163,6 +163,11 @@ var (
|
|||||||
Usage: "Port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
|
Usage: "Port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
|
||||||
Value: "any",
|
Value: "any",
|
||||||
}
|
}
|
||||||
|
JSpathFlag = cli.StringFlag{
|
||||||
|
Name: "jspath",
|
||||||
|
Usage: "JS library path to be used with console and js subcommands",
|
||||||
|
Value: ".",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetNAT(ctx *cli.Context) nat.Interface {
|
func GetNAT(ctx *cli.Context) nat.Interface {
|
||||||
|
Loading…
Reference in New Issue
Block a user