Merge branch 'develop' into conversion

This commit is contained in:
obscuren committed 2015-03-17 21:40:05 +01:00
commit 142e81258c
29 files changed
+1198 -506

No files matched your search

+259
View File
@@ -0,0 +1,259 @@
package main
import (
"fmt"
"net"
"net/http"
"os"
"time"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/otto"
)
/*
node admin bindings
*/
func (js *jsre) adminBindings() {
js.re.Set("admin", struct{}{})
t, _ := js.re.Get("admin")
admin := t.Object()
admin.Set("suggestPeer", js.suggestPeer)
admin.Set("startRPC", js.startRPC)
admin.Set("startMining", js.startMining)
admin.Set("stopMining", js.stopMining)
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("dumpBlock", js.dumpBlock)
}
func (js *jsre) startMining(call otto.FunctionCall) otto.Value {
_, err := call.Argument(0).ToInteger()
if err != nil {
fmt.Println(err)
return otto.FalseValue()
}
// threads now ignored
err = js.ethereum.StartMining()
if err != nil {
fmt.Println(err)
return otto.FalseValue()
}
return otto.TrueValue()
}
func (js *jsre) stopMining(call otto.FunctionCall) otto.Value {
js.ethereum.StopMining()
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()
}
dataDir := js.ethereum.DataDir
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
if err != nil {
fmt.Printf("Can't listen on %s:%d: %v", addr, port, err)
return otto.FalseValue()
}
go http.Serve(l, rpc.JSONRPC(xeth.New(js.ethereum, nil), dataDir))
return otto.TrueValue()
}
func (js *jsre) suggestPeer(call otto.FunctionCall) otto.Value {
nodeURL, err := call.Argument(0).ToString()
if err != nil {
fmt.Println(err)
return otto.FalseValue()
}
err = js.ethereum.SuggestPeer(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()
}
arg := call.Argument(1)
var passphrase string
if arg.IsUndefined() {
fmt.Println("Please enter a passphrase now.")
passphrase, err = readPassword("Passphrase: ", true)
if err != nil {
utils.Fatalf("%v", err)
}
} else {
passphrase, err = arg.ToString()
if err != nil {
fmt.Println(err)
return otto.FalseValue()
}
}
am := js.ethereum.AccountManager()
// err := am.Unlock(common.FromHex(split[0]), split[1])
// if err != nil {
// utils.Fatalf("Unlock account failed '%v'", err)
// }
err = am.TimedUnlock(common.FromHex(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 := readPassword("Passphrase: ", true)
if err != nil {
utils.Fatalf("%v", err)
}
confirm, err := readPassword("Repeat Passphrase: ", false)
if err != nil {
utils.Fatalf("%v", err)
}
if auth != confirm {
utils.Fatalf("Passphrases did not match.")
}
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()
}
return js.re.ToVal(common.Bytes2Hex(acct.Address))
}
func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value {
return js.re.ToVal(js.ethereum.NodeInfo())
}
func (js *jsre) peers(call otto.FunctionCall) otto.Value {
return js.re.ToVal(js.ethereum.PeersInfo())
}
func (js *jsre) importChain(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()
}
var fh *os.File
fh, err = os.OpenFile(fn, os.O_RDONLY, os.ModePerm)
if err != nil {
fmt.Println(err)
return otto.FalseValue()
}
defer fh.Close()
var blocks types.Blocks
if err = rlp.Decode(fh, &blocks); err != nil {
fmt.Println(err)
return otto.FalseValue()
}
js.ethereum.ChainManager().Reset()
if err = js.ethereum.ChainManager().InsertChain(blocks); err != nil {
fmt.Println(err)
return otto.FalseValue()
}
return otto.TrueValue()
}
func (js *jsre) exportChain(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 := js.ethereum.ChainManager().Export()
if err := common.WriteFile(fn, data); err != nil {
fmt.Println(err)
return otto.FalseValue()
}
return otto.TrueValue()
}
func (js *jsre) dumpBlock(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 = js.ethereum.ChainManager().GetBlockByNumber(uint64(num))
} else if call.Argument(0).IsString() {
hash, _ := call.Argument(0).ToString()
block = js.ethereum.ChainManager().GetBlock(common.Hex2Bytes(hash))
} else {
fmt.Println("invalid argument for dump. Either hex string or number")
}
} else {
block = js.ethereum.ChainManager().CurrentBlock()
}
if block == nil {
fmt.Println("block not found")
return otto.UndefinedValue()
}
statedb := state.New(block.Root(), js.ethereum.StateDb())
dump := statedb.RawDump()
return js.re.ToVal(dump)
}
+54 -114
View File
@@ -20,18 +20,16 @@ package main
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"path"
"strings"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/javascript"
"github.com/ethereum/go-ethereum/state"
re "github.com/ethereum/go-ethereum/jsre"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/otto"
"github.com/peterh/liner"
)
@@ -59,7 +57,7 @@ func (r dumbterm) PasswordPrompt(p string) (string, error) {
func (r dumbterm) AppendHistory(string) {}
type jsre struct {
re *javascript.JSRE
re *re.JSRE
ethereum *eth.Ethereum
xeth *xeth.XEth
ps1 string
@@ -68,11 +66,12 @@ type jsre struct {
prompter
}
func newJSRE(ethereum *eth.Ethereum) *jsre {
func newJSRE(ethereum *eth.Ethereum, libPath string) *jsre {
js := &jsre{ethereum: ethereum, ps1: "> "}
js.xeth = xeth.New(ethereum, js)
js.re = javascript.NewJSRE(js.xeth)
js.initStdFuncs()
js.re = re.New(libPath)
js.apiBindings()
js.adminBindings()
if !liner.TerminalSupported() {
js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
@@ -89,6 +88,49 @@ func newJSRE(ethereum *eth.Ethereum) *jsre {
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 {
p := fmt.Sprintf("Confirm Transaction %v\n[y/n] ", tx)
answer, _ := self.Prompt(p)
@@ -111,15 +153,7 @@ func (self *jsre) UnlockAccount(addr []byte) bool {
}
func (self *jsre) exec(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
content, err := ioutil.ReadAll(file)
if err != nil {
return err
}
if _, err := self.re.Run(string(content)); err != nil {
if err := self.re.Exec(filename); err != nil {
return fmt.Errorf("Javascript Error: %v", err)
}
return nil
@@ -193,102 +227,8 @@ func (self *jsre) setIndent() {
}
func (self *jsre) printValue(v interface{}) {
method, _ := self.re.Vm.Get("prettyPrint")
v, err := self.re.Vm.ToValue(v)
val, err := self.re.PrettyPrint(v)
if err == nil {
val, err := method.Call(method, v)
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(common.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 := common.WriteFile(fn, data); err != nil {
fmt.Println(err)
return otto.FalseValue()
}
return otto.TrueValue()
}
+252
View File
@@ -0,0 +1,252 @@
package main
import (
"fmt"
"github.com/obscuren/otto"
"os"
"path"
"testing"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
)
var port = 30300
func testJEthRE(t *testing.T) (repl *jsre, ethereum *eth.Ethereum, err error) {
os.RemoveAll("/tmp/eth/")
err = os.MkdirAll("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/", os.ModePerm)
if err != nil {
t.Errorf("%v", err)
return
}
err = os.MkdirAll("/tmp/eth/data", os.ModePerm)
if err != nil {
t.Errorf("%v", err)
return
}
// FIXME: this does not work ATM
ks := crypto.NewKeyStorePlain("/tmp/eth/keys")
common.WriteFile("/tmp/eth/keys/e273f01c99144c438695e10f24926dc1f9fbf62d/e273f01c99144c438695e10f24926dc1f9fbf62d",
[]byte(`{"Id":"RhRXD+fNRKS4jx+7ZfEsNA==","Address":"4nPwHJkUTEOGleEPJJJtwfn79i0=","PrivateKey":"h4ACVpe74uIvi5Cg/2tX/Yrm2xdr3J7QoMbMtNX2CNc="}`))
port++
ethereum, err = eth.New(&eth.Config{
DataDir: "/tmp/eth",
AccountManager: accounts.NewManager(ks),
Port: fmt.Sprintf("%d", port),
MaxPeers: 10,
Name: "test",
})
if err != nil {
t.Errorf("%v", err)
return
}
assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
repl = newJSRE(ethereum, assetPath)
return
}
func TestNodeInfo(t *testing.T) {
repl, ethereum, err := testJEthRE(t)
if err != nil {
t.Errorf("error creating jsre, got %v", err)
return
}
err = ethereum.Start()
if err != nil {
t.Errorf("error starting ethereum: %v", err)
return
}
defer ethereum.Stop()
val, err := repl.re.Run("admin.nodeInfo()")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
exp, err := val.Export()
if err != nil {
t.Errorf("expected no error, got %v", err)
}
nodeInfo, ok := exp.(*eth.NodeInfo)
if !ok {
t.Errorf("expected nodeInfo, got %v", err)
}
exp = "test"
got := nodeInfo.Name
if exp != got {
t.Errorf("expected %v, got %v", exp, got)
}
exp = 30301
port := nodeInfo.DiscPort
if exp != port {
t.Errorf("expected %v, got %v", exp, port)
}
exp = 30301
port = nodeInfo.TCPPort
if exp != port {
t.Errorf("expected %v, got %v", exp, port)
}
}
func TestAccounts(t *testing.T) {
repl, ethereum, err := testJEthRE(t)
if err != nil {
t.Errorf("error creating jsre, got %v", err)
return
}
err = ethereum.Start()
if err != nil {
t.Errorf("error starting ethereum: %v", err)
return
}
defer ethereum.Stop()
val, err := repl.re.Run("eth.coinbase")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
pp, err := repl.re.PrettyPrint(val)
if err != nil {
t.Errorf("%v", err)
}
if !val.IsString() {
t.Errorf("incorrect type, expected string, got %v: %v", val, pp)
}
strVal, _ := val.ToString()
expected := "0xe273f01c99144c438695e10f24926dc1f9fbf62d"
if strVal != expected {
t.Errorf("incorrect result, expected %s, got %v", expected, strVal)
}
val, err = repl.re.Run(`admin.newAccount("password")`)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
addr, err := val.ToString()
if err != nil {
t.Errorf("expected string, got %v", err)
}
val, err = repl.re.Run("eth.accounts")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
exp, err := val.Export()
if err != nil {
t.Errorf("expected no error, got %v", err)
}
addrs, ok := exp.([]string)
if !ok {
t.Errorf("expected []string, got %v", err)
}
if len(addrs) != 2 || (addr != addrs[0][2:] && addr != addrs[1][2:]) {
t.Errorf("expected addrs == [<default>, <new>], got %v (%v)", addrs, addr)
}
}
func TestBlockChain(t *testing.T) {
repl, ethereum, err := testJEthRE(t)
if err != nil {
t.Errorf("error creating jsre, got %v", err)
return
}
err = ethereum.Start()
if err != nil {
t.Errorf("error starting ethereum: %v", err)
return
}
defer ethereum.Stop()
// should get current block
val0, err := repl.re.Run("admin.dumpBlock()")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
fn := "/tmp/eth/data/blockchain.0"
_, err = repl.re.Run("admin.export(\"" + fn + "\")")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
if _, err = os.Stat(fn); err != nil {
t.Errorf("expected no error on file, got %v", err)
}
_, err = repl.re.Run("admin.import(\"" + fn + "\")")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
var val1 otto.Value
// should get current block
val1, err = repl.re.Run("admin.dumpBlock()")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
// FIXME: neither != , nor reflect.DeepEqual works, doing string comparison
v0 := fmt.Sprintf("%v", val0)
v1 := fmt.Sprintf("%v", val1)
if v0 != v1 {
t.Errorf("expected same head after export-import, got %v (!=%v)", v1, v0)
}
}
func TestMining(t *testing.T) {
repl, ethereum, err := testJEthRE(t)
if err != nil {
t.Errorf("error creating jsre, got %v", err)
return
}
err = ethereum.Start()
if err != nil {
t.Errorf("error starting ethereum: %v", err)
return
}
defer ethereum.Stop()
val, err := repl.re.Run("eth.mining")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
var mining bool
mining, err = val.ToBoolean()
if err != nil {
t.Errorf("expected boolean, got %v", err)
}
if mining {
t.Errorf("expected false (not mining), got true")
}
}
func TestRPC(t *testing.T) {
repl, ethereum, err := testJEthRE(t)
if err != nil {
t.Errorf("error creating jsre, got %v", err)
return
}
err = ethereum.Start()
if err != nil {
t.Errorf("error starting ethereum: %v", err)
return
}
defer ethereum.Stop()
val, err := repl.re.Run(`admin.startRPC("127.0.0.1", 5004)`)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
success, _ := val.ToBoolean()
if !success {
t.Errorf("expected true (started), got false")
}
}
+37 -19
View File
@@ -31,9 +31,9 @@ import (
"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
"github.com/peterh/liner"
@@ -41,7 +41,7 @@ import (
const (
ClientIdentifier = "Ethereum(G)"
Version = "0.9.0"
Version = "0.9.1"
)
var (
@@ -89,16 +89,20 @@ Use "ethereum dump 0" to dump the genesis block.
`,
},
{
Action: runjs,
Name: "js",
Usage: `interactive JavaScript console`,
Action: console,
Name: "console",
Usage: `Ethereum Console: interactive JavaScript environment`,
Description: `
In the console, you can use the eth object to interact
with the running ethereum stack. The API does not match
ethereum.js.
A JavaScript file can be provided as the argument. The
runtime will execute the file and exit.
Console is an interactive shell for the Ethereum JavaScript runtime environment which exposes a node admin interface as well as the DAPP JavaScript API.
See https://github.com/ethereum/go-ethereum/wiki/Frontier-Console
`,
},
{
Action: execJSFiles,
Name: "js",
Usage: `executes the given JavaScript files in the Ethereum Frontier JavaScript VM`,
Description: `
The Ethereum 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.BootnodesFlag,
utils.DataDirFlag,
utils.JSpathFlag,
utils.ListenPortFlag,
utils.LogFileFlag,
utils.LogFormatFlag,
@@ -131,6 +136,7 @@ runtime will execute the file and exit.
utils.RPCPortFlag,
utils.UnencryptedKeysFlag,
utils.VMDebugFlag,
//utils.VMTypeFlag,
}
@@ -168,7 +174,7 @@ func run(ctx *cli.Context) {
ethereum.WaitForShutdown()
}
func runjs(ctx *cli.Context) {
func console(ctx *cli.Context) {
cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
ethereum, err := eth.New(cfg)
if err != nil {
@@ -176,14 +182,26 @@ func runjs(ctx *cli.Context) {
}
startEth(ctx, ethereum)
repl := newJSRE(ethereum)
if len(ctx.Args()) == 0 {
repl.interactive()
} else {
for _, file := range ctx.Args() {
repl.exec(file)
}
repl := newJSRE(ethereum, ctx.String(utils.JSpathFlag.Name))
repl.interactive()
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() {
repl.exec(file)
}
ethereum.Stop()
ethereum.WaitForShutdown()
}
+4 -2
View File
@@ -1,2 +1,4 @@
/*! bignumber.js v2.0.0 https://github.com/MikeMcl/bignumber.js/LICENCE */
(function(n){"use strict";function t(n,i){var b,a,l,p,o,w,s=this;if(!(s instanceof t))return new t(n,i);if(n instanceof t){if(i==null){u=0;s.s=n.s;s.e=n.e;s.c=(n=n.c)?n.slice():n;return}n+=""}else if(p=(o=typeof n)=="number"){if(i==null&&n===~~n){for(s.s=1/n<0?(n=-n,-1):1,a=u=0,l=n;l>=10;l/=10,a++);s.e=a;s.c=[n];return}n=n===0&&1/n<0?"-0":n+""}else o!="string"&&(n+="");if(o=n,i==null&&ft.test(o))s.s=o.charCodeAt(0)===45?(o=o.slice(1),-1):1;else{if(i==10)return s=new t(o),y(s,c+s.e+1,h);if(o=lt.call(o).replace(/^\+(?!-)/,""),s.s=o.charCodeAt(0)===45?(o=o.replace(/^-(?!-)/,""),-1):1,i!=null?i!=~~i&&d||(e=!(i>=2&&i<65))?(f(i,2),w=ft.test(o)):(b="["+ut.slice(0,i=i|0)+"]+",o=o.replace(/\.$/,"").replace(/^\./,"0."),(w=new RegExp("^"+b+"(?:\\."+b+")?$",i<37?"i":"").test(o))?(p&&(o.replace(/^0\.0*|\./,"").length>15&&f(n,0),p=!p),o=ct(o,10,i,s.s)):o!="Infinity"&&o!="NaN"&&(f(n,1,i),n="NaN")):w=ft.test(o),!w){s.c=s.e=null;o!="Infinity"&&(o!="NaN"&&f(n,3),s.s=null);u=0;return}}for((a=o.indexOf("."))>-1&&(o=o.replace(".","")),(l=o.search(/e/i))>0?(a<0&&(a=l),a+=+o.slice(l+1),o=o.substring(0,l)):a<0&&(a=o.length),l=0;o.charCodeAt(l)===48;l++);for(i=o.length;o.charCodeAt(--i)===48;);if(o=o.slice(l,i+1),o)if(i=o.length,p&&i>15&&f(n,0),a=a-l-1,a>v)s.c=s.e=null;else if(a<nt)s.c=[s.e=0];else{if(s.e=a,s.c=[],l=(a+1)%r,a<0&&(l+=r),l<i){for(l&&s.c.push(+o.slice(0,l)),i-=r;l<i;s.c.push(+o.slice(l,l+=r)));o=o.slice(l);l=r-o.length}else l-=i;for(;l--;o+="0");s.c.push(+o)}else s.c=[s.e=0];u=0}function et(n,t,i){for(var f=1,u=t.length;!t[--u];t.pop());for(u=t[0];u>=10;u/=10,f++);return(i=f+i*r-1)>v?n.c=n.e=null:i<nt?n.c=[n.e=0]:(n.e=i,n.c=t),n}function tt(n){for(var t,f,e=1,i=n.length,u=n[0]+"";e<i;){for(t=n[e++]+"",f=r-t.length;f--;t="0"+t);u+=t}for(i=u.length;u.charCodeAt(--i)===48;);return u.slice(0,i+1||1)}function ht(n,t,i){for(var u,r=[0],f,e=0,o=n.length;e<o;){for(f=r.length;f--;r[f]*=t);for(r[u=0]+=ut.indexOf(n.charAt(e++));u<r.length;u++)r[u]>i-1&&(r[u+1]==null&&(r[u+1]=0),r[u+1]+=r[u]/i|0,r[u]%=i)}return r.reverse()}function ct(n,i,r,u){var l,e,v,y,s,f,w,o=n.indexOf("."),p=h;for(r<37&&(n=n.toLowerCase()),o>=0&&(n=n.replace(".",""),w=new t(r),s=w.pow(n.length-o),w.c=ht(s.toFixed(),10,i),w.e=w.c.length),f=ht(n,r,i),e=v=f.length;f[--v]==0;f.pop());if(!f[0])return"0";if(o<0?--e:(s.c=f,s.e=e,s.s=u,s=a(s,w,c,p,i),f=s.c,y=s.r,e=s.e),l=e+c+1,o=f[l],v=i/2,y=y||l<0||f[l+1]!=null,y=p<4?(o!=null||y)&&(p==0||p==(s.s<0?3:2)):o>v||o==v&&(p==4||y||p==6&&f[l-1]&1||p==(s.s<0?8:7)),l<1||!f[0])f.length=1,v=0,y?(f[0]=1,e=-c):e=f[0]=0;else{if(f.length=l,y)for(--i;++f[--l]>i;)f[l]=0,l||(++e,f.unshift(1));for(v=f.length;!f[--v];);}for(o=0,n="";o<=v;n+=ut.charAt(f[o++]));if(e<0){for(;++e;n="0"+n);n="0."+n}else if(o=n.length,++e>o)for(e-=o;e--;n+="0");else e<o&&(n=n.slice(0,e)+"."+n.slice(e));return n}function rt(n,i,r){var o,u,e,f=(n=new t(n)).e;if(i==null?o=0:(y(n,++i,h),o=r?i:i+n.e-f,f=n.e),u=tt(n.c),r==1||r==2&&(i<=f||f<=p)){for(;u.length<o;u+="0");u.length>1&&(u=u.charAt(0)+"."+u.slice(1));u+=(f<0?"e":"e+")+f}else{if(r=u.length,f<0){for(e=o-r;++f;u="0"+u);u="0."+u}else if(++f>r){for(e=o-f,f-=r;f--;u+="0");e>0&&(u+=".")}else e=o-r,f<r?u=u.slice(0,f)+"."+u.slice(f):e>0&&(u+=".");if(e>0)for(;e--;u+="0");}return n.s<0&&n.c[0]?"-"+u:u}function f(n,t,i,r,f,o){if(d){var c,s=["new BigNumber","cmp","div","eq","gt","gte","lt","lte","minus","mod","plus","times","toFraction","divToInt"][u?u<0?-u:u:1/u<0?1:0]+"()",h=e?" out of range":" not a"+(f?" non-zero":"n")+" integer";h=([s+" number type has more than 15 significant digits",s+" not a base "+i+" number",s+" base"+h,s+" not a number"][t]||i+"() "+t+(o?" not a boolean or binary digit":h+(r?" or not ["+(e?" negative, positive":" integer, integer")+" ]":"")))+": "+n;e=u=0;c=new Error(h);c.name="BigNumber Error";throw c;}}function y(n,t,i,u){var c,o,e,s,a,h,p,f,y=st;if(f=n.c){n:{for(c=1,s=f[0];s>=10;s/=10,c++);if(o=t-c,o<0)o+=r,e=t,a=f[h=0],p=a/y[c-e-1]%10|0;else if(h=Math.ceil((o+1)/r),h>=f.length)if(u){for(;f.length<=h;f.push(0));a=p=0;c=1;o%=r;e=o-r+1}else break n;else{for(a=s=f[h],c=1;s>=10;s/=10,c++);o%=r;e=o-r+c;p=e<0?0:a/y[c-e-1]%10|0}if(u=u||t<0||f[h+1]!=null||(e<0?a:a%y[c-e-1]),u=i<4?(p||u)&&(i==0||i==(n.s<0?3:2)):p>5||p==5&&(i==4||u||i==6&&(o>0?e>0?a/y[c-e]:0:f[h-1])%10&1||i==(n.s<0?8:7)),t<1||!f[0])return f.length=0,u?(t-=n.e+1,f[0]=y[t%r],n.e=-t||0):f[0]=n.e=0,n;if(o==0?(f.length=h,s=1,h--):(f.length=h+1,s=y[r-o],f[h]=e>0?g(a/y[c-e]%y[e])*s:0),u)for(;;)if(h==0){for(o=1,e=f[0];e>=10;e/=10,o++);for(e=f[0]+=s,s=1;e>=10;e/=10,s++);o!=s&&(n.e++,f[0]==l&&(f[0]=1));break}else{if(f[h]+=s,f[h]!=l)break;f[h--]=0;s=1}for(o=f.length;f[--o]===0;f.pop());}n.e>v?n.c=n.e=null:n.e<nt&&(n.c=[n.e=0])}return n}var o=1e9,ot=1e6,c=20,h=4,p=-7,k=21,nt=-o,v=o,d=!0,w=parseInt,b={decimalSeparator:".",groupSeparator:",",groupSize:3,secondaryGroupSize:0,fractionGroupSeparator:" ",fractionGroupSize:0},i=t.prototype,ut="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",e,u=0,g=Math.floor,ft=/^-?(\d+(\.\d*)?Line truncated
/* bignumber.js v2.0.3 https://github.com/MikeMcl/bignumber.js/LICENCE */
/* modified by zelig to fix https://github.com/robertkrimen/otto#regular-expression-incompatibility */
!function(e){"use strict";function n(e){function a(e,n){var t,r,i,o,u,s,f=this;if(!(f instanceof a))return j&&L(26,"constructor call without new",e),new a(e,n);if(null!=n&&H(n,2,64,M,"base")){if(n=0|n,s=e+"",10==n)return f=new a(e instanceof a?e:s),U(f,P+f.e+1,k);if((o="number"==typeof e)&&0*e!=0||!new RegExp("^-?"+(t="["+O.slice(0,n)+"]+")+"(?:\\."+t+")?$",37>n?"i":"").test(s))return g(f,s,o,n);o?(f.s=0>1/e?(s=s.slice(1),-1):1,j&&s.replace(/^0\.0*|\./,"").length>15&&L(M,b,e),o=!1):f.s=45===s.charCodeAt(0)?(s=s.slice(1),-1):1,s=D(s,10,n,f.s)}else{if(e instanceof a)return f.s=e.s,f.e=e.e,f.c=(e=e.c)?e.slice():e,void(M=0);if((o="number"==typeof e)&&0*e==0){if(f.s=0>1/e?(e=-e,-1):1,e===~~e){for(r=0,i=e;i>=10;i/=10,r++);return f.e=r,f.c=[e],void(M=0)}s=e+""}else{if(!p.test(s=e+""))return g(f,s,o);f.s=45===s.charCodeAt(0)?(s=s.slice(1),-1):1}}for((r=s.indexOf("."))>-1&&(s=s.replace(".","")),(i=s.search(/e/i))>0?(0>r&&(r=i),r+=+s.slice(i+1),s=s.substring(0,i)):0>r&&(r=s.length),i=0;48===s.charCodeAt(i);i++);for(u=s.length;48===s.charCodeAt(--u););if(s=s.slice(i,u+1))if(u=s.length,o&&j&&u>15&&L(M,b,f.s*e),r=r-i-1,r>z)f.c=f.e=null;else if(G>r)f.c=[f.e=0];else{if(f.e=r,f.c=[],i=(r+1)%y,0>r&&(i+=y),u>i){for(i&&f.c.push(+s.slice(0,i)),u-=y;u>i;)f.c.push(+s.slice(i,i+=y));s=s.slice(i),i=y-s.length}else i-=u;for(;i--;s+="0");f.c.push(+s)}else f.c=[f.e=0];M=0}function D(e,n,t,i){var o,u,f,c,h,g,p,d=e.indexOf("."),m=P,w=k;for(37>t&&(e=e.toLowerCase()),d>=0&&(f=J,J=0,e=e.replace(".",""),p=new a(t),h=p.pow(e.length-d),J=f,p.c=s(l(r(h.c),h.e),10,n),p.e=p.c.length),g=s(e,t,n),u=f=g.length;0==g[--f];g.pop());if(!g[0])return"0";if(0>d?--u:(h.c=g,h.e=u,h.s=i,h=C(h,p,m,w,n),g=h.c,c=h.r,u=h.e),o=u+m+1,d=g[o],f=n/2,c=c||0>o||null!=g[o+1],c=4>w?(null!=d||c)&&(0==w||w==(h.s<0?3:2)):d>f||d==f&&(4==w||c||6==w&&1&g[o-1]||w==(h.s<0?8:7)),1>o||!g[0])e=c?l("1",-m):"0";else{if(g.length=o,c)for(--n;++g[--o]>n;)g[o]=0,o||(++u,g.unshift(1));for(f=g.length;!g[--f];);for(d=0,e="";f>=d;e+=O.charAt(g[d++]));e=l(e,u)}return e}function _(e,n,t,i){var o,u,s,c,h;if(t=null!=t&&H(t,0,8,i,v)?0|t:k,!e.c)return e.toString();if(o=e.c[0],s=e.e,null==n)h=r(e.c),h=19==i||24==i&&B>=s?f(h,s):l(h,s);else if(e=U(new a(e),n,t),u=e.e,h=r(e.c),c=h.length,19==i||24==i&&(u>=n||B>=u)){for(;n>c;h+="0",c++);h=f(h,u)}else if(n-=s,h=l(h,u),u+1>c){if(--n>0)for(h+=".";n--;h+="0");}else if(n+=u-c,n>0)for(u+1==c&&(h+=".");n--;h+="0");return e.s<0&&o?"-"+h:h}function x(e,n){var t,r,i=0;for(u(e[0])&&(e=e[0]),t=new a(e[0]);++i<e.length;){if(r=new a(e[i]),!r.s){t=r;break}n.call(t,r)&&(t=r)}return t}function F(e,n,t,r,i){return(n>e||e>t||e!=c(e))&&L(r,(i||"decimal places")+(n>e||e>t?" out of range":" not an integer"),e),!0}function I(e,n,t){for(var r=1,i=n.length;!n[--i];n.pop());for(i=n[0];i>=10;i/=10,r++);return(t=r+t*y-1)>z?e.c=e.e=null:G>t?e.c=[e.e=0]:(e.e=t,e.c=n),e}function L(e,n,t){var r=new Error(["new BigNumber","cmp","config","div","divToInt","eq","gt","gte","lt","lte","minus","mod","plus","precision","random","round","shift","times","toDigits","toExponential","toFixed","toFormat","toFraction","pow","toPrecision","toString","BigNumber"][e]+"() "+n+": "+t);throw r.name="BigNumber Error",M=0,r}function U(e,n,t,r){var i,o,u,s,f,l,c,a=e.c,h=R;if(a){e:{for(i=1,s=a[0];s>=10;s/=10,i++);if(o=n-i,0>o)o+=y,u=n,f=a[l=0],c=f/h[i-u-1]%10|0;else if(l=d((o+1)/y),l>=a.length){if(!r)break e;for(;a.length<=l;a.push(0));f=c=0,i=1,o%=y,u=o-y+1}else{for(f=s=a[l],i=1;s>=10;s/=10,i++);o%=y,u=o-y+i,c=0>u?0:f/h[i-u-1]%10|0}if(r=r||0>n||null!=a[l+1]||(0>u?f:f%h[i-u-1]),r=4>t?(c||r)&&(0==t||t==(e.s<0?3:2)):c>5||5==c&&(4==t||r||6==t&&(o>0?u>0?f/h[i-u]:0:a[l-1])%10&1||t==(e.s<0?8:7)),1>n||!a[0])return a.length=0,r?(n-=e.e+1,a[0]=h[n%y],e.e=-n||0):a[0]=e.e=0,e;if(0==o?(a.length=l,s=1,l--):(a.length=l+1,s=h[y-o],a[l]=u>0?m(f/h[i-u]%h[u])*s:0),r)for(;;){if(0==l){for(o=1,u=a[0];u>=10;u/=10,o++);for(u=a[0]+=s,s=1;u>=10;u/=10,s++);o!=s&&(e.e++,a[0]==N&&(a[0]=1));break}if(a[l]+=s,a[l]!=N)break;a[l--]=0,s=1}for(o=a.length;0===a[--o];a.pop());}e.e>z?e.c=e.e=null:e.e<G&&(e.c=[e.e=0])}return e}var C,M=0,T=a.prototype,q=new a(1),P=20,k=4,B=-7,$=21,G=-1e7,z=1e7,j=!0,H=F,V=!1,W=1,J=100,X={decimalSeparator:".",groupSeparator:",",groupSize:3,secondaryGroupSize:0,fractionGroupSeparator:" ",fractionGroupSize:0};return a.another=n,a.ROUND_UP=0,a.ROUND_DOWN=1,a.ROUND_CEIL=2,a.ROUND_FLOOR=3,a.ROUND_HALF_UP=4,a.ROUND_HALF_DOWN=5,a.ROUND_HALF_EVEN=6,a.ROUND_HALF_CEIL=7,a.ROUND_HALF_FLOOR=8,a.EUCLID=9,a.config=function(){var e,n,t=0,r={},i=arguments,s=i[0],f=s&&"object"==typeof s?function(){return s.hasOwnProperty(n)?null!=(e=s[n]):void 0}:function(){return i.length>t?null!=(e=i[t++]):void 0};return f(n="DECIMAL_PLACES")&&H(e,0,E,2,n)&&(P=0|e),r[n]=P,f(n="ROUNDING_MODE")&&H(e,0,8,2,n)&&(k=0|e),r[n]=k,f(n="EXPONENTIAL_AT")&&(u(e)?H(e[0],-E,0,2,n)&&H(e[1],0,E,2,n)&&(B=0|e[0],$=0|e[1]):H(e,-E,E,2,n)&&(B=-($=0|(0>e?-e:e)))),r[n]=[B,$],f(n="RANGE")&&(u(e)?H(e[0],-E,-1,2,n)&&H(e[1],1,E,2,n)&&(G=0|e[0],z=0|e[1]):H(e,-E,E,2,n)&&(0|Line truncated
//# sourceMappingURL=doc/bignumber.js.map
+52 -62
View File
@@ -12,7 +12,7 @@ import "../ext/http.js" as Http
ApplicationWindow {
id: root
//flags: Qt.FramelessWindowHint
// Use this to make the window frameless. But then you'll need to do move and resize by hand
@@ -53,7 +53,7 @@ ApplicationWindow {
whisperTab.view.url = "http://ethereum-dapp-whisper-client.meteor.com/";
whisperTab.menuItem.title = "Whisper Chat";
*/
addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/wallet.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/transaction.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/whisper.qml", {noAdd: true, close: false, section: "legacy"});
addPlugin("./views/chain.qml", {noAdd: true, close: false, section: "legacy"});
@@ -126,7 +126,7 @@ ApplicationWindow {
}
function newBrowserTab(url) {
var urlMatches = url.toString().match(/^[a-z]*\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
var requestedDomain = urlMatches && urlMatches[1];
@@ -138,17 +138,17 @@ ApplicationWindow {
var existingDomain = matches && matches[1];
if (requestedDomain == existingDomain) {
domainAlreadyOpen = true;
if (mainSplit.views[i].view.url != url){
mainSplit.views[i].view.url = url;
}
activeView(mainSplit.views[i].view, mainSplit.views[i].menuItem);
}
}
}
}
if (!domainAlreadyOpen) {
if (!domainAlreadyOpen) {
var window = addPlugin("./views/browser.qml", {noAdd: true, close: true, section: "apps", active: true});
window.view.url = url;
window.menuItem.title = "Mist";
@@ -157,7 +157,6 @@ ApplicationWindow {
}
menuBar: MenuBar {
Menu {
title: "File"
@@ -165,7 +164,7 @@ ApplicationWindow {
text: "New tab"
shortcut: "Ctrl+t"
onTriggered: {
activeView(catalog.view, catalog.menuItem);
activeView(catalog.view, catalog.menuItem);
}
}
@@ -206,15 +205,6 @@ ApplicationWindow {
}
}
MenuItem {
text: "Run JS file"
onTriggered: {
generalFileDialog.show(true, function(path) {
eth.evalJavascriptFile(path)
})
}
}
MenuItem {
text: "Dump state"
onTriggered: {
@@ -313,28 +303,28 @@ ApplicationWindow {
Layout.minimumWidth: 192
Layout.maximumWidth: 192
FontLoader {
FontLoader {
id: sourceSansPro
source: "fonts/SourceSansPro-Regular.ttf"
source: "fonts/SourceSansPro-Regular.ttf"
}
FontLoader {
source: "fonts/SourceSansPro-Semibold.ttf"
}
FontLoader {
source: "fonts/SourceSansPro-Bold.ttf"
}
FontLoader {
source: "fonts/SourceSansPro-Black.ttf"
}
FontLoader {
source: "fonts/SourceSansPro-Light.ttf"
}
FontLoader {
source: "fonts/SourceSansPro-ExtraLight.ttf"
}
FontLoader {
FontLoader {
source: "fonts/SourceSansPro-Semibold.ttf"
}
FontLoader {
source: "fonts/SourceSansPro-Bold.ttf"
}
FontLoader {
source: "fonts/SourceSansPro-Black.ttf"
}
FontLoader {
source: "fonts/SourceSansPro-Light.ttf"
}
FontLoader {
source: "fonts/SourceSansPro-ExtraLight.ttf"
}
FontLoader {
id: simpleLineIcons
source: "fonts/Simple-Line-Icons.ttf"
source: "fonts/Simple-Line-Icons.ttf"
}
Rectangle {
@@ -393,7 +383,7 @@ ApplicationWindow {
function setSelection(on) {
sel.visible = on
if (this.closable == true) {
closeIcon.visible = on
}
@@ -404,7 +394,7 @@ ApplicationWindow {
label.visible = !on
buttonLabel.visible = on
}
width: 192
height: 55
color: "#00000000"
@@ -417,7 +407,7 @@ ApplicationWindow {
Rectangle {
// New App Button
id: newAppButton
visible: false
visible: false
anchors.fill: parent
anchors.rightMargin: 8
border.width: 0
@@ -504,16 +494,16 @@ ApplicationWindow {
id: buttonLabel
visible: false
text: "GO TO NEW APP"
font.family: sourceSansPro.name
font.family: sourceSansPro.name
font.weight: Font.DemiBold
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: "#AAA0A0"
}
}
Text {
id: label
font.family: sourceSansPro.name
font.family: sourceSansPro.name
font.weight: Font.DemiBold
elide: Text.ElideRight
x:250
@@ -529,15 +519,15 @@ ApplicationWindow {
}
}
Text {
id: secondary
//only shows secondary title if there's no badge
visible: (badgeContent == "icon" || badgeContent == "number" )? false : true
font.family: sourceSansPro.name
font.family: sourceSansPro.name
font.weight: Font.Light
anchors {
left: icon.right
@@ -566,8 +556,8 @@ ApplicationWindow {
}
Text {
font.family: simpleLineIcons.name
font.family: simpleLineIcons.name
anchors {
centerIn: parent
}
@@ -575,11 +565,11 @@ ApplicationWindow {
font.pixelSize: 20
text: "\ue082"
}
}
}
Rectangle {
id: badge
visible: (badgeContent == "icon" || badgeContent == "number" )? true : false
visible: (badgeContent == "icon" || badgeContent == "number" )? true : false
width: 32
color: "#05000000"
anchors {
@@ -588,11 +578,11 @@ ApplicationWindow {
bottom: parent.bottom;
rightMargin: 4;
}
Text {
id: badgeIconLabel
visible: (badgeContent == "icon") ? true : false;
font.family: simpleLineIcons.name
font.family: simpleLineIcons.name
anchors {
centerIn: parent
}
@@ -600,7 +590,7 @@ ApplicationWindow {
color: "#AAA0A0"
font.pixelSize: 20
text: badgeIcon
}
}
Text {
id: badgeNumberLabel
@@ -609,14 +599,14 @@ ApplicationWindow {
centerIn: parent
}
horizontalAlignment: Text.AlignCenter
font.family: sourceSansPro.name
font.family: sourceSansPro.name
font.weight: Font.Light
color: "#AAA0A0"
font.pixelSize: 18
text: badgeNumber
}
}
function closeApp() {
@@ -685,7 +675,7 @@ ApplicationWindow {
anchors.left: parent.left
anchors.right: parent.right
spacing: 3
ColumnLayout {
@@ -702,7 +692,7 @@ ApplicationWindow {
color: "transparent"
Text {
text: "ETHEREUM"
font.family: sourceSansPro.name
font.family: sourceSansPro.name
font.weight: Font.Regular
// anchors.top: 20
// anchors.left: 16
@@ -711,10 +701,10 @@ ApplicationWindow {
topMargin: 4
fill: parent
}
// anchors.leftMargin: 16
// anchors.topMargin: 16
// anchors.leftMargin: 16
// anchors.topMargin: 16
// anchors.verticalCenterOffset: 50
color: "#AAA0A0"
color: "#AAA0A0"
}
}
@@ -735,7 +725,7 @@ ApplicationWindow {
Text {
text: "APPS"
font.family: sourceSansPro.name
font.family: sourceSansPro.name
font.weight: Font.Regular
anchors.fill: parent
anchors.leftMargin: 16
@@ -775,7 +765,7 @@ ApplicationWindow {
anchors.left: menu.right
anchors.bottom: parent.bottom
anchors.top: parent.top
color: "#00000000"
color: "#00000000"
/*Rectangle {
id: urlPane
+2 -23
View File
@@ -25,9 +25,7 @@ import "C"
import (
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"os"
"path"
"runtime"
"sort"
@@ -99,7 +97,7 @@ func NewWindow(ethereum *eth.Ethereum) *Gui {
return gui
}
func (gui *Gui) Start(assetPath string) {
func (gui *Gui) Start(assetPath, libPath string) {
defer gui.txDb.Close()
guilogger.Infoln("Starting GUI")
@@ -117,7 +115,7 @@ func (gui *Gui) Start(assetPath string) {
// Create a new QML engine
gui.engine = qml.NewEngine()
context := gui.engine.Context()
gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath)
gui.uiLib = NewUiLib(gui.engine, gui.eth, assetPath, libPath)
gui.whisper = qwhisper.New(gui.eth.Whisper())
// Expose the eth library and the ui library to QML
@@ -292,25 +290,6 @@ func (self *Gui) getObjectByName(objectName string) qml.Object {
return self.win.Root().ObjectByName(objectName)
}
func loadJavascriptAssets(gui *Gui) (jsfiles string) {
for _, fn := range []string{"ext/q.js", "ext/eth.js/main.js", "ext/eth.js/qt.js", "ext/setup.js"} {
f, err := os.Open(gui.uiLib.AssetPath(fn))
if err != nil {
fmt.Println(err)
continue
}
content, err := ioutil.ReadAll(f)
if err != nil {
fmt.Println(err)
continue
}
jsfiles += string(content)
}
return
}
func (gui *Gui) SendCommand(cmd ServEv) {
gui.serviceEvents <- cmd
}
+2 -1
View File
@@ -65,6 +65,7 @@ func init() {
utils.NodeKeyFileFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
utils.JSpathFlag,
}
}
@@ -111,7 +112,7 @@ func run(ctx *cli.Context) {
gui := NewWindow(ethereum)
utils.RegisterInterrupt(func(os.Signal) { gui.Stop() })
// gui blocks the main thread
gui.Start(ctx.GlobalString(assetPathFlag.Name))
gui.Start(ctx.GlobalString(assetPathFlag.Name), ctx.GlobalString(utils.JSpathFlag.Name))
return nil
})
}
+8 -19
View File
@@ -21,7 +21,6 @@
package main
import (
"fmt"
"io/ioutil"
"path"
@@ -29,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/javascript"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/qml"
)
@@ -49,15 +47,19 @@ type UiLib struct {
// The main application window
win *qml.Window
jsEngine *javascript.JSRE
filterCallbacks map[int][]int
filterManager *filter.FilterManager
}
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath string) *UiLib {
func NewUiLib(engine *qml.Engine, eth *eth.Ethereum, assetPath, libPath string) *UiLib {
x := xeth.New(eth, nil)
lib := &UiLib{XEth: x, engine: engine, eth: eth, assetPath: assetPath, jsEngine: javascript.NewJSRE(x), filterCallbacks: make(map[int][]int)} //, filters: make(map[int]*xeth.JSFilter)}
lib := &UiLib{
XEth: x,
engine: engine,
eth: eth,
assetPath: assetPath,
filterCallbacks: make(map[int][]int),
}
lib.filterManager = filter.NewFilterManager(eth.EventMux())
go lib.filterManager.Start()
@@ -76,19 +78,6 @@ func (self *UiLib) ImportTx(rlpTx string) {
}
}
func (self *UiLib) EvalJavascriptFile(path string) {
self.jsEngine.LoadExtFile(path[7:])
}
func (self *UiLib) EvalJavascriptString(str string) string {
value, err := self.jsEngine.Run(str)
if err != nil {
return err.Error()
}
return fmt.Sprintf("%v", value)
}
func (ui *UiLib) Muted(content string) {
component, err := ui.engine.LoadFile(ui.AssetPath("qml/muted.qml"))
if err != nil {
+5
View File
@@ -163,6 +163,11 @@ var (
Usage: "Port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
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 {
+65 -3
View File
@@ -219,6 +219,64 @@ func New(config *Config) (*Ethereum, error) {
return eth, nil
}
type NodeInfo struct {
Name string
NodeUrl string
NodeID string
IP string
DiscPort int // UDP listening port for discovery protocol
TCPPort int // TCP listening port for RLPx
Td string
ListenAddr string
}
func (s *Ethereum) NodeInfo() *NodeInfo {
node := s.net.Self()
return &NodeInfo{
Name: s.Name(),
NodeUrl: node.String(),
NodeID: node.ID.String(),
IP: node.IP.String(),
DiscPort: node.DiscPort,
TCPPort: node.TCPPort,
ListenAddr: s.net.ListenAddr,
Td: s.ChainManager().Td().String(),
}
}
type PeerInfo struct {
ID string
Name string
Caps string
RemoteAddress string
LocalAddress string
}
func newPeerInfo(peer *p2p.Peer) *PeerInfo {
var caps []string
for _, cap := range peer.Caps() {
caps = append(caps, cap.String())
}
return &PeerInfo{
ID: peer.ID().String(),
Name: peer.Name(),
Caps: strings.Join(caps, ", "),
RemoteAddress: peer.RemoteAddr().String(),
LocalAddress: peer.LocalAddr().String(),
}
}
// PeersInfo returns an array of PeerInfo objects describing connected peers
func (s *Ethereum) PeersInfo() (peersinfo []*PeerInfo) {
for _, peer := range s.net.Peers() {
if peer != nil {
peersinfo = append(peersinfo, newPeerInfo(peer))
}
}
return
}
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
s.chainManager.ResetWithGenesisBlock(gb)
s.pow.UpdateCache(true)
@@ -251,6 +309,7 @@ func (s *Ethereum) StateDb() common.Database { return s.stateDb }
func (s *Ethereum) ExtraDb() common.Database { return s.extraDb }
func (s *Ethereum) IsListening() bool { return true } // Always listening
func (s *Ethereum) PeerCount() int { return s.net.PeerCount() }
func (s *Ethereum) PeerInfo() int { return s.net.PeerCount() }
func (s *Ethereum) Peers() []*p2p.Peer { return s.net.Peers() }
func (s *Ethereum) MaxPeers() int { return s.net.MaxPeers }
func (s *Ethereum) Version() string { return s.version }
@@ -262,9 +321,11 @@ func (s *Ethereum) Start() error {
ProtocolVersion: ProtocolVersion,
})
err := s.net.Start()
if err != nil {
return err
if s.net.MaxPeers > 0 {
err := s.net.Start()
if err != nil {
return err
}
}
// Start services
@@ -311,6 +372,7 @@ func (s *Ethereum) Stop() {
// Close the database
defer s.blockDb.Close()
defer s.stateDb.Close()
defer s.extraDb.Close()
s.txSub.Unsubscribe() // quits txBroadcastLoop
s.blockSub.Unsubscribe() // quits blockBroadcastLoop
-103
View File
@@ -1,103 +0,0 @@
package javascript
import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/otto"
)
var jsrelogger = logger.NewLogger("JSRE")
type JSRE struct {
Vm *otto.Otto
xeth *xeth.XEth
objectCb map[string][]otto.Value
}
func (jsre *JSRE) LoadExtFile(path string) {
result, err := ioutil.ReadFile(path)
if err == nil {
jsre.Vm.Run(result)
} else {
jsrelogger.Infoln("Could not load file:", path)
}
}
func (jsre *JSRE) LoadIntFile(file string) {
assetPath := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
jsre.LoadExtFile(path.Join(assetPath, file))
}
func NewJSRE(xeth *xeth.XEth) *JSRE {
re := &JSRE{
otto.New(),
xeth,
make(map[string][]otto.Value),
}
// Init the JS lib
re.Vm.Run(jsLib)
// Load extra javascript files
re.LoadIntFile("bignumber.min.js")
re.Bind("eth", &JSEthereum{re.xeth, re.Vm})
re.initStdFuncs()
jsrelogger.Infoln("started")
return re
}
func (self *JSRE) Bind(name string, v interface{}) {
self.Vm.Set(name, v)
}
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"
}
fh, err := os.Open(file)
if err != nil {
return err
}
content, _ := ioutil.ReadAll(fh)
self.Run("exports = {};(function() {" + string(content) + "})();")
return nil
}
func (self *JSRE) require(call otto.FunctionCall) otto.Value {
file, err := call.Argument(0).ToString()
if err != nil {
return otto.UndefinedValue()
}
if err := self.Require(file); err != nil {
fmt.Println("err:", err)
return otto.UndefinedValue()
}
t, _ := self.Vm.Get("exports")
return t
}
-94
View File
@@ -1,94 +0,0 @@
package javascript
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/otto"
)
type JSStateObject struct {
*xeth.Object
eth *JSEthereum
}
func (self *JSStateObject) EachStorage(call otto.FunctionCall) otto.Value {
cb := call.Argument(0)
it := self.Object.Trie().Iterator()
for it.Next() {
cb.Call(self.eth.toVal(self), self.eth.toVal(common.Bytes2Hex(it.Key)), self.eth.toVal(common.Bytes2Hex(it.Value)))
}
return otto.UndefinedValue()
}
// The JSEthereum object attempts to wrap the PEthereum object and returns
// meaningful javascript objects
type JSBlock struct {
*xeth.Block
eth *JSEthereum
}
func (self *JSBlock) GetTransaction(hash string) otto.Value {
return self.eth.toVal(self.Block.GetTransaction(hash))
}
type JSLog struct {
Address string `json:address`
Topics []string `json:topics`
Number int32 `json:number`
Data string `json:data`
}
func NewJSLog(log state.Log) JSLog {
return JSLog{
Address: common.Bytes2Hex(log.Address()),
Topics: nil, //common.Bytes2Hex(log.Address()),
Number: 0,
Data: common.Bytes2Hex(log.Data()),
}
}
type JSEthereum struct {
*xeth.XEth
vm *otto.Otto
}
func (self *JSEthereum) Block(v interface{}) otto.Value {
if number, ok := v.(int64); ok {
return self.toVal(&JSBlock{self.XEth.BlockByNumber(number), self})
} else if hash, ok := v.(string); ok {
return self.toVal(&JSBlock{self.XEth.BlockByHash(hash), self})
}
return otto.UndefinedValue()
}
func (self *JSEthereum) GetStateObject(addr string) otto.Value {
return self.toVal(&JSStateObject{self.XEth.State().SafeGet(addr), self})
}
func (self *JSEthereum) Transact(fromStr, recipient, valueStr, gasStr, gasPriceStr, dataStr string) otto.Value {
r, err := self.XEth.Transact(fromStr, recipient, valueStr, gasStr, gasPriceStr, dataStr)
if err != nil {
fmt.Println(err)
return otto.UndefinedValue()
}
return self.toVal(r)
}
func (self *JSEthereum) toVal(v interface{}) otto.Value {
result, err := self.vm.ToValue(v)
if err != nil {
fmt.Println("Value unknown:", err)
return otto.UndefinedValue()
}
return result
}
+6
View File
@@ -0,0 +1,6 @@
package jsre
const BigNumber_JS = `/* bignumber.js v2.0.3 https://github.com/MikeMcl/bignumber.js/LICENCE */
/* modified by zelig to fix https://github.com/robertkrimen/otto#regular-expression-incompatibility */
!function(e){"use strict";function n(e){function a(e,n){var t,r,i,o,u,s,f=this;if(!(f instanceof a))return j&&L(26,"constructor call without new",e),new a(e,n);if(null!=n&&H(n,2,64,M,"base")){if(n=0|n,s=e+"",10==n)return f=new a(e instanceof a?e:s),U(f,P+f.e+1,k);if((o="number"==typeof e)&&0*e!=0||!new RegExp("^-?"+(t="["+O.slice(0,n)+"]+")+"(?:\\."+t+")?$",37>n?"i":"").test(s))return g(f,s,o,n);o?(f.s=0>1/e?(s=s.slice(1),-1):1,j&&s.replace(/^0\.0*|\./,"").length>15&&L(M,b,e),o=!1):f.s=45===s.charCodeAt(0)?(s=s.slice(1),-1):1,s=D(s,10,n,f.s)}else{if(e instanceof a)return f.s=e.s,f.e=e.e,f.c=(e=e.c)?e.slice():e,void(M=0);if((o="number"==typeof e)&&0*e==0){if(f.s=0>1/e?(e=-e,-1):1,e===~~e){for(r=0,i=e;i>=10;i/=10,r++);return f.e=r,f.c=[e],void(M=0)}s=e+""}else{if(!p.test(s=e+""))return g(f,s,o);f.s=45===s.charCodeAt(0)?(s=s.slice(1),-1):1}}for((r=s.indexOf("."))>-1&&(s=s.replace(".","")),(i=s.search(/e/i))>0?(0>r&&(r=i),r+=+s.slice(i+1),s=s.substring(0,i)):0>r&&(r=s.length),i=0;48===s.charCodeAt(i);i++);for(u=s.length;48===s.charCodeAt(--u););if(s=s.slice(i,u+1))if(u=s.length,o&&j&&u>15&&L(M,b,f.s*e),r=r-i-1,r>z)f.c=f.e=null;else if(G>r)f.c=[f.e=0];else{if(f.e=r,f.c=[],i=(r+1)%y,0>r&&(i+=y),u>i){for(i&&f.c.push(+s.slice(0,i)),u-=y;u>i;)f.c.push(+s.slice(i,i+=y));s=s.slice(i),i=y-s.length}else i-=u;for(;i--;s+="0");f.c.push(+s)}else f.c=[f.e=0];M=0}function D(e,n,t,i){var o,u,f,c,h,g,p,d=e.indexOf("."),m=P,w=k;for(37>t&&(e=e.toLowerCase()),d>=0&&(f=J,J=0,e=e.replace(".",""),p=new a(t),h=p.pow(e.length-d),J=f,p.c=s(l(r(h.c),h.e),10,n),p.e=p.c.length),g=s(e,t,n),u=f=g.length;0==g[--f];g.pop());if(!g[0])return"0";if(0>d?--u:(h.c=g,h.e=u,h.s=i,h=C(h,p,m,w,n),g=h.c,c=h.r,u=h.e),o=u+m+1,d=g[o],f=n/2,c=c||0>o||null!=g[o+1],c=4>w?(null!=d||c)&&(0==w||w==(h.s<0?3:2)):d>f||d==f&&(4==w||c||6==w&&1&g[o-1]||w==(h.s<0?8:7)),1>o||!g[0])e=c?l("1",-m):"0";else{if(g.length=o,c)for(--n;++g[--o]>n;)g[o]=0,o||(++u,g.unshift(1));for(f=g.length;!g[--f];);for(d=0,e="";f>=d;e+=O.charAt(g[d++]));e=l(e,u)}return e}function _(e,n,t,i){var o,u,s,c,h;if(t=null!=t&&H(t,0,8,i,v)?0|t:k,!e.c)return e.toString();if(o=e.c[0],s=e.e,null==n)h=r(e.c),h=19==i||24==i&&B>=s?f(h,s):l(h,s);else if(e=U(new a(e),n,t),u=e.e,h=r(e.c),c=h.length,19==i||24==i&&(u>=n||B>=u)){for(;n>c;h+="0",c++);h=f(h,u)}else if(n-=s,h=l(h,u),u+1>c){if(--n>0)for(h+=".";n--;h+="0");}else if(n+=u-c,n>0)for(u+1==c&&(h+=".");n--;h+="0");return e.s<0&&o?"-"+h:h}function x(e,n){var t,r,i=0;for(u(e[0])&&(e=e[0]),t=new a(e[0]);++i<e.length;){if(r=new a(e[i]),!r.s){t=r;break}n.call(t,r)&&(t=r)}return t}function F(e,n,t,r,i){return(n>e||e>t||e!=c(e))&&L(r,(i||"decimal places")+(n>e||e>t?" out of range":" not an integer"),e),!0}function I(e,n,t){for(var r=1,i=n.length;!n[--i];n.pop());for(i=n[0];i>=10;i/=10,r++);return(t=r+t*y-1)>z?e.c=e.e=null:G>t?e.c=[e.e=0]:(e.e=t,e.c=n),e}function L(e,n,t){var r=new Error(["new BigNumber","cmp","config","div","divToInt","eq","gt","gte","lt","lte","minus","mod","plus","precision","random","round","shift","times","toDigits","toExponential","toFixed","toFormat","toFraction","pow","toPrecision","toString","BigNumber"][e]+"() "+n+": "+t);throw r.name="BigNumber Error",M=0,r}function U(e,n,t,r){var i,o,u,s,f,l,c,a=e.c,h=R;if(a){e:{for(i=1,s=a[0];s>=10;s/=10,i++);if(o=n-i,0>o)o+=y,u=n,f=a[l=0],c=f/h[i-u-1]%10|0;else if(l=d((o+1)/y),l>=a.length){if(!r)break e;for(;a.length<=l;a.push(0));f=c=0,i=1,o%=y,u=o-y+1}else{for(f=s=a[l],i=1;s>=10;s/=10,i++);o%=y,u=o-y+i,c=0>u?0:f/h[i-u-1]%10|0}if(r=r||0>n||null!=a[l+1]||(0>u?f:f%h[i-u-1]),r=4>t?(c||r)&&(0==t||t==(e.s<0?3:2)):c>5||5==c&&(4==t||r||6==t&&(o>0?u>0?f/h[i-u]:0:a[l-1])%10&1||t==(e.s<0?8:7)),1>n||!a[0])return a.length=0,r?(n-=e.e+1,a[0]=h[n%y],e.e=-n||0):a[0]=e.e=0,e;if(0==o?(a.length=l,s=1,l--):(a.length=l+1,s=h[y-o],a[l]=u>0?m(f/h[i-u]%h[u])*s:0),r)for(;;){if(0==l){for(o=1,u=a[0];u>=10;u/=10,o++);for(u=a[0]+=s,s=1;u>=10;u/=10,s++);o!=s&&(e.e++,a[0]==N&&(a[0]=1));break}if(a[l]+=s,a[l]!=N)break;a[l--]=0,s=1}for(o=a.length;0===a[--o];a.pop());}e.e>z?e.c=e.e=null:e.e<G&&(e.c=[e.e=0])}return e}var C,M=0,T=a.prototype,q=new a(1),P=20,k=4,B=-7,$=21,G=-1e7,z=1e7,j=!0,H=F,V=!1,W=1,J=100,X={decimalSeparator:".",groupSeparator:",",groupSize:3,secondaryGroupSize:0,fractionGroupSeparator:" ",fractionGroupSize:0};return a.another=n,a.ROUND_UP=0,a.ROUND_DOWN=1,a.ROUND_CEIL=2,a.ROUND_FLOOR=3,a.ROUND_HALF_UP=4,a.ROUND_HALF_DOWN=5,a.ROUND_HALF_EVEN=6,a.ROUND_HALF_CEIL=7,a.ROUND_HALF_FLOOR=8,a.EUCLID=9,a.config=function(){var e,n,t=0,r={},i=arguments,s=i[0],f=s&&"object"==typeof s?function(){return s.hasOwnProperty(n)?null!=(e=s[n]):void 0}:function(){return i.length>t?null!=(e=i[t++]):void 0};return f(n="DECIMAL_PLACES")&&H(e,0,E,2,n)&&(P=0|e),r[n]=P,f(n="ROUNDING_MODE")&&H(e,0,8,2,n)&&(k=0|e),r[n]=k,f(n="EXPONENTIAL_AT")&&(u(e)?H(e[0],-E,0,2,n)&&H(e[1],0,E,2,n)&&(B=0|e[0],$=0|e[1]):H(e,-E,E,2,n)&&(B=-($=0|(0>e?-e:e)))),r[n]=[B,$],f(n="RANGE")&&(u(e)?H(e[0],-E,-1,2,n)&&H(e[1],1,E,2,n)&&(G=0|e[0],z=0|e[1]):H(e,-E,E,2,n)&&(0|Line truncated
//# sourceMappingURL=doc/bignumber.js.map`
+3
View File
@@ -0,0 +1,3 @@
package jsre
const Ethereum_JS = `require=function t(e,n,r){function o(i,u){if(!n[i]){if(!e[i]){var s="function"==typeof require&&require;if(!u&&s)return s(i,!0);if(a)return a(i,!0);var c=new Error("Cannot find module '"+i+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[i]={exports:{}};e[i][0].call(l.exports,function(t){var n=e[i][1][t];return o(n?n:t)},l,l.exports,t,e,n,r)}return n[i].exports}for(var a="function"==typeof require&&require,i=0;i<r.length;i++)o(r[i]);return o}({1:[function(t,e){var n=t("../utils/utils"),r=t("../utils/config"),o=t("./types"),a=t("./formatters"),i=function(t){throw new Error("parser does not support type: "+t)},u=function(t){return"[]"===t.slice(-2)},s=function(t,e){return u(t)||"string"===t?a.formatInputInt(e.length):""},c=o.inputTypes(),l=function(t,e){var n="",r="",o="";return t.forEach(function(t,r){n+=s(t.type,e[r])}),t.forEach(function(n,a){for(var s=!1,l=0;l<c.length&&!s;l++)s=c[l].type(t[a].type,e[a]);s||i(t[a].type);var f=c[l-1].format;u(t[a].type)?o+=e[a].reduce(function(t,e){return t+f(e)},""):"string"===t[a].type?o+=f(e[a]):r+=f(e[a])}),n+=r+o},f=function(t){return u(t)||"string"===t?2*r.ETH_PADDING:0},p=o.outputTypes(),m=function(t,e){e=e.slice(2);var n=[],s=2*r.ETH_PADDING,c=t.reduce(function(t,e){return t+f(e.type)},0),l=e.slice(0,c);return e=e.slice(c),t.forEach(function(r,c){for(var f=!1,m=0;m<p.length&&!f;m++)f=p[m].type(t[c].type);f||i(t[c].type);var d=p[m-1].format;if(u(t[c].type)){var h=a.formatOutputUInt(l.slice(0,s));l=l.slice(s);for(var g=[],y=0;h>y;y++)g.push(d(e.slice(0,s))),e=e.slice(s);n.push(g)}else o.prefixedType("string")(t[c].type)?(l=l.slice(s),n.push(d(e.slice(0,s))),e=e.slice(s)):(n.push(d(e.slice(0,s))),e=e.slice(s))}),n},d=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),a=function(){var e=Array.prototype.slice.call(arguments);return l(t.inputs,e)};void 0===e[r]&&(e[r]=a),e[r][o]=a}),e},h=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),o=n.extractTypeName(t.name),a=function(e){return m(t.outputs,e)};void 0===e[r]&&(e[r]=a),e[r][o]=a}),e};e.exports={inputParser:d,outputParser:h,formatInput:l,formatOutput:m}},{"../utils/config":4,"../utils/utils":5,"./formatters":2,"./types":3}],2:[function(t,e){var n=t("../utils/utils"),r=t("../utils/config"),o=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},a=function(t){var e=2*r.ETH_PADDING;return BigNumber.config(r.ETH_BIGNUMBER_ROUNDING_MODE),o(n.toTwosComplement(t).round().toString(16),e)},i=function(t){return n.fromAscii(t,r.ETH_PADDING).substr(2)},u=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},s=function(t){return a(new BigNumber(t).times(new BigNumber(2).pow(128)))},c=function(t){return"1"===new BigNumber(t.substr(0,1),16).toString(2).substr(0,1)},l=function(t){return t=t||"0",c(t)?new BigNumber(t,16).minus(new BigNumber("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new BigNumber(t,16)},f=function(t){return t=t||"0",new BigNumber(t,16)},p=function(t){return l(t).dividedBy(new BigNumber(2).pow(128))},m=function(t){return f(t).dividedBy(new BigNumber(2).pow(128))},d=function(t){return"0x"+t},h=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},g=function(t){return n.toAscii(t)},y=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:a,formatInputString:i,formatInputBool:u,formatInputReal:s,formatOutputInt:l,formatOutputUInt:f,formatOutputReal:p,formatOutputUReal:m,formatOutputHash:d,formatOutputBool:h,formatOutputString:g,formatOutputAddress:y}},{"../utils/config":4,"../utils/utils":5}],3:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},o=function(t){return function(e){return t===e}},a=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("hash"),format:n.formatInputInt},{type:r("string"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:o("address"),format:n.formatInputInt},{type:o("bool"),format:n.formatInputBool}]},i=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("hash"),format:n.formatOutputHash},{type:r("string"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:o("address"),format:n.formatOutputAddress},{type:o("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:o,inputTypes:a,outputTypes:i}},{"./formatters":2}],4:[function(t,e){var n=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:n,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:BigNumber.ROUND_DOWN},ELine truncated
+115
View File
@@ -0,0 +1,115 @@
package jsre
import (
"fmt"
"github.com/obscuren/otto"
"io/ioutil"
"github.com/ethereum/go-ethereum/common"
)
/*
JSRE is a generic JS runtime environment embedding the otto JS interpreter.
It provides some helper functions to
- load code from files
- run code snippets
- require libraries
- bind native go objects
*/
type JSRE struct {
assetPath string
vm *otto.Otto
}
func New(assetPath string) *JSRE {
re := &JSRE{
assetPath,
otto.New(),
}
// load prettyprint func definition
re.vm.Run(pp_js)
re.vm.Set("loadScript", re.loadScript)
return re
}
// Exec(file) loads and runs the contents of a file
// if a relative path is given, the jsre's assetPath is used
func (self *JSRE) Exec(file string) error {
return self.exec(common.AbsolutePath(self.assetPath, file))
}
func (self *JSRE) exec(path string) error {
code, err := ioutil.ReadFile(path)
if err != nil {
return err
}
_, err = self.vm.Run(code)
return err
}
func (self *JSRE) Bind(name string, v interface{}) (err error) {
self.vm.Set(name, v)
return
}
func (self *JSRE) Run(code string) (otto.Value, error) {
return self.vm.Run(code)
}
func (self *JSRE) Get(ns string) (otto.Value, error) {
return self.vm.Get(ns)
}
func (self *JSRE) Set(ns string, v interface{}) error {
return self.vm.Set(ns, v)
}
func (self *JSRE) loadScript(call otto.FunctionCall) otto.Value {
file, err := call.Argument(0).ToString()
if err != nil {
return otto.FalseValue()
}
if err := self.Exec(file); err != nil {
fmt.Println("err:", err)
return otto.FalseValue()
}
return otto.TrueValue()
}
func (self *JSRE) PrettyPrint(v interface{}) (val otto.Value, err error) {
var method otto.Value
v, err = self.vm.ToValue(v)
if err != nil {
return
}
method, err = self.vm.Get("prettyPrint")
if err != nil {
return
}
return method.Call(method, v)
}
func (self *JSRE) ToVal(v interface{}) otto.Value {
result, err := self.vm.ToValue(v)
if err != nil {
fmt.Println("Value unknown:", err)
return otto.UndefinedValue()
}
return result
}
func (self *JSRE) Eval(code string) (s string, err error) {
var val otto.Value
val, err = self.Run(code)
if err != nil {
return
}
val, err = self.PrettyPrint(val)
if err != nil {
return
}
return fmt.Sprintf("%v", val), nil
}
+84
View File
@@ -0,0 +1,84 @@
package jsre
import (
"github.com/obscuren/otto"
"testing"
"github.com/ethereum/go-ethereum/common"
)
type testNativeObjectBinding struct {
toVal func(interface{}) otto.Value
}
type msg struct {
Msg string
}
func (no *testNativeObjectBinding) TestMethod(call otto.FunctionCall) otto.Value {
m, err := call.Argument(0).ToString()
if err != nil {
return otto.UndefinedValue()
}
return no.toVal(&msg{m})
}
func TestExec(t *testing.T) {
jsre := New("/tmp")
common.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`))
err := jsre.Exec("test.js")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
val, err := jsre.Run("msg")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
if !val.IsString() {
t.Errorf("expected string value, got %v", val)
}
exp := "testMsg"
got, _ := val.ToString()
if exp != got {
t.Errorf("expected '%v', got '%v'", exp, got)
}
}
func TestBind(t *testing.T) {
jsre := New("/tmp")
jsre.Bind("no", &testNativeObjectBinding{jsre.ToVal})
val, err := jsre.Run(`no.testMethod("testMsg")`)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
pp, err := jsre.PrettyPrint(val)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
t.Logf("no: %v", pp)
}
func TestLoadScript(t *testing.T) {
jsre := New("/tmp")
common.WriteFile("/tmp/test.js", []byte(`msg = "testMsg"`))
_, err := jsre.Run(`loadScript("test.js")`)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
val, err := jsre.Run("msg")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
if !val.IsString() {
t.Errorf("expected string value, got %v", val)
}
exp := "testMsg"
got, _ := val.ToString()
if exp != got {
t.Errorf("expected '%v', got '%v'", exp, got)
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
package javascript
package jsre
const jsLib = `
const pp_js = `
function pp(object) {
var str = "";
@@ -34,7 +34,7 @@ function pp(object) {
} else if(typeof(object) === "function") {
str += "\033[35m[Function]";
} else {
str += object;
str += object;
}
str += "\033[0m";
+3 -3
View File
@@ -51,9 +51,9 @@ func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr) *Table {
return tab
}
// Self returns the local node ID.
func (tab *Table) Self() NodeID {
return tab.self.ID
// Self returns the local node.
func (tab *Table) Self() *Node {
return tab.self
}
// Close terminates the network listener.
+9 -5
View File
@@ -180,7 +180,7 @@ func (srv *Server) Start() (err error) {
srv.ntab = ntab
// handshake
srv.ourHandshake = &protoHandshake{Version: baseProtocolVersion, Name: srv.Name, ID: ntab.Self()}
srv.ourHandshake = &protoHandshake{Version: baseProtocolVersion, Name: srv.Name, ID: ntab.Self().ID}
for _, p := range srv.Protocols {
srv.ourHandshake.Caps = append(srv.ourHandshake.Caps, p.cap())
}
@@ -298,7 +298,7 @@ func (srv *Server) dialLoop() {
srv.lock.Lock()
_, isconnected := srv.peers[dest.ID]
srv.lock.Unlock()
if isconnected || dialing[dest.ID] || dest.ID == srv.ntab.Self() {
if isconnected || dialing[dest.ID] || dest.ID == srv.Self().ID {
continue
}
@@ -332,12 +332,16 @@ func (srv *Server) dialNode(dest *discover.Node) {
srv.startPeer(conn, dest)
}
func (srv *Server) Self() *discover.Node {
return srv.ntab.Self()
}
func (srv *Server) findPeers() {
far := srv.ntab.Self()
far := srv.Self().ID
for i := range far {
far[i] = ^far[i]
}
closeToSelf := srv.ntab.Lookup(srv.ntab.Self())
closeToSelf := srv.ntab.Lookup(srv.Self().ID)
farFromSelf := srv.ntab.Lookup(far)
for i := 0; i < len(closeToSelf) || i < len(farFromSelf); i++ {
@@ -402,7 +406,7 @@ func (srv *Server) addPeer(id discover.NodeID, p *Peer) (bool, DiscReason) {
return false, DiscTooManyPeers
case srv.peers[id] != nil:
return false, DiscAlreadyConnected
case id == srv.ntab.Self():
case id == srv.Self().ID:
return false, DiscSelf
}
srv.peers[id] = p
+12 -1
View File
@@ -9,11 +9,11 @@ import (
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/state"
@@ -371,6 +371,11 @@ func (p *EthereumApi) NewWhisperIdentity(reply *interface{}) error {
return nil
}
// func (p *EthereumApi) RemoveWhisperIdentity(args *WhisperIdentityArgs, reply *interface{}) error {
// *reply = p.xeth().Whisper().RemoveIdentity(args.Identity)
// return nil
// }
func (p *EthereumApi) NewWhisperFilter(args *WhisperFilterArgs, reply *interface{}) error {
var id int
opts := new(xeth.Options)
@@ -751,6 +756,12 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return p.WhisperPost(args, reply)
case "shh_newIdentity":
return p.NewWhisperIdentity(reply)
// case "shh_removeIdentity":
// args := new(WhisperIdentityArgs)
// if err := json.Unmarshal(req.Params, &args); err != nil {
// return err
// }
// return p.RemoveWhisperIdentity(args, reply)
case "shh_hasIdentity":
args := new(WhisperIdentityArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
+28 -40
View File
@@ -331,42 +331,6 @@ func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
return nil
}
// type FilterArgs struct {
// FromBlock uint64
// ToBlock uint64
// Limit uint64
// Offset uint64
// Address string
// Topics []string
// }
// func (args *FilterArgs) UnmarshalJSON(b []byte) (err error) {
// var obj []struct {
// FromBlock string `json:"fromBlock"`
// ToBlock string `json:"toBlock"`
// Limit string `json:"limit"`
// Offset string `json:"offset"`
// Address string `json:"address"`
// Topics []string `json:"topics"`
// }
// if err = json.Unmarshal(b, &obj); err != nil {
// return errDecodeArgs
// }
// if len(obj) < 1 {
// return errArguments
// }
// args.FromBlock = uint64(common.Big(obj[0].FromBlock).Int64())
// args.ToBlock = uint64(common.Big(obj[0].ToBlock).Int64())
// args.Limit = uint64(common.Big(obj[0].Limit).Int64())
// args.Offset = uint64(common.Big(obj[0].Offset).Int64())
// args.Address = obj[0].Address
// args.Topics = obj[0].Topics
// return nil
// }
type FilterOptions struct {
Earliest int64
Latest int64
@@ -378,8 +342,8 @@ type FilterOptions struct {
func (args *FilterOptions) UnmarshalJSON(b []byte) (err error) {
var obj []struct {
FromBlock string `json:"fromBlock"`
ToBlock string `json:"toBlock"`
FromBlock interface{} `json:"fromBlock"`
ToBlock interface{} `json:"toBlock"`
Limit string `json:"limit"`
Offset string `json:"offset"`
Address string `json:"address"`
@@ -394,8 +358,32 @@ func (args *FilterOptions) UnmarshalJSON(b []byte) (err error) {
return NewInsufficientParamsError(len(obj), 1)
}
args.Earliest = int64(common.Big(obj[0].FromBlock).Int64())
args.Latest = int64(common.Big(obj[0].ToBlock).Int64())
fromstr, ok := obj[0].FromBlock.(string)
if !ok {
return NewDecodeParamError("FromBlock is not a string")
}
switch fromstr {
case "latest":
args.Earliest = 0
default:
args.Earliest = int64(common.Big(obj[0].FromBlock.(string)).Int64())
}
tostr, ok := obj[0].ToBlock.(string)
if !ok {
return NewDecodeParamError("ToBlock is not a string")
}
switch tostr {
case "latest":
args.Latest = 0
case "pending":
args.Latest = -1
default:
args.Latest = int64(common.Big(obj[0].ToBlock.(string)).Int64())
}
args.Max = int(common.Big(obj[0].Limit).Int64())
args.Skip = int(common.Big(obj[0].Offset).Int64())
args.Address = obj[0].Address
+120
View File
@@ -74,6 +74,16 @@ func TestGetBlockByHashArgs(t *testing.T) {
}
}
func TestGetBlockByHashEmpty(t *testing.T) {
input := `[]`
args := new(GetBlockByHashArgs)
err := json.Unmarshal([]byte(input), &args)
if err == nil {
t.Error("Expected error but didn't get one")
}
}
func TestGetBlockByNumberArgs(t *testing.T) {
input := `["0x1b4", false]`
expected := new(GetBlockByNumberArgs)
@@ -94,6 +104,16 @@ func TestGetBlockByNumberArgs(t *testing.T) {
}
}
func TestGetBlockByNumberEmpty(t *testing.T) {
input := `[]`
args := new(GetBlockByNumberArgs)
err := json.Unmarshal([]byte(input), &args)
if err == nil {
t.Error("Expected error but didn't get one")
}
}
func TestNewTxArgs(t *testing.T) {
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f072445675",
@@ -139,6 +159,16 @@ func TestNewTxArgs(t *testing.T) {
}
}
func TestNewTxArgsEmpty(t *testing.T) {
input := `[]`
args := new(NewTxArgs)
err := json.Unmarshal([]byte(input), &args)
if err == nil {
t.Error("Expected error but didn't get one")
}
}
func TestGetStorageArgs(t *testing.T) {
input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"]`
expected := new(GetStorageArgs)
@@ -163,6 +193,16 @@ func TestGetStorageArgs(t *testing.T) {
}
}
func TestGetStorageEmptyArgs(t *testing.T) {
input := `[]`
args := new(GetStorageArgs)
err := json.Unmarshal([]byte(input), &args)
if err == nil {
t.Error("Expected error but didn't get one")
}
}
func TestGetStorageAtArgs(t *testing.T) {
input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "0x0", "0x2"]`
expected := new(GetStorageAtArgs)
@@ -192,6 +232,16 @@ func TestGetStorageAtArgs(t *testing.T) {
}
}
func TestGetStorageAtEmptyArgs(t *testing.T) {
input := `[]`
args := new(GetStorageAtArgs)
err := json.Unmarshal([]byte(input), &args)
if err == nil {
t.Error("Expected error but didn't get one")
}
}
func TestGetTxCountArgs(t *testing.T) {
input := `["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"]`
expected := new(GetTxCountArgs)
@@ -216,6 +266,16 @@ func TestGetTxCountArgs(t *testing.T) {
}
}
func TestGetTxCountEmptyArgs(t *testing.T) {
input := `[]`
args := new(GetTxCountArgs)
err := json.Unmarshal([]byte(input), &args)
if err == nil {
t.Error("Expected error but didn't get one")
}
}
func TestGetDataArgs(t *testing.T) {
input := `["0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8", "latest"]`
expected := new(GetDataArgs)
@@ -240,6 +300,16 @@ func TestGetDataArgs(t *testing.T) {
}
}
func TestGetDataEmptyArgs(t *testing.T) {
input := `[]`
args := new(GetDataArgs)
err := json.Unmarshal([]byte(input), &args)
if err == nil {
t.Error("Expected error but didn't get one")
}
}
func TestFilterOptions(t *testing.T) {
input := `[{
"fromBlock": "0x1",
@@ -286,6 +356,56 @@ func TestFilterOptions(t *testing.T) {
// }
}
func TestFilterOptionsWords(t *testing.T) {
input := `[{
"fromBlock": "latest",
"toBlock": "pending"
}]`
expected := new(FilterOptions)
expected.Earliest = 0
expected.Latest = -1
args := new(FilterOptions)
if err := json.Unmarshal([]byte(input), &args); err != nil {
t.Error(err)
}
if expected.Earliest != args.Earliest {
t.Errorf("Earliest shoud be %#v but is %#v", expected.Earliest, args.Earliest)
}
if expected.Latest != args.Latest {
t.Errorf("Latest shoud be %#v but is %#v", expected.Latest, args.Latest)
}
}
func TestFilterOptionsNums(t *testing.T) {
input := `[{
"fromBlock": 2,
"toBlock": 3
}]`
args := new(FilterOptions)
err := json.Unmarshal([]byte(input), &args)
switch err.(type) {
case *DecodeParamError:
break
default:
t.Errorf("Should have *DecodeParamError but instead have %T", err)
}
}
func TestFilterOptionsEmptyArgs(t *testing.T) {
input := `[]`
args := new(FilterOptions)
err := json.Unmarshal([]byte(input), &args)
if err == nil {
t.Error("Expected error but didn't get one")
}
}
func TestDbArgs(t *testing.T) {
input := `["0x74657374","0x6b6579","0x6d79537472696e67"]`
expected := new(DbArgs)
+7 -7
View File
@@ -26,7 +26,7 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
if req.ContentLength > maxSizeReqLength {
jsonerr := &RpcErrorObject{-32700, "Request too large"}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
json.Send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr})
return
}
@@ -36,11 +36,11 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
break
case *DecodeParamError, *InsufficientParamsError, *ValidationError:
jsonerr := &RpcErrorObject{-32602, reqerr.Error()}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
json.Send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr})
return
default:
jsonerr := &RpcErrorObject{-32700, "Could not parse request"}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
json.Send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr})
return
}
@@ -51,19 +51,19 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
break
case *NotImplementedError:
jsonerr := &RpcErrorObject{-32601, reserr.Error()}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Error: jsonerr})
json.Send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: reqParsed.Id, Error: jsonerr})
return
case *DecodeParamError, *InsufficientParamsError, *ValidationError:
jsonerr := &RpcErrorObject{-32602, reserr.Error()}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Error: jsonerr})
json.Send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: reqParsed.Id, Error: jsonerr})
return
default:
jsonerr := &RpcErrorObject{-32603, reserr.Error()}
json.Send(w, &RpcErrorResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Error: jsonerr})
json.Send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: reqParsed.Id, Error: jsonerr})
return
}
rpchttplogger.DebugDetailf("Generated response: %T %s", response, response)
json.Send(w, &RpcSuccessResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Result: response})
json.Send(w, &RpcSuccessResponse{Jsonrpc: jsonrpcver, Id: reqParsed.Id, Result: response})
})
}
+43
View File
@@ -0,0 +1,43 @@
package rpc
import (
"encoding/json"
// "fmt"
"github.com/obscuren/otto"
)
type Jeth struct {
ethApi *EthereumApi
toVal func(interface{}) otto.Value
}
func NewJeth(ethApi *EthereumApi, toVal func(interface{}) otto.Value) *Jeth {
return &Jeth{ethApi, toVal}
}
func (self *Jeth) err(code int, msg string, id interface{}) otto.Value {
rpcerr := &RpcErrorObject{code, msg}
rpcresponse := &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: id, Error: rpcerr}
return self.toVal(rpcresponse)
}
func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
reqif, err := call.Argument(0).Export()
if err != nil {
return self.err(-32700, err.Error(), nil)
}
jsonreq, err := json.Marshal(reqif)
var req RpcRequest
err = json.Unmarshal(jsonreq, &req)
var respif interface{}
err = self.ethApi.GetRequestReply(&req, &respif)
if err != nil {
return self.err(-32603, err.Error(), req.Id)
}
rpcresponse := &RpcSuccessResponse{Jsonrpc: jsonrpcver, Id: req.Id, Result: respif}
response = self.toVal(rpcresponse)
return
}
+6 -6
View File
@@ -83,21 +83,21 @@ func NewValidationError(param string, msg string) error {
}
type RpcRequest struct {
ID interface{} `json:"id"`
JsonRpc string `json:"jsonrpc"`
Id interface{} `json:"id"`
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params json.RawMessage `json:"params"`
}
type RpcSuccessResponse struct {
ID interface{} `json:"id"`
JsonRpc string `json:"jsonrpc"`
Id interface{} `json:"id"`
Jsonrpc string `json:"jsonrpc"`
Result interface{} `json:"result"`
}
type RpcErrorResponse struct {
ID interface{} `json:"id"`
JsonRpc string `json:"jsonrpc"`
Id interface{} `json:"id"`
Jsonrpc string `json:"jsonrpc"`
Error *RpcErrorObject `json:"error"`
}
+5
View File
@@ -45,6 +45,11 @@ func UnmarshalRawMessages(b []byte, iface interface{}, number *int64) (err error
return NewDecodeParamError(err.Error())
}
// Hrm... Occurs when no params
if len(data) == 0 {
return NewDecodeParamError("No data")
}
// Number index determines the index in the array for a possible block number
numberIndex := 0
+9
View File
@@ -116,6 +116,15 @@ func (self *Whisper) GetIdentity(key *ecdsa.PublicKey) *ecdsa.PrivateKey {
return self.keys[string(crypto.FromECDSAPub(key))]
}
// func (self *Whisper) RemoveIdentity(key *ecdsa.PublicKey) bool {
// k := string(crypto.FromECDSAPub(key))
// if _, ok := self.keys[k]; ok {
// delete(self.keys, k)
// return true
// }
// return false
// }
func (self *Whisper) Watch(opts Filter) int {
return self.filters.Install(filter.Generic{
Str1: string(crypto.FromECDSAPub(opts.To)),
+5 -1
View File
@@ -4,8 +4,8 @@ import (
"errors"
"time"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/whisper"
)
@@ -63,6 +63,10 @@ func (self *Whisper) HasIdentity(key string) bool {
return self.Whisper.HasIdentity(crypto.ToECDSAPub(common.FromHex(key)))
}
// func (self *Whisper) RemoveIdentity(key string) bool {
// return self.Whisper.RemoveIdentity(crypto.ToECDSAPub(common.FromHex(key)))
// }
func (self *Whisper) Watch(opts *Options) int {
filter := whisper.Filter{
To: crypto.ToECDSAPub(common.FromHex(opts.To)),