aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/ethereum/admin.go259
-rw-r--r--cmd/ethereum/js.go168
-rw-r--r--cmd/ethereum/js_test.go252
-rw-r--r--cmd/ethereum/main.go54
-rw-r--r--cmd/mist/assets/ext/bignumber.min.js6
-rw-r--r--cmd/mist/assets/qml/main.qml114
-rw-r--r--cmd/mist/gui.go25
-rw-r--r--cmd/mist/main.go3
-rw-r--r--cmd/mist/ui_lib.go27
-rw-r--r--cmd/utils/flags.go5
10 files changed, 674 insertions, 239 deletions
diff --git a/cmd/ethereum/admin.go b/cmd/ethereum/admin.go
new file mode 100644
index 000000000..880a22c22
--- /dev/null
+++ b/cmd/ethereum/admin.go
@@ -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)
+
+}
diff --git a/cmd/ethereum/js.go b/cmd/ethereum/js.go
index a3c5f5d2d..b4b54b7e6 100644
--- a/cmd/ethereum/js.go
+++ b/cmd/ethereum/js.go
@@ -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)
- }
- }
-}
-
-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()
+ fmt.Printf("%v", val)
}
-
- return otto.TrueValue()
}
diff --git a/cmd/ethereum/js_test.go b/cmd/ethereum/js_test.go
new file mode 100644
index 000000000..0d3c22553
--- /dev/null
+++ b/cmd/ethereum/js_test.go
@@ -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")
+ }
+}
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 1efea927f..3b952dd79 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -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,
+ Action: console,
+ Name: "console",
+ Usage: `Ethereum Console: interactive JavaScript environment`,
+ Description: `
+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: `interactive JavaScript console`,
+ Usage: `executes the given JavaScript files in the Ethereum Frontier JavaScript VM`,
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.
+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()
}
diff --git a/cmd/mist/assets/ext/bignumber.min.js b/cmd/mist/assets/ext/bignumber.min.js
index c1627d780..7b63a8a02 100644
--- a/cmd/mist/assets/ext/bignumber.min.js
+++ b/cmd/mist/assets/ext/bignumber.min.js
@@ -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*)?|\.\d+)(e[+-]?\d+)?$/i,lt=String.prototype.trim||function(){return this.replace(/^\s+|\s+$/g,"")},l=1e14,r=14,s=1e7,st=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],it=new t(1),a;t.ROUND_UP=0;t.ROUND_DOWN=1;t.ROUND_CEIL=2;t.ROUND_FLOOR=3;t.ROUND_HALF_UP=4;t.ROUND_HALF_DOWN=5;t.ROUND_HALF_EVEN=6;t.ROUND_HALF_CEIL=7;t.ROUND_HALF_FLOOR=8;t.config=function(){var n,t,g=0,i={},y=arguments,a=y[0],s="config",r=function(n,t,i){return!((e=n<t||n>i)||w(n)!=n&&n!==0)},l=a&&typeof a=="object"?function(){if(a.hasOwnProperty(t))return(n=a[t])!=null}:function(){if(y.length>g)return(n=y[g++])!=null};if(l(t="DECIMAL_PLACES")&&(r(n,0,o)?c=n|0:f(n,t,s)),i[t]=c,l(t="ROUNDING_MODE")&&(r(n,0,8)?h=n|0:f(n,t,s)),i[t]=h,l(t="EXPONENTIAL_AT")&&(r(n,-o,o)?p=-(k=~~(n<0?-n:+n)):!e&&n&&r(n[0],-o,0)&&r(n[1],0,o)?(p=~~n[0],k=~~n[1]):f(n,t,s,1)),i[t]=[p,k],l(t="RANGE")&&(r(n,-o,o)&&~~n?nt=-(v=~~(n<0?-n:+n)):!e&&n&&r(n[0],-o,-1)&&r(n[1],1,o)?(nt=~~n[0],v=~~n[1]):f(n,t,s,1,1)),i[t]=[nt,v],l(t="ERRORS")&&(n===!!n||n===1||n===0?(e=u=0,w=(d=!!n)?parseInt:parseFloat):f(n,t,s,0,0,1)),i[t]=d,l(t="FORMAT"))if(typeof n=="object")b=n;else if(d){i=new Error(s+"() "+t+" not an object: "+n);i.name="BigNumber Error";throw i;}return i[t]=b,i};a=function(){function n(n,t,i){var f,e,o,h,r=0,u=n.length,c=t%s,l=t/s|0;for(n=n.slice();u--;)o=n[u]%s,h=n[u]/s|0,f=l*o+h*c,e=c*o+f%s*s+r,r=(e/i|0)+(f/s|0)+l*h,n[u]=e%i;return r&&n.unshift(r),n}function i(n,t,i,r){var u,f;if(i!=r)f=i>r?1:-1;else for(u=f=0;u<i;u++)if(n[u]!=t[u]){f=n[u]>t[u]?1:-1;break}return f}function u(n,t,i,r){for(var u=0;i--;)n[i]-=u,u=n[i]<t[i]?1:0,n[i]=u*r+n[i]-t[i];for(;!n[0]&&n.length>1;n.shift());}return function(f,e,o,s,h){var nt,ut,a,ot,p,tt,ft,it,et,v,w,st,ht,rt,lt,k,ct,d=f.s==e.s?1:-1,b=f.c,c=e.c;if(!b||!b[0]||!c||!c[0])return new t(!f.s||!e.s||(b?c&&b[0]==c[0]:!c)?NaN:b&&b[0]==0||!c?d*0:d/0);for(it=new t(d),et=it.c=[],ut=f.e-e.e,d=o+ut+1,h||(h=l,ut=(rt=f.e/r,a=rt|0,rt>0||rt===a?a:a-1)-(k=e.e/r,a=k|0,k>0||k===a?a:a-1),d=d/r|0),a=0;c[a]==(b[a]||0);a++);if(c[a]>(b[a]||0)&&ut--,d<0)et.push(1),ot=!0;else{for(rt=b.length,k=c.length,a=0,d+=2,p=g(h/(c[0]+1)),p>1&&(c=n(c,p,h),b=n(b,p,h),k=c.length,rt=b.length),ht=k,v=b.slice(0,k),w=v.length;w<k;v[w++]=0);ct=c.slice();ct.unshift(0);lt=c[0];c[1]>=h/2&&lt++;do p=0,nt=i(c,v,k,w),nt<0?(st=v[0],k!=w&&(st=st*h+(v[1]||0)),p=g(st/lt),p>1?(p>=h&&(p=h-1),tt=n(c,p,h),ft=tt.length,w=v.length,nt=i(tt,v,ft,w),nt==1&&(p--,u(tt,k<ft?ct:c,ft,h))):(p==0&&(nt=p=1),tt=c.slice()),ft=tt.length,ft<w&&tt.unshift(0),u(v,tt,w,h),nt==-1&&(w=v.length,nt=i(c,v,k,w),nt<1&&(p++,u(v,k<w?ct:c,w,h))),w=v.length):nt===0&&(p++,v=[0]),et[a++]=p,nt&&v[0]?v[w++]=b[ht]||0:(v=[b[ht]],w=1);while((ht++<rt||v[0]!=null)&&d--);ot=v[0]!=null;et[0]||et.shift()}if(h==l){for(a=1,d=et[0];d>=10;d/=10,a++);y(it,o+(it.e=a+ut*r-1)+1,s,ot)}else it.e=ut,it.r=+ot;return it}}();i.absoluteValue=i.abs=function(){var n=new t(this);return n.s<0&&(n.s=1),n};i.ceil=function(){return y(new t(this),this.e+1,2)};i.comparedTo=i.cmp=function(n,i){var f,l=this,e=l.c,o=(u=-u,n=new t(n,i)).c,r=l.s,c=n.s,s=l.e,h=n.e;if(!r||!c)return null;if(f=e&&!e[0],i=o&&!o[0],f||i)return f?i?0:-c:r;if(r!=c)return r;if(f=r<0,i=s==h,!e||!o)return i?0:!e^f?1:-1;if(!i)return s>h^f?1:-1;for(r=-1,c=(s=e.length)<(h=o.length)?s:h;++r<c;)if(e[r]!=o[r])return e[r]>o[r]^f?1:-1;return s==h?0:s>h^f?1:-1};i.decimalPlaces=i.dp=function(){var n,t,i=this.c;if(!i)return null;if(n=((t=i.length-1)-g(this.e/r))*r,t=i[t])for(;t%10==0;t/=10,n--);return n<0&&(n=0),n};i.dividedBy=i.div=function(n,i){return u=2,a(this,new t(n,i),c,h)};i.dividedToIntegerBy=i.divToInt=function(n,i){return u=13,a(this,new t(n,i),0,1)};i.equals=i.eq=function(n,t){return u=3,this.cmp(n,t)===0};i.floor=function(){return y(new t(this),this.e+1,3)};i.greaterThan=i.gt=function(n,t){return u=4,this.cmp(n,t)>0};i.greaterThanOrEqualTo=i.gte=function(n,t){return u=5,(t=this.cmp(n,t))==1||t===0};i.isFinite=function(){return!!this.c};i.isInteger=i.isInt=function(){return!!this.c&&g(this.e/r)>this.c.length-2};i.isNaN=function(){return!this.s};i.isNegative=i.isNeg=function(){return this.s<0};i.isZero=function(){return!!this.c&&this.c[0]==0};i.lessThan=i.lt=function(n,t){return u=6,this.cmp(n,t)<0};i.lessThanOrEqualTo=i.lte=function(n,t){return u=7,(t=this.cmp(n,t))==-1||t===0};i.minus=function(n,i){var e,c,v,w,p=this,s=p.s;if(u=8,n=new t(n,i),i=n.s,!s||!i)return new t(NaN);if(s!=i)return n.s=-i,p.plus(n);var y=p.e/r,a=n.e/r,f=p.c,o=n.c;if(!y||!a){if(!f||!o)return f?(n.s=-i,n):new t(o?p:NaN);if(!f[0]||!o[0])return o[0]?(n.s=-i,n):new t(f[0]?p:h==3?-0:0)}if(e=y|0,y=y>0||y===e?e:e-1,e=a|0,a=a>0||a===e?e:e-1,f=f.slice(),s=y-a){for((w=s<0)?(s=-s,v=f):(a=y,v=o),v.reverse(),i=s;i--;v.push(0));v.reverse()}else for(c=(w=(s=f.length)<(i=o.length))?s:i,s=i=0;i<c;i++)if(f[i]!=o[i]){w=f[i]<o[i];break}if(w&&(v=f,f=o,o=v,n.s=-n.s),i=(c=o.length)-(e=f.length),i>0)for(;i--;f[e++]=0);for(i=l-1;c>s;){if(f[--c]<o[c]){for(e=c;e&&!f[--e];f[e]=i);--f[e];f[c]+=l}f[c]-=o[c]}for(;f[0]==0;f.shift(),--a);return f[0]?et(n,f,a):(n.s=h==3?-1:1,n.c=[n.e=0],n)};i.modulo=i.mod=function(n,i){u=9;var r=this,f=r.c,e=(n=new t(n,i)).c,o=r.s,s=n.s;return(i=!o||!s||e&&!e[0],i||f&&!f[0])?new t(i?NaN:r):(r.s=n.s=1,i=n.cmp(r)==1,r.s=o,n.s=s,i?new t(r):r.minus(a(r,n,0,1).times(n)))};i.negated=i.neg=function(){var n=new t(this);return n.s=-n.s||null,n};i.plus=function(n,i){var h,a=this,f=a.s;if(u=10,n=new t(n,i),i=n.s,!f||!i)return new t(NaN);if(f!=i)return n.s=-i,a.minus(n);var c=a.e/r,o=n.e/r,e=a.c,s=n.c;if(!c||!o){if(!e||!s)return new t(f/0);if(!e[0]||!s[0])return s[0]?n:new t(e[0]?a:f*0)}if(f=c|0,c=c>0||c===f?f:f-1,f=o|0,o=o>0||o===f?f:f-1,e=e.slice(),f=c-o){for(f>0?(o=c,h=s):(f=-f,h=e),h.reverse();f--;h.push(0));h.reverse()}for(f=e.length,i=s.length,f-i<0&&(h=s,s=e,e=h,i=f),f=0;i;)f=(e[--i]=e[i]+s[i]+f)/l|0,e[i]%=l;return f&&(e.unshift(f),++o),et(n,e,o)};i.round=function(n,i){return n=n==null||((e=n<0||n>o)||w(n)!=n)&&!f(n,"decimal places","round")?0:n|0,i=i==null||((e=i<0||i>8)||w(i)!=i&&i!==0)&&!f(i,"mode","round")?h:i|0,y(new t(this),n+this.e+1,i)};i.squareRoot=i.sqrt=function(){var v,i,r,s,f,e=this,o=e.c,n=e.s,u=e.e,l=c+4,p=new t("0.5");if(n!==1||!o||!o[0])return new t(!n||n<0&&(!o||o[0])?NaN:o?e:1/0);if(n=Math.sqrt(+e),n==0||n==1/0?(i=tt(o),(i.length+u)%2==0&&(i+="0"),n=Math.sqrt(i),u=g((u+1)/2)-(u<0||u%2),n==1/0?i="1e"+u:(i=n.toExponential(),i=i.slice(0,i.indexOf("e")+1)+u),r=new t(i)):r=new t(n.toString()),r.c[0])for(u=r.e,n=u+l,n<3&&(n=0);;)if(f=r,r=p.times(f.plus(a(e,f,l,1))),tt(f.c).slice(0,n)===(i=tt(r.c)).slice(0,n))if(r.e<u&&--n,i=i.slice(n-3,n+1),i!="9999"&&(s||i!="4999")){+i&&(+i.slice(1)||i.charAt(0)!="5")||(y(r,r.e+c+2,1),v=!r.times(r).eq(e));break}else{if(!s&&(y(f,f.e+c+2,0),f.times(f).eq(e))){r=f;break}l+=4;n+=4;s=1}return y(r,r.e+c+1,h,v)};i.times=function(n,i){var p,e,w,b,a,y,k,d,g,nt=this,o=nt.c,h=(u=11,n=new t(n,i)).c,c=nt.e/r,f=n.e/r,v=nt.s;if(n.s=v==(i=n.s)?1:-1,!c&&(!o||!o[0])||!f&&(!h||!h[0]))return new t(!v||!i||o&&!o[0]&&!h||h&&!h[0]&&!o?NaN:!o||!h?n.s/0:n.s*0);for(e=(e=c|0,c>0||c===e?e:e-1)+(e=f|0,f>0||f===e?e:e-1),v=o.length,i=h.length,v<i&&(a=o,o=h,h=a,f=v,v=i,i=f),f=v+i,a=[];f--;a.push(0));for(c=i;--c>=0;){for(p=0,f=v+c,w=v,d=h[c]%s,g=h[c]/s|0;f>c;)y=o[--w]%s,k=o[w]/s|0,b=g*y+k*d,y=d*y+b%s*s+a[f]+p,p=(y/l|0)+(b/s|0)+g*k,a[f--]=y%l;a[f]=p}return p?++e:a.shift(),et(n,a,e)};i.toExponential=function(n){var t=this;return t.c?rt(t,n==null||((e=n<0||n>o)||w(n)!=n&&n!==0)&&!f(n,"decimal places","toExponential")?null:n|0,1):t.toString()};i.toFixed=function(n){var t,i=this,r=p,u=k;return n=n==null||((e=n<0||n>o)||w(n)!=n&&n!==0)&&!f(n,"decimal places","toFixed")?null:i.e+(n|0),p=-(k=1/0),n!=null&&i.c?(t=rt(i,n),i.s<0&&i.c&&(i.c[0]?t.indexOf("-")<0&&(t="-"+t):t=t.replace("-",""))):t=i.toString(),p=r,k=u,t};i.toFormat=function(n){var f=this;if(!f.c)return f.toString();var t,h=f.s<0,c=b.groupSeparator,r=+b.groupSize,u=+b.secondaryGroupSize,l=f.toFixed(n).split("."),i=l[0],s=l[1],e=h?i.slice(1):i,o=e.length;if(u&&(t=r,r=u,u=t,o-=t),r>0&&o>0){for(t=o%r||r,i=e.substr(0,t);t<o;t+=r)i+=c+e.substr(t,r);u>0&&(i+=c+e.slice(t));h&&(i="-"+i)}return s?i+b.decimalSeparator+((u=+b.fractionGroupSize)?s.replace(new RegExp("\\d{"+u+"}\\B","g"),"$&"+b.fractionGroupSeparator):s):i};i.toFraction=function(n){var ut,c,i,w,k,o,s,nt,rt,l=c=new t(it),y=s=new t(it),b=this,ft=b.c,p=new t(it);if(!ft)return b.toString();for(rt=tt(ft),w=p.e=rt.length-b.e-1,p.c[0]=st[(k=w%r)<0?r+k:k],(n==null||(!(u=12,o=new t(n)).s||(e=o.cmp(l)<0||!o.c)||d&&g(o.e/r)<o.c.length-1)&&!f(n,"max denominator","toFraction")||(n=o).cmp(p)>0)&&(n=w>0?p:l),k=v,v=1/0,o=new t(rt),s.c[0]=0;;){if(nt=a(o,p,0,1),i=c.plus(nt.times(y)),i.cmp(n)==1)break;c=y;y=i;l=s.plus(nt.times(i=l));s=i;p=o.minus(nt.times(i=p));o=i}return i=a(n.minus(c),y,0,1),s=s.plus(i.times(l)),c=c.plus(i.times(y)),s.s=l.s=b.s,w*=2,ut=a(l,y,w,h).minus(b).abs().cmp(a(s,c,w,h).minus(b).abs())<1?[l.toString(),y.toString()]:[s.toString(),c.toString()],v=k,ut};i.toNumber=function(){var n=this;return+n||(n.s?0*n.s:NaN)};i.toPower=i.pow=function(n){var i=n*0==0?~~n:n,r=new t(this),u=new t(it);if(((e=n<-ot||n>ot)&&(i=n/0)||w(n)!=n&&n!==0&&!(i=NaN))&&!f(n,"exponent","pow")||!i)return new t(Math.pow(+r,i));for(i=i<0?-i:i;;){if(i&1&&(u=u.times(r)),i>>=1,!i)break;r=r.times(r)}return n<0?it.div(u):u};i.toPrecision=function(n){var t=this;return n==null||((e=n<1||n>o)||w(n)!=n)&&!f(n,"precision","toPrecision")||!t.c?t.toString():rt(t,--n|0,2)};i.toString=function(n){var r,t,o,u=this,i=u.e;if(i===null)t=u.s?"Infinity":"NaN";else{if(n==r&&(i<=p||i>=k))return rt(u,r,1);if(t=tt(u.c),i<0){for(;++i;t="0"+t);t="0."+t}else if(o=t.length,i>0)if(++i>o)for(i-=o;i--;t+="0");else i<o&&(t=t.slice(0,i)+"."+t.slice(i));else if(r=t.charAt(0),o>1)t=r+"."+t.slice(1);else if(r=="0")return r;if(n!=null)if((e=!(n>=2&&n<65))||n!=~~n&&d)f(n,"base","toS");else if(t=ct(t,n|0,10,u.s),t=="0")return t}return u.s<0?"-"+t:t};i.valueOf=i.toJSON=function(){return this.toString()};typeof module!="undefined"&&module.exports?module.exports=t:typeof define=="function"&&define.amd?define(function(){return t}):n.BigNumber=t})(this) \ No newline at end of file
+/* 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|e?G=-(z=0|(0>e?-e:e)):j&&L(2,n+" cannot be zero",e))),r[n]=[G,z],f(n="ERRORS")&&(e===!!e||1===e||0===e?(M=0,H=(j=!!e)?F:o):j&&L(2,n+w,e)),r[n]=j,f(n="CRYPTO")&&(e===!!e||1===e||0===e?(V=!(!e||!h||"object"!=typeof h),e&&!V&&j&&L(2,"crypto unavailable",h)):j&&L(2,n+w,e)),r[n]=V,f(n="MODULO_MODE")&&H(e,0,9,2,n)&&(W=0|e),r[n]=W,f(n="POW_PRECISION")&&H(e,0,E,2,n)&&(J=0|e),r[n]=J,f(n="FORMAT")&&("object"==typeof e?X=e:j&&L(2,n+" not an object",e)),r[n]=X,r},a.max=function(){return x(arguments,T.lt)},a.min=function(){return x(arguments,T.gt)},a.random=function(){var e=9007199254740992,n=Math.random()*e&2097151?function(){return m(Math.random()*e)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(e){var t,r,i,o,u,s=0,f=[],l=new a(q);if(e=null!=e&&H(e,0,E,14)?0|e:P,o=d(e/y),V)if(h&&h.getRandomValues){for(t=h.getRandomValues(new Uint32Array(o*=2));o>s;)u=131072*t[s]+(t[s+1]>>>11),u>=9e15?(r=h.getRandomValues(new Uint32Array(2)),t[s]=r[0],t[s+1]=r[1]):(f.push(u%1e14),s+=2);s=o/2}else if(h&&h.randomBytes){for(t=h.randomBytes(o*=7);o>s;)u=281474976710656*(31&t[s])+1099511627776*t[s+1]+4294967296*t[s+2]+16777216*t[s+3]+(t[s+4]<<16)+(t[s+5]<<8)+t[s+6],u>=9e15?h.randomBytes(7).copy(t,s):(f.push(u%1e14),s+=7);s=o/7}else j&&L(14,"crypto unavailable",h);if(!s)for(;o>s;)u=n(),9e15>u&&(f[s++]=u%1e14);for(o=f[--s],e%=y,o&&e&&(u=R[y-e],f[s]=m(o/u)*u);0===f[s];f.pop(),s--);if(0>s)f=[i=0];else{for(i=-1;0===f[0];f.shift(),i-=y);for(s=1,u=f[0];u>=10;u/=10,s++);y>s&&(i-=y-s)}return l.e=i,l.c=f,l}}(),C=function(){function e(e,n,t){var r,i,o,u,s=0,f=e.length,l=n%A,c=n/A|0;for(e=e.slice();f--;)o=e[f]%A,u=e[f]/A|0,r=c*o+u*l,i=l*o+r%A*A+s,s=(i/t|0)+(r/A|0)+c*u,e[f]=i%t;return s&&e.unshift(s),e}function n(e,n,t,r){var i,o;if(t!=r)o=t>r?1:-1;else for(i=o=0;t>i;i++)if(e[i]!=n[i]){o=e[i]>n[i]?1:-1;break}return o}function r(e,n,t,r){for(var i=0;t--;)e[t]-=i,i=e[t]<n[t]?1:0,e[t]=i*r+e[t]-n[t];for(;!e[0]&&e.length>1;e.shift());}return function(i,o,u,s,f){var l,c,h,g,p,d,w,v,b,O,S,R,A,E,D,_,x,F=i.s==o.s?1:-1,I=i.c,L=o.c;if(!(I&&I[0]&&L&&L[0]))return new a(i.s&&o.s&&(I?!L||I[0]!=L[0]:L)?I&&0==I[0]||!L?0*F:F/0:0/0);for(v=new a(F),b=v.c=[],c=i.e-o.e,F=u+c+1,f||(f=N,c=t(i.e/y)-t(o.e/y),F=F/y|0),h=0;L[h]==(I[h]||0);h++);if(L[h]>(I[h]||0)&&c--,0>F)b.push(1),g=!0;else{for(E=I.length,_=L.length,h=0,F+=2,p=m(f/(L[0]+1)),p>1&&(L=e(L,p,f),I=e(I,p,f),_=L.length,E=I.length),A=_,O=I.slice(0,_),S=O.length;_>S;O[S++]=0);x=L.slice(),x.unshift(0),D=L[0],L[1]>=f/2&&D++;do p=0,l=n(L,O,_,S),0>l?(R=O[0],_!=S&&(R=R*f+(O[1]||0)),p=m(R/D),p>1?(p>=f&&(p=f-1),d=e(L,p,f),w=d.length,S=O.length,l=n(d,O,w,S),1==l&&(p--,r(d,w>_?x:L,w,f))):(0==p&&(l=p=1),d=L.slice()),w=d.length,S>w&&d.unshift(0),r(O,d,S,f),-1==l&&(S=O.length,l=n(L,O,_,S),1>l&&(p++,r(O,S>_?x:L,S,f))),S=O.length):0===l&&(p++,O=[0]),b[h++]=p,l&&O[0]?O[S++]=I[A]||0:(O=[I[A]],S=1);while((A++<E||null!=O[0])&&F--);g=null!=O[0],b[0]||b.shift()}if(f==N){for(h=1,F=b[0];F>=10;F/=10,h++);U(v,u+(v.e=h+c*y-1)+1,s,g)}else v.e=c,v.r=+g;return v}}(),g=function(){var e=/^(-?)0([xbo])(\w[\w.]*$)/i,n=/^([^.]+)\.$/,t=/^\.([^.]+)$/,r=/^-?(Infinity|NaN)$/,i=/^\s*\+([\w.])|^\s+|\s+$/g;return function(o,u,s,f){var l,c=s?u:u.replace(i,"$1");if(r.test(c))o.s=isNaN(c)?null:0>c?-1:1;else{if(!s&&(c=c.replace(e,function(e,n,t){return l="x"==(t=t.toLowerCase())?16:"b"==t?2:8,f&&f!=l?e:n}),f&&(l=f,c=c.replace(n,"$1").replace(t,"0.$1")),u!=c))return new a(c,l);j&&L(M,"not a"+(f?" base "+f:"")+" number",u),o.s=null}o.c=o.e=null,M=0}}(),T.absoluteValue=T.abs=function(){var e=new a(this);return e.s<0&&(e.s=1),e},T.ceil=function(){return U(new a(this),this.e+1,2)},T.comparedTo=T.cmp=function(e,n){return M=1,i(this,new a(e,n))},T.decimalPlaces=T.dp=function(){var e,n,r=this.c;if(!r)return null;if(e=((n=r.length-1)-t(this.e/y))*y,n=r[n])for(;n%10==0;n/=10,e--);return 0>e&&(e=0),e},T.dividedBy=T.div=function(e,n){return M=3,C(this,new a(e,n),P,k)},T.dividedToIntegerBy=T.divToInt=function(e,n){return M=4,C(this,new a(e,n),0,1)},T.equals=T.eq=function(e,n){return M=5,0===i(this,new a(e,n))},T.floor=function(){return U(new a(this),this.e+1,3)},T.greaterThan=T.gt=function(e,n){return M=6,i(this,new a(e,n))>0},T.greaterThanOrEqualTo=T.gte=function(e,n){return M=7,1===(n=i(this,new a(e,n)))||0===n},T.isFinite=function(){return!!this.c},T.isInteger=T.isInt=function(){return!!this.c&&t(this.e/y)>this.c.length-2},T.isNaN=function(){return!this.s},T.isNegative=T.isNeg=function(){return this.s<0},T.isZero=function(){return!!this.c&&0==this.c[0]},T.lessThan=T.lt=function(e,n){return M=8,i(this,new a(e,n))<0},T.lessThanOrEqualTo=T.lte=function(e,n){return M=9,-1===(n=i(this,new a(e,n)))||0===n},T.minus=T.sub=function(e,n){var r,i,o,u,s=this,f=s.s;if(M=10,e=new a(e,n),n=e.s,!f||!n)return new a(0/0);if(f!=n)return e.s=-n,s.plus(e);var l=s.e/y,c=e.e/y,h=s.c,g=e.c;if(!l||!c){if(!h||!g)return h?(e.s=-n,e):new a(g?s:0/0);if(!h[0]||!g[0])return g[0]?(e.s=-n,e):new a(h[0]?s:3==k?-0:0)}if(l=t(l),c=t(c),h=h.slice(),f=l-c){for((u=0>f)?(f=-f,o=h):(c=l,o=g),o.reverse(),n=f;n--;o.push(0));o.reverse()}else for(i=(u=(f=h.length)<(n=g.length))?f:n,f=n=0;i>n;n++)if(h[n]!=g[n]){u=h[n]<g[n];break}if(u&&(o=h,h=g,g=o,e.s=-e.s),n=(i=g.length)-(r=h.length),n>0)for(;n--;h[r++]=0);for(n=N-1;i>f;){if(h[--i]<g[i]){for(r=i;r&&!h[--r];h[r]=n);--h[r],h[i]+=N}h[i]-=g[i]}for(;0==h[0];h.shift(),--c);return h[0]?I(e,h,c):(e.s=3==k?-1:1,e.c=[e.e=0],e)},T.modulo=T.mod=function(e,n){var t,r,i=this;return M=11,e=new a(e,n),!i.c||!e.s||e.c&&!e.c[0]?new a(0/0):!e.c||i.c&&!i.c[0]?new a(i):(9==W?(r=e.s,e.s=1,t=C(i,e,0,3),e.s=r,t.s*=r):t=C(i,e,0,W),i.minus(t.times(e)))},T.negated=T.neg=function(){var e=new a(this);return e.s=-e.s||null,e},T.plus=T.add=function(e,n){var r,i=this,o=i.s;if(M=12,e=new a(e,n),n=e.s,!o||!n)return new a(0/0);if(o!=n)return e.s=-n,i.minus(e);var u=i.e/y,s=e.e/y,f=i.c,l=e.c;if(!u||!s){if(!f||!l)return new a(o/0);if(!f[0]||!l[0])return l[0]?e:new a(f[0]?i:0*o)}if(u=t(u),s=t(s),f=f.slice(),o=u-s){for(o>0?(s=u,r=l):(o=-o,r=f),r.reverse();o--;r.push(0));r.reverse()}for(o=f.length,n=l.length,0>o-n&&(r=l,l=f,f=r,n=o),o=0;n;)o=(f[--n]=f[n]+l[n]+o)/N|0,f[n]%=N;return o&&(f.unshift(o),++s),I(e,f,s)},T.precision=T.sd=function(e){var n,t,r=this,i=r.c;if(null!=e&&e!==!!e&&1!==e&&0!==e&&(j&&L(13,"argument"+w,e),e!=!!e&&(e=null)),!i)return null;if(t=i.length-1,n=t*y+1,t=i[t]){for(;t%10==0;t/=10,n--);for(t=i[0];t>=10;t/=10,n++);}return e&&r.e+1>n&&(n=r.e+1),n},T.round=function(e,n){var t=new a(this);return(null==e||H(e,0,E,15))&&U(t,~~e+this.e+1,null!=n&&H(n,0,8,15,v)?0|n:k),t},T.shift=function(e){var n=this;return H(e,-S,S,16,"argument")?n.times("1e"+c(e)):new a(n.c&&n.c[0]&&(-S>e||e>S)?n.s*(0>e?0:1/0):n)},T.squareRoot=T.sqrt=function(){var e,n,i,o,u,s=this,f=s.c,l=s.s,c=s.e,h=P+4,g=new a("0.5");if(1!==l||!f||!f[0])return new a(!l||0>l&&(!f||f[0])?0/0:f?s:1/0);if(l=Math.sqrt(+s),0==l||l==1/0?(n=r(f),(n.length+c)%2==0&&(n+="0"),l=Math.sqrt(n),c=t((c+1)/2)-(0>c||c%2),l==1/0?n="1e"+c:(n=l.toExponential(),n=n.slice(0,n.indexOf("e")+1)+c),i=new a(n)):i=new a(l+""),i.c[0])for(c=i.e,l=c+h,3>l&&(l=0);;)if(u=i,i=g.times(u.plus(C(s,u,h,1))),r(u.c).slice(0,l)===(n=r(i.c)).slice(0,l)){if(i.e<c&&--l,n=n.slice(l-3,l+1),"9999"!=n&&(o||"4999"!=n)){(!+n||!+n.slice(1)&&"5"==n.charAt(0))&&(U(i,i.e+P+2,1),e=!i.times(i).eq(s));break}if(!o&&(U(u,u.e+P+2,0),u.times(u).eq(s))){i=u;break}h+=4,l+=4,o=1}return U(i,i.e+P+1,k,e)},T.times=T.mul=function(e,n){var r,i,o,u,s,f,l,c,h,g,p,d,m,w,v,b=this,O=b.c,S=(M=17,e=new a(e,n)).c;if(!(O&&S&&O[0]&&S[0]))return!b.s||!e.s||O&&!O[0]&&!S||S&&!S[0]&&!O?e.c=e.e=e.s=null:(e.s*=b.s,O&&S?(e.c=[0],e.e=0):e.c=e.e=null),e;for(i=t(b.e/y)+t(e.e/y),e.s*=b.s,l=O.length,g=S.length,g>l&&(m=O,O=S,S=m,o=l,l=g,g=o),o=l+g,m=[];o--;m.push(0));for(w=N,v=A,o=g;--o>=0;){for(r=0,p=S[o]%v,d=S[o]/v|0,s=l,u=o+s;u>o;)c=O[--s]%v,h=O[s]/v|0,f=d*c+h*p,c=p*c+f%v*v+m[u]+r,r=(c/w|0)+(f/v|0)+d*h,m[u--]=c%w;m[u]=r}return r?++i:m.shift(),I(e,m,i)},T.toDigits=function(e,n){var t=new a(this);return e=null!=e&&H(e,1,E,18,"precision")?0|e:null,n=null!=n&&H(n,0,8,18,v)?0|n:k,e?U(t,e,n):t},T.toExponential=function(e,n){return _(this,null!=e&&H(e,0,E,19)?~~e+1:null,n,19)},T.toFixed=function(e,n){return _(this,null!=e&&H(e,0,E,20)?~~e+this.e+1:null,n,20)},T.toFormat=function(e,n){var t=_(this,null!=e&&H(e,0,E,21)?~~e+this.e+1:null,n,21);if(this.c){var r,i=t.split("."),o=+X.groupSize,u=+X.secondaryGroupSize,s=X.groupSeparator,f=i[0],l=i[1],c=this.s<0,a=c?f.slice(1):f,h=a.length;if(u&&(r=o,o=u,u=r,h-=r),o>0&&h>0){for(r=h%o||o,f=a.substr(0,r);h>r;r+=o)f+=s+a.substr(r,o);u>0&&(f+=s+a.slice(r)),c&&(f="-"+f)}t=l?f+X.decimalSeparator+((u=+X.fractionGroupSize)?l.replace(new RegExp("\\d{"+u+"}\\B","g"),"$&"+X.fractionGroupSeparator):l):f}return t},T.toFraction=function(e){var n,t,i,o,u,s,f,l,c,h=j,g=this,p=g.c,d=new a(q),m=t=new a(q),w=f=new a(q);if(null!=e&&(j=!1,s=new a(e),j=h,(!(h=s.isInt())||s.lt(q))&&(j&&L(22,"max denominator "+(h?"out of range":"not an integer"),e),e=!h&&s.c&&U(s,s.e+1,1).gte(q)?s:null)),!p)return g.toString();for(c=r(p),o=d.e=c.length-g.e-1,d.c[0]=R[(u=o%y)<0?y+u:u],e=!e||s.cmp(d)>0?o>0?d:m:s,u=z,z=1/0,s=new a(c),f.c[0]=0;l=C(s,d,0,1),i=t.plus(l.times(w)),1!=i.cmp(e);)t=w,w=i,m=f.plus(l.times(i=m)),f=i,d=s.minus(l.times(i=d)),s=i;return i=C(e.minus(t),w,0,1),f=f.plus(i.times(m)),t=t.plus(i.times(w)),f.s=m.s=g.s,o*=2,n=C(m,w,o,k).minus(g).abs().cmp(C(f,t,o,k).minus(g).abs())<1?[m.toString(),w.toString()]:[f.toString(),t.toString()],z=u,n},T.toNumber=function(){var e=this;return+e||(e.s?0*e.s:0/0)},T.toPower=T.pow=function(e){var n,t,r=m(0>e?-e:+e),i=this;if(!H(e,-S,S,23,"exponent")&&(!isFinite(e)||r>S&&(e/=0)||parseFloat(e)!=e&&!(e=0/0)))return new a(Math.pow(+i,e));for(n=J?d(J/y+2):0,t=new a(q);;){if(r%2){if(t=t.times(i),!t.c)break;n&&t.c.length>n&&(t.c.length=n)}if(r=m(r/2),!r)break;i=i.times(i),n&&i.c&&i.c.length>n&&(i.c.length=n)}return 0>e&&(t=q.div(t)),n?U(t,J,k):t},T.toPrecision=function(e,n){return _(this,null!=e&&H(e,1,E,24,"precision")?0|e:null,n,24)},T.toString=function(e){var n,t=this,i=t.s,o=t.e;return null===o?i?(n="Infinity",0>i&&(n="-"+n)):n="NaN":(n=r(t.c),n=null!=e&&H(e,2,64,25,"base")?D(l(n,o),0|e,10,i):B>=o||o>=$?f(n,o):l(n,o),0>i&&t.c[0]&&(n="-"+n)),n},T.truncated=T.trunc=function(){return U(new a(this),this.e+1,1)},T.valueOf=T.toJSON=function(){return this.toString()},null!=e&&a.config(e),a}function t(e){var n=0|e;return e>0||e===n?n:n-1}function r(e){for(var n,t,r=1,i=e.length,o=e[0]+"";i>r;){for(n=e[r++]+"",t=y-n.length;t--;n="0"+n);o+=n}for(i=o.length;48===o.charCodeAt(--i););return o.slice(0,i+1||1)}function i(e,n){var t,r,i=e.c,o=n.c,u=e.s,s=n.s,f=e.e,l=n.e;if(!u||!s)return null;if(t=i&&!i[0],r=o&&!o[0],t||r)return t?r?0:-s:u;if(u!=s)return u;if(t=0>u,r=f==l,!i||!o)return r?0:!i^t?1:-1;if(!r)return f>l^t?1:-1;for(s=(f=i.length)<(l=o.length)?f:l,u=0;s>u;u++)if(i[u]!=o[u])return i[u]>o[u]^t?1:-1;return f==l?0:f>l^t?1:-1}function o(e,n,t){return(e=c(e))>=n&&t>=e}function u(e){return"[object Array]"==Object.prototype.toString.call(e)}function s(e,n,t){for(var r,i,o=[0],u=0,s=e.length;s>u;){for(i=o.length;i--;o[i]*=n);for(o[r=0]+=O.indexOf(e.charAt(u++));r<o.length;r++)o[r]>t-1&&(null==o[r+1]&&(o[r+1]=0),o[r+1]+=o[r]/t|0,o[r]%=t)}return o.reverse()}function f(e,n){return(e.length>1?e.charAt(0)+"."+e.slice(1):e)+(0>n?"e":"e+")+n}function l(e,n){var t,r;if(0>n){for(r="0.";++n;r+="0");e=r+e}else if(t=e.length,++n>t){for(r="0",n-=t;--n;r+="0");e+=r}else t>n&&(e=e.slice(0,n)+"."+e.slice(n));return e}function c(e){return e=parseFloat(e),0>e?d(e):m(e)}var a,h,g,p=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,d=Math.ceil,m=Math.floor,w=" not a boolean or binary digit",v="rounding mode",b="number type has more than 15 significant digits",O="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",N=1e14,y=14,S=9007199254740991,R=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],A=1e7,E=1e9;if(a=n(),"function"==typeof define&&define.amd)define(function(){return a});else if("undefined"!=typeof module&&module.exports){if(module.exports=a,!h)try{h=require("crypto")}catch(D){}}else e.BigNumber=a}(this);
+//# sourceMappingURL=doc/bignumber.js.map \ No newline at end of file
diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml
index 8558ebd51..bf83dc3b2 100644
--- a/cmd/mist/assets/qml/main.qml
+++ b/cmd/mist/assets/qml/main.qml
@@ -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);
}
}
@@ -207,15 +206,6 @@ ApplicationWindow {
}
MenuItem {
- text: "Run JS file"
- onTriggered: {
- generalFileDialog.show(true, function(path) {
- eth.evalJavascriptFile(path)
- })
- }
- }
-
- MenuItem {
text: "Dump state"
onTriggered: {
generalFileDialog.show(false, function(path) {
@@ -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-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-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
diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go
index 476b441c8..19ad09454 100644
--- a/cmd/mist/gui.go
+++ b/cmd/mist/gui.go
@@ -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
}
diff --git a/cmd/mist/main.go b/cmd/mist/main.go
index 256c08691..1c51233e3 100644
--- a/cmd/mist/main.go
+++ b/cmd/mist/main.go
@@ -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
})
}
diff --git a/cmd/mist/ui_lib.go b/cmd/mist/ui_lib.go
index 90237d4cb..34ce56e77 100644
--- a/cmd/mist/ui_lib.go
+++ b/cmd/mist/ui_lib.go
@@ -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 {
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 95666e3c9..42256903e 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -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 {