aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Van de Sande <alex.vandesande@ethdev.com>2015-03-04 21:04:07 +0800
committerAlexandre Van de Sande <alex.vandesande@ethdev.com>2015-03-04 21:04:07 +0800
commit5f25c117eb6a1145b18fc13ebc03e4dc570b908e (patch)
treef5296850d29c08179ac9f51c925463d880e2db08
parentcf880f78d5e85d563654ac8277c1d51bf8c382c2 (diff)
parenta56243075a7527d65d14c4cf3480029feb0a1e3f (diff)
downloaddexon-5f25c117eb6a1145b18fc13ebc03e4dc570b908e.tar
dexon-5f25c117eb6a1145b18fc13ebc03e4dc570b908e.tar.gz
dexon-5f25c117eb6a1145b18fc13ebc03e4dc570b908e.tar.bz2
dexon-5f25c117eb6a1145b18fc13ebc03e4dc570b908e.tar.lz
dexon-5f25c117eb6a1145b18fc13ebc03e4dc570b908e.tar.xz
dexon-5f25c117eb6a1145b18fc13ebc03e4dc570b908e.tar.zst
dexon-5f25c117eb6a1145b18fc13ebc03e4dc570b908e.zip
Merge branch 'develop' into ui
-rw-r--r--.travis.yml4
-rw-r--r--Dockerfile12
-rw-r--r--Godeps/Godeps.json11
-rw-r--r--Godeps/_workspace/src/bitbucket.org/kardianos/osext/LICENSE20
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/LICENSE27
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/README.md14
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext.go (renamed from Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext.go)5
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_plan9.go (renamed from Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_plan9.go)18
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_procfs.go (renamed from Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_procfs.go)7
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go (renamed from Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_sysctl.go)0
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_test.go (renamed from Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_test.go)0
-rw-r--r--Godeps/_workspace/src/github.com/kardianos/osext/osext_windows.go (renamed from Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_windows.go)0
-rw-r--r--README.md112
-rw-r--r--accounts/account_manager.go55
-rw-r--r--accounts/accounts_test.go68
-rw-r--r--cmd/ethereum/flags.go99
-rw-r--r--cmd/ethereum/main.go47
-rw-r--r--cmd/ethereum/repl/repl.go1
-rw-r--r--cmd/mist/assets/examples/coin.html24
-rw-r--r--cmd/mist/assets/examples/info.html7
-rw-r--r--cmd/mist/assets/ext/ethereum.js/dist/ethereum.js734
-rw-r--r--cmd/mist/assets/qml/main.qml2
-rw-r--r--cmd/mist/ext_app.go5
-rw-r--r--cmd/mist/flags.go97
-rw-r--r--cmd/mist/main.go8
-rw-r--r--cmd/utils/cmd.go46
-rw-r--r--core/block_processor.go15
-rw-r--r--core/chain_manager.go31
-rw-r--r--core/filter.go35
-rw-r--r--core/genesis.go2
-rw-r--r--core/state_transition.go4
-rw-r--r--crypto/key_store_plain.go14
-rw-r--r--crypto/key_store_test.go9
-rw-r--r--eth/backend.go32
-rw-r--r--eth/block_pool.go4
-rw-r--r--eth/block_pool_test.go6
-rw-r--r--eth/protocol.go7
-rw-r--r--eth/protocol_test.go4
-rw-r--r--ethutil/common.go50
-rw-r--r--event/filter/eth_filter.go3
-rwxr-xr-xinstall.sh53
-rw-r--r--javascript/javascript_runtime.go58
-rw-r--r--javascript/js_lib.go2
-rw-r--r--javascript/types.go15
-rw-r--r--logger/types.go9
-rw-r--r--miner/miner.go7
-rw-r--r--miner/worker.go28
-rw-r--r--rpc/api.go (renamed from rpc/packages.go)259
-rw-r--r--rpc/api_test.go (renamed from rpc/packages_test.go)1
-rw-r--r--rpc/args.go91
-rw-r--r--rpc/http/server.go10
-rw-r--r--rpc/messages.go (renamed from rpc/message.go)162
-rw-r--r--rpc/util.go4
-rw-r--r--rpc/ws/server.go121
-rw-r--r--state/dump.go9
-rw-r--r--state/state_object.go21
-rw-r--r--state/statedb.go18
-rw-r--r--ui/filter.go76
-rw-r--r--ui/frontend.go18
-rw-r--r--ui/qt/filter.go29
-rw-r--r--vm/vm.go23
-rw-r--r--vm/vm_jit.go25
-rw-r--r--whisper/whisper.go4
-rw-r--r--xeth/state.go (renamed from xeth/world.go)13
-rw-r--r--xeth/xeth.go32
65 files changed, 1402 insertions, 1325 deletions
diff --git a/.travis.yml b/.travis.yml
index 5499cf257..c4e39b05e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,8 @@
language: go
go:
- - 1.4.1
+ - 1.4.2
before_install:
- - sudo add-apt-repository ppa:beineri/opt-qt54 -y
+ - sudo add-apt-repository ppa:beineri/opt-qt541 -y
- sudo apt-get update -qq
- sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine
install:
diff --git a/Dockerfile b/Dockerfile
index 1f6555d1a..b7e23aaab 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:14.04.1
+FROM ubuntu:14.04.2
## Environment setup
ENV HOME /root
@@ -12,22 +12,22 @@ ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y git mercurial build-essential software-properties-common wget pkg-config libgmp3-dev libreadline6-dev libpcre3-dev libpcre++-dev
-## Install Qt5.4 (not required for CLI)
-# RUN add-apt-repository ppa:beineri/opt-qt54-trusty -y
+## Install Qt5.4.1 (not required for CLI)
+# RUN add-apt-repository ppa:beineri/opt-qt541-trusty -y
# RUN apt-get update -y
# RUN apt-get install -y qt54quickcontrols qt54webengine mesa-common-dev libglu1-mesa-dev
# ENV PKG_CONFIG_PATH /opt/qt54/lib/pkgconfig
# Install Golang
-RUN wget https://storage.googleapis.com/golang/go1.4.1.linux-amd64.tar.gz
+RUN wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz
RUN tar -C /usr/local -xzf go*.tar.gz && go version
# this is a workaround, to make sure that docker's cache is invalidated whenever the git repo changes
ADD https://api.github.com/repos/ethereum/go-ethereum/git/refs/heads/develop file_does_not_exist
## Fetch and install go-ethereum
-RUN go get -v github.com/tools/godep
-RUN go get -v -d github.com/ethereum/go-ethereum/...
+RUN go get github.com/tools/godep
+RUN go get -d github.com/ethereum/go-ethereum/...
WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum
RUN git checkout develop
RUN godep restore
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 9b7306530..b66ea932f 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -1,16 +1,11 @@
{
"ImportPath": "github.com/ethereum/go-ethereum",
- "GoVersion": "go1.4.1",
+ "GoVersion": "go1.4.2",
"Packages": [
"./..."
],
"Deps": [
{
- "ImportPath": "bitbucket.org/kardianos/osext",
- "Comment": "null-13",
- "Rev": "5d3ddcf53a508cc2f7404eaebf546ef2cb5cdb6e"
- },
- {
"ImportPath": "code.google.com/p/go-uuid/uuid",
"Comment": "null-12",
"Rev": "7dda39b2e7d5e265014674c5af696ba4186679e9"
@@ -38,6 +33,10 @@
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
},
{
+ "ImportPath": "github.com/kardianos/osext",
+ "Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
+ },
+ {
"ImportPath": "github.com/obscuren/otto",
"Rev": "cf13cc4228c5e5ce0fe27a7aea90bc10091c4f19"
},
diff --git a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/LICENSE b/Godeps/_workspace/src/bitbucket.org/kardianos/osext/LICENSE
deleted file mode 100644
index 18527a28f..000000000
--- a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2012 Daniel Theophanes
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
-
- 3. This notice may not be removed or altered from any source
- distribution.
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/LICENSE b/Godeps/_workspace/src/github.com/kardianos/osext/LICENSE
new file mode 100644
index 000000000..744875676
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/kardianos/osext/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Godeps/_workspace/src/github.com/kardianos/osext/README.md b/Godeps/_workspace/src/github.com/kardianos/osext/README.md
new file mode 100644
index 000000000..820e1ecb5
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/kardianos/osext/README.md
@@ -0,0 +1,14 @@
+### Extensions to the "os" package.
+
+## Find the current Executable and ExecutableFolder.
+
+There is sometimes utility in finding the current executable file
+that is running. This can be used for upgrading the current executable
+or finding resources located relative to the executable file.
+
+Multi-platform and supports:
+ * Linux
+ * OS X
+ * Windows
+ * Plan 9
+ * BSDs.
diff --git a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext.go
index 37efbb221..4ed4b9aa3 100644
--- a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext.go
+++ b/Godeps/_workspace/src/github.com/kardianos/osext/osext.go
@@ -25,8 +25,3 @@ func ExecutableFolder() (string, error) {
folder, _ := filepath.Split(p)
return folder, nil
}
-
-// Depricated. Same as Executable().
-func GetExePath() (exePath string, err error) {
- return Executable()
-}
diff --git a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_plan9.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_plan9.go
index 4468a73a7..655750c54 100644
--- a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_plan9.go
+++ b/Godeps/_workspace/src/github.com/kardianos/osext/osext_plan9.go
@@ -5,16 +5,16 @@
package osext
import (
- "syscall"
- "os"
- "strconv"
+ "os"
+ "strconv"
+ "syscall"
)
func executable() (string, error) {
- f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
- if err != nil {
- return "", err
- }
- defer f.Close()
- return syscall.Fd2path(int(f.Fd()))
+ f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+ return syscall.Fd2path(int(f.Fd()))
}
diff --git a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_procfs.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_procfs.go
index 546fec915..a50021ad5 100644
--- a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_procfs.go
+++ b/Godeps/_workspace/src/github.com/kardianos/osext/osext_procfs.go
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux netbsd openbsd
+// +build linux netbsd openbsd solaris dragonfly
package osext
import (
"errors"
+ "fmt"
"os"
"runtime"
)
@@ -18,8 +19,10 @@ func executable() (string, error) {
return os.Readlink("/proc/self/exe")
case "netbsd":
return os.Readlink("/proc/curproc/exe")
- case "openbsd":
+ case "openbsd", "dragonfly":
return os.Readlink("/proc/curproc/file")
+ case "solaris":
+ return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))
}
return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
}
diff --git a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_sysctl.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go
index b66cac878..b66cac878 100644
--- a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_sysctl.go
+++ b/Godeps/_workspace/src/github.com/kardianos/osext/osext_sysctl.go
diff --git a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_test.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_test.go
index dc661dbc2..dc661dbc2 100644
--- a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_test.go
+++ b/Godeps/_workspace/src/github.com/kardianos/osext/osext_test.go
diff --git a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_windows.go b/Godeps/_workspace/src/github.com/kardianos/osext/osext_windows.go
index 72d282cf8..72d282cf8 100644
--- a/Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_windows.go
+++ b/Godeps/_workspace/src/github.com/kardianos/osext/osext_windows.go
diff --git a/README.md b/README.md
index 18392816a..bf4bf341b 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,25 @@ Ethereum (CLI):
`go get github.com/ethereum/go-ethereum/cmd/ethereum`
-For further, detailed, build instruction please see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go))
+As of POC-8, go-ethereum uses [Godep](https://github.com/tools/godep) to manage dependencies. Assuming you have [your environment all set up](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)), switch to the go-ethereum repository root folder, and build/install the executable you need:
+
+Mist (GUI):
+
+```
+godep go build -v ./cmd/mist
+```
+
+Ethereum (CLI):
+
+```
+godep go build -v ./cmd/ethereum
+```
+
+Instead of `build`, you can use `install` which will also install the resulting binary.
+
+For prerequisites and detailed build instructions please see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go))
+
+If you intend to develop on go-ethereum, check the [Developers' Guide](https://github.com/ethereum/go-ethereum/wiki/Developers'-Guide)
Automated (dev) builds
======================
@@ -34,97 +52,47 @@ Automated (dev) builds
* [Windows] Coming soon&trade;
* [Linux] Coming soon&trade;
-Binaries
-========
+Executables
+===========
-Go Ethereum comes with several binaries found in
-[cmd](https://github.com/ethereum/go-ethereum/tree/master/cmd):
+Go Ethereum comes with several wrappers/executables found in
+[the `cmd` directory](https://github.com/ethereum/go-ethereum/tree/develop/cmd):
-* `mist` Official Ethereum Browser
-* `ethereum` Ethereum CLI
-* `ethtest` test tool which runs with the [tests](https://github.com/ethereum/testes) suit:
+* `mist` Official Ethereum Browser (ethereum GUI client)
+* `ethereum` Ethereum CLI (ethereum command line interface client)
+* `bootnode` runs a bootstrap node for the Discovery Protocol
+* `ethtest` test tool which runs with the [tests](https://github.com/ethereum/testes) suite:
`cat file | ethtest`.
* `evm` is a generic Ethereum Virtual Machine: `evm -code 60ff60ff -gas
10000 -price 0 -dump`. See `-h` for a detailed description.
-* `rlpdump` converts a rlp stream to `interface{}`.
-* `peerserver` simple P2P (noi-ethereum) peer server.
* `disasm` disassembles EVM code: `echo "6001" | disasm`
+* `rlpdump` converts a rlp stream to `interface{}`.
-General command line options
+Command line options
============================
+Both `mist` and `ethereum` can be configured via command line options, environment variables and config files.
+
+To get the options available:
+
```
-== Shared between ethereum and Mist ==
-
-= Settings
--id Set the custom identifier of the client (shows up on other clients)
--port Port on which the server will accept incomming connections
--upnp Enable UPnP
--maxpeer Desired amount of peers
--rpc Start JSON RPC
--dir Data directory used to store configs and databases
-
-= Utility
--h This
--import Import a private key
--genaddr Generates a new address and private key (destructive action)
--dump Dump a specific state of a block to stdout given the -number or -hash
--difftool Supress all output and prints VM output to stdout
--diff vm=only vm output, all=all output including state storage
-
-Ethereum only
-ethereum [options] [filename]
--js Start the JavaScript REPL
-filename Load the given file and interpret as JavaScript
--m Start mining blocks
-
-== Mist only ==
-
--asset_path absolute path to GUI assets directory
+ethereum -help
```
+For further details on options, see the [wiki](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options)
+
Contribution
============
-If you'd like to contribute to Ethereum please fork, fix, commit and
+If you'd like to contribute to go-ethereum please fork, fix, commit and
send a pull request. Commits who do not comply with the coding standards
are ignored (use gofmt!). If you send pull requests make absolute sure that you
commit on the `develop` branch and that you do not merge to master.
Commits that are directly based on master are simply ignored.
-For dependency management, we use [godep](https://github.com/tools/godep). After installing with `go get github.com/tools/godep`, run `godep restore` to ensure that changes to other repositories do not break the build. To update a dependency version (for example, to include a new upstream fix), run `go get -u <foo/bar>` then `godep update <foo/...>`. To track a new dependency, add it to the project as normal than run `godep save ./...`. Changes to the Godeps folder should be manually verified then commited.
-
-To make life easier try [git flow](http://nvie.com/posts/a-successful-git-branching-model/) it sets
-this all up and streamlines your work flow.
-
-Coding standards
-================
-
-Sources should be formatted according to the [Go Formatting
-Style](http://golang.org/doc/effective_go.html#formatting).
-
-Unless structs fields are supposed to be directly accesible, provide
-Getters and hide the fields through Go's exporting facility.
-
-When you comment put meaningful comments. Describe in detail what you
-want to achieve.
-
-*wrong*
-
-```go
-// Check if the value at x is greater than y
-if x > y {
- // It's greater!
-}
-```
-
-Everyone reading the source probably know what you wanted to achieve
-with above code. Those are **not** meaningful comments.
+For dependency management, we use [godep](https://github.com/tools/godep). After installing with `go get github.com/tools/godep`, run `godep restore` to ensure that changes to other repositories do not break the build. To update a dependency version (for example, to include a new upstream fix), run `go get -u <foo/bar>` then `godep update <foo/...>`. To track a new dependency, add it to the project as normal than run `godep save ./...`. Changes to the [Godeps folder](https://github.com/ethereum/go-ethereum/tree/develop/Godeps): should be manually verified then commited.
-While the project isn't 100% tested I want you to write tests non the
-less. I haven't got time to evaluate everyone's code in detail so I
-expect you to write tests for me so I don't have to test your code
-manually. (If you want to contribute by just writing tests that's fine
-too!)
+To make life easier try [git flow](http://nvie.com/posts/a-successful-git-branching-model/) it sets this all up and streamlines your work flow.
+See [Developers' Guide](https://github.com/ethereum/go-ethereum/wiki/Developers'-Guide)
diff --git a/accounts/account_manager.go b/accounts/account_manager.go
index da0bd8900..3e9fa7799 100644
--- a/accounts/account_manager.go
+++ b/accounts/account_manager.go
@@ -34,33 +34,62 @@ package accounts
import (
crand "crypto/rand"
+
+ "errors"
+ "sync"
+ "time"
+
"github.com/ethereum/go-ethereum/crypto"
)
+var ErrLocked = errors.New("account is locked; please request passphrase")
+
// TODO: better name for this struct?
type Account struct {
Address []byte
}
type AccountManager struct {
- keyStore crypto.KeyStore2
+ keyStore crypto.KeyStore2
+ unlockedKeys map[string]crypto.Key
+ unlockMilliseconds time.Duration
+ mutex sync.RWMutex
}
-// TODO: get key by addr - modify KeyStore2 GetKey to work with addr
-
-// TODO: pass through passphrase for APIs which require access to private key?
-func NewAccountManager(keyStore crypto.KeyStore2) AccountManager {
+func NewAccountManager(keyStore crypto.KeyStore2, unlockMilliseconds time.Duration) AccountManager {
+ keysMap := make(map[string]crypto.Key)
am := &AccountManager{
- keyStore: keyStore,
+ keyStore: keyStore,
+ unlockedKeys: keysMap,
+ unlockMilliseconds: unlockMilliseconds,
}
return *am
}
-func (am *AccountManager) Sign(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) {
+func (am AccountManager) DeleteAccount(address []byte, auth string) error {
+ return am.keyStore.DeleteKey(address, auth)
+}
+
+func (am *AccountManager) Sign(fromAccount *Account, toSign []byte) (signature []byte, err error) {
+ am.mutex.RLock()
+ unlockedKey := am.unlockedKeys[string(fromAccount.Address)]
+ am.mutex.RUnlock()
+ if unlockedKey.Address == nil {
+ return nil, ErrLocked
+ }
+ signature, err = crypto.Sign(toSign, unlockedKey.PrivateKey)
+ return signature, err
+}
+
+func (am *AccountManager) SignLocked(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) {
key, err := am.keyStore.GetKey(fromAccount.Address, keyAuth)
if err != nil {
return nil, err
}
+ am.mutex.RLock()
+ am.unlockedKeys[string(fromAccount.Address)] = *key
+ am.mutex.RUnlock()
+ go unlockLater(am, fromAccount.Address)
signature, err = crypto.Sign(toSign, key.PrivateKey)
return signature, err
}
@@ -76,8 +105,6 @@ func (am AccountManager) NewAccount(auth string) (*Account, error) {
return ua, err
}
-// set of accounts == set of keys in given key store
-// TODO: do we need persistence of accounts as well?
func (am *AccountManager) Accounts() ([]Account, error) {
addresses, err := am.keyStore.GetKeyAddresses()
if err != nil {
@@ -93,3 +120,13 @@ func (am *AccountManager) Accounts() ([]Account, error) {
}
return accounts, err
}
+
+func unlockLater(am *AccountManager, addr []byte) {
+ select {
+ case <-time.After(time.Millisecond * am.unlockMilliseconds):
+ }
+ am.mutex.RLock()
+ // TODO: how do we know the key is actually gone from memory?
+ delete(am.unlockedKeys, string(addr))
+ am.mutex.RUnlock()
+}
diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go
index 30e8c6285..44d1d72f1 100644
--- a/accounts/accounts_test.go
+++ b/accounts/accounts_test.go
@@ -5,16 +5,78 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/randentropy"
+ "github.com/ethereum/go-ethereum/ethutil"
+ "time"
)
func TestAccountManager(t *testing.T) {
- ks := crypto.NewKeyStorePlain(crypto.DefaultDataDir())
- am := NewAccountManager(ks)
+ ks := crypto.NewKeyStorePlain(ethutil.DefaultDataDir() + "/testaccounts")
+ am := NewAccountManager(ks, 100)
pass := "" // not used but required by API
a1, err := am.NewAccount(pass)
toSign := randentropy.GetEntropyCSPRNG(32)
- _, err = am.Sign(a1, pass, toSign)
+ _, err = am.SignLocked(a1, pass, toSign)
if err != nil {
t.Fatal(err)
}
+
+ // Cleanup
+ time.Sleep(time.Millisecond * 150) // wait for locking
+
+ accounts, err := am.Accounts()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, account := range accounts {
+ err := am.DeleteAccount(account.Address, pass)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+func TestAccountManagerLocking(t *testing.T) {
+ ks := crypto.NewKeyStorePassphrase(ethutil.DefaultDataDir() + "/testaccounts")
+ am := NewAccountManager(ks, 200)
+ pass := "foo"
+ a1, err := am.NewAccount(pass)
+ toSign := randentropy.GetEntropyCSPRNG(32)
+
+ // Signing without passphrase fails because account is locked
+ _, err = am.Sign(a1, toSign)
+ if err != ErrLocked {
+ t.Fatal(err)
+ }
+
+ // Signing with passphrase works
+ _, err = am.SignLocked(a1, pass, toSign)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Signing without passphrase works because account is temp unlocked
+ _, err = am.Sign(a1, toSign)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Signing without passphrase fails after automatic locking
+ time.Sleep(time.Millisecond * time.Duration(250))
+
+ _, err = am.Sign(a1, toSign)
+ if err != ErrLocked {
+ t.Fatal(err)
+ }
+
+ // Cleanup
+ accounts, err := am.Accounts()
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, account := range accounts {
+ err := am.DeleteAccount(account.Address, pass)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
}
diff --git a/cmd/ethereum/flags.go b/cmd/ethereum/flags.go
index 577bee442..a3004f503 100644
--- a/cmd/ethereum/flags.go
+++ b/cmd/ethereum/flags.go
@@ -26,50 +26,52 @@ import (
"fmt"
"log"
"os"
- "os/user"
"path"
+ "runtime"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/vm"
)
var (
- Identifier string
- KeyRing string
- DiffTool bool
- DiffType string
- KeyStore string
- StartRpc bool
- StartWebSockets bool
- RpcPort int
- WsPort int
- OutboundPort string
- ShowGenesis bool
- AddPeer string
- MaxPeer int
- GenAddr bool
- BootNodes string
- NodeKey *ecdsa.PrivateKey
- NAT nat.Interface
- SecretFile string
- ExportDir string
- NonInteractive bool
- Datadir string
- LogFile string
- ConfigFile string
- DebugFile string
- LogLevel int
- LogFormat string
- Dump bool
- DumpHash string
- DumpNumber int
- VmType int
- ImportChain string
- SHH bool
- Dial bool
- PrintVersion bool
+ Identifier string
+ KeyRing string
+ DiffTool bool
+ DiffType string
+ KeyStore string
+ StartRpc bool
+ StartWebSockets bool
+ RpcListenAddress string
+ RpcPort int
+ OutboundPort string
+ ShowGenesis bool
+ AddPeer string
+ MaxPeer int
+ GenAddr bool
+ BootNodes string
+ NodeKey *ecdsa.PrivateKey
+ NAT nat.Interface
+ SecretFile string
+ ExportDir string
+ NonInteractive bool
+ Datadir string
+ LogFile string
+ ConfigFile string
+ DebugFile string
+ LogLevel int
+ LogFormat string
+ Dump bool
+ DumpHash string
+ DumpNumber int
+ VmType int
+ ImportChain string
+ SHH bool
+ Dial bool
+ PrintVersion bool
+ MinerThreads int
)
// flags specific to cli client
@@ -79,12 +81,7 @@ var (
InputFile string
)
-func defaultDataDir() string {
- usr, _ := user.Current()
- return path.Join(usr.HomeDir, ".ethereum")
-}
-
-var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
+var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
func Init() {
// TODO: move common flag processing to cmd/util
@@ -96,22 +93,21 @@ func Init() {
flag.IntVar(&VmType, "vm", 0, "Virtual Machine type: 0-1: standard, debug")
flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
- flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
+ flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file")
+ flag.StringVar(&RpcListenAddress, "rpcaddr", "127.0.0.1", "address for json-rpc server to listen on")
flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
- flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on")
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
- flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
- flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use")
+ flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
- flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
- flag.StringVar(&LogFormat, "logformat", "std", "logformat: std,raw)")
+ flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5 (= silent,error,warn,info,debug,debug detail)")
+ flag.StringVar(&LogFormat, "logformat", "std", "logformat: std,raw")
flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
flag.BoolVar(&ShowGenesis, "genesis", false, "Dump the genesis block")
@@ -121,9 +117,10 @@ func Init() {
flag.StringVar(&DumpHash, "hash", "", "specify arg in hex")
flag.IntVar(&DumpNumber, "number", -1, "specify arg in number")
- flag.BoolVar(&StartMining, "mine", false, "start dagger mining")
+ flag.BoolVar(&StartMining, "mine", false, "start mining")
flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console")
flag.BoolVar(&PrintVersion, "version", false, "prints version number")
+ flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads")
// Network stuff
var (
@@ -140,6 +137,12 @@ func Init() {
flag.Parse()
+ // When the javascript console is started log to a file instead
+ // of stdout
+ if StartJsConsole {
+ LogFile = path.Join(Datadir, "ethereum.log")
+ }
+
var err error
if NAT, err = nat.Parse(*natstr); err != nil {
log.Fatalf("-nat: %v", err)
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 9c840de58..ff306b10f 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -37,7 +37,7 @@ import (
const (
ClientIdentifier = "Ethereum(G)"
- Version = "0.8.5"
+ Version = "0.8.6"
)
var clilogger = logger.NewLogger("CLI")
@@ -62,20 +62,21 @@ func main() {
utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
ethereum, err := eth.New(&eth.Config{
- Name: p2p.MakeName(ClientIdentifier, Version),
- KeyStore: KeyStore,
- DataDir: Datadir,
- LogFile: LogFile,
- LogLevel: LogLevel,
- LogFormat: LogFormat,
- MaxPeers: MaxPeer,
- Port: OutboundPort,
- NAT: NAT,
- KeyRing: KeyRing,
- Shh: true,
- Dial: Dial,
- BootNodes: BootNodes,
- NodeKey: NodeKey,
+ Name: p2p.MakeName(ClientIdentifier, Version),
+ KeyStore: KeyStore,
+ DataDir: Datadir,
+ LogFile: LogFile,
+ LogLevel: LogLevel,
+ LogFormat: LogFormat,
+ MaxPeers: MaxPeer,
+ Port: OutboundPort,
+ NAT: NAT,
+ KeyRing: KeyRing,
+ Shh: true,
+ Dial: Dial,
+ BootNodes: BootNodes,
+ NodeKey: NodeKey,
+ MinerThreads: MinerThreads,
})
if err != nil {
@@ -113,10 +114,6 @@ func main() {
return
}
- if StartMining {
- utils.StartMining(ethereum)
- }
-
if len(ImportChain) > 0 {
start := time.Now()
err := utils.ImportChain(ethereum, ImportChain)
@@ -128,15 +125,17 @@ func main() {
}
if StartRpc {
- utils.StartRpc(ethereum, RpcPort)
- }
-
- if StartWebSockets {
- utils.StartWebSockets(ethereum, WsPort)
+ utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
}
utils.StartEthereum(ethereum)
+ fmt.Printf("Welcome to the FRONTIER\n")
+
+ if StartMining {
+ ethereum.Miner().Start()
+ }
+
if StartJsConsole {
InitJsConsole(ethereum)
} else if len(InputFile) > 0 {
diff --git a/cmd/ethereum/repl/repl.go b/cmd/ethereum/repl/repl.go
index 4a7880ff4..11b812617 100644
--- a/cmd/ethereum/repl/repl.go
+++ b/cmd/ethereum/repl/repl.go
@@ -60,6 +60,7 @@ func (self *JSRepl) Start() {
if !self.running {
self.running = true
repllogger.Infoln("init JS Console")
+
reader := bufio.NewReader(self.history)
for {
line, err := reader.ReadString('\n')
diff --git a/cmd/mist/assets/examples/coin.html b/cmd/mist/assets/examples/coin.html
index 18a6811d7..509a9aeeb 100644
--- a/cmd/mist/assets/examples/coin.html
+++ b/cmd/mist/assets/examples/coin.html
@@ -19,6 +19,7 @@
<span>Amount:</span>
<input type="text" id="amount" style="width:200px">
<button onclick="transact()">Send</button>
+ <span id="message"></span>
</div>
<hr>
@@ -95,17 +96,28 @@
}
function transact() {
- var to = document.querySelector("#address").value;
- if( to.length == 0 ) {
+ var to = document.querySelector("#address");
+ if( to.value.length == 0 ) {
to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3";
} else {
- to = "0x"+to;
+ if (to.value.substr(0,2) != "0x")
+ to.value = "0x"+to.value;
}
- var value = parseInt( document.querySelector("#amount").value );
- console.log("transact: ", to, " => ", value)
+ var value = document.querySelector("#amount");
+ var amount = parseInt( value.value );
+ console.log("transact: ", to.value, " => ", amount)
- contract.send( to, value );
+ contract.send( to.value, amount );
+
+ to.value = "";
+ value.value = "";
+
+ var message = document.querySelector("#message")
+ message.innerHTML = "Submitted";
+ setTimeout(function() {
+ message.innerHTML = "";
+ }, 1000);
}
refresh();
diff --git a/cmd/mist/assets/examples/info.html b/cmd/mist/assets/examples/info.html
index 2a405c280..3b958a494 100644
--- a/cmd/mist/assets/examples/info.html
+++ b/cmd/mist/assets/examples/info.html
@@ -62,6 +62,8 @@
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545'));
+ eth.defaultBlock = -2
+
document.querySelector("#number").innerHTML = eth.number;
document.querySelector("#coinbase").innerHTML = eth.coinbase
document.querySelector("#peer_count").innerHTML = eth.peerCount;
@@ -72,8 +74,9 @@
document.querySelector("#mining").innerHTML = eth.mining;
document.querySelector("#listening").innerHTML = eth.listening;
eth.watch('chain').changed(function() {
- document.querySelector("#number").innerHTML = eth.number;
- });
+ document.querySelector("#number").innerHTML = eth.number;
+ });
+
</script>
diff --git a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
index 83b598b3f..522b77ebf 100644
--- a/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
+++ b/cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
@@ -53,7 +53,6 @@ var inputTypes = types.inputTypes();
/// @returns bytes representation of input params
var formatInput = function (inputs, params) {
var bytes = "";
- var padding = c.ETH_PADDING * 2;
/// first we iterate in search for dynamic
inputs.forEach(function (input, index) {
@@ -110,6 +109,7 @@ var formatOutput = function (outs, output) {
output = output.slice(dynamicPartLength);
outs.forEach(function (out, i) {
+ /*jshint maxcomplexity:6 */
var typeMatch = false;
for (var j = 0; j < outputTypes.length && !typeMatch; j++) {
typeMatch = outputTypes[j].type(outs[i].type);
@@ -210,7 +210,7 @@ module.exports = {
};
-},{"./const":2,"./formatters":6,"./types":11,"./utils":12,"./web3":13}],2:[function(require,module,exports){
+},{"./const":2,"./formatters":8,"./types":14,"./utils":15,"./web3":17}],2:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -264,7 +264,8 @@ module.exports = {
ETH_PADDING: 32,
ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS,
- ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN }
+ ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN },
+ ETH_POLLING_TIMEOUT: 1000
};
@@ -340,6 +341,7 @@ var addFunctionsToContract = function (contract, desc, address) {
var typeName = utils.extractTypeName(method.name);
var impl = function () {
+ /*jshint maxcomplexity:7 */
var params = Array.prototype.slice.call(arguments);
var signature = abi.signatureFromAscii(method.name);
var parsed = inputParser[displayName][typeName].apply(null, params);
@@ -416,11 +418,11 @@ var addEventsToContract = function (contract, desc, address) {
var signature = abi.eventSignatureFromAscii(e.name);
var event = eventImpl.inputParser(address, signature, e);
var o = event.apply(null, params);
- o._onWatchEventResult = function (data) {
+ var outputFormatter = function (data) {
var parser = eventImpl.outputParser(e);
return parser(data);
};
- return web3.eth.watch(o);
+ return web3.eth.watch(o, undefined, undefined, outputFormatter);
};
// this property should be used by eth.filter to check if object is an event
@@ -487,7 +489,131 @@ var contract = function (address, desc) {
module.exports = contract;
-},{"./abi":1,"./event":4,"./utils":12,"./web3":13}],4:[function(require,module,exports){
+},{"./abi":1,"./event":6,"./utils":15,"./web3":17}],4:[function(require,module,exports){
+/*
+ This file is part of ethereum.js.
+
+ ethereum.js is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ ethereum.js is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file db.js
+ * @authors:
+ * Marek Kotewicz <marek@ethdev.com>
+ * @date 2015
+ */
+
+/// @returns an array of objects describing web3.db api methods
+var methods = function () {
+ return [
+ { name: 'put', call: 'db_put' },
+ { name: 'get', call: 'db_get' },
+ { name: 'putString', call: 'db_putString' },
+ { name: 'getString', call: 'db_getString' }
+ ];
+};
+
+module.exports = {
+ methods: methods
+};
+
+},{}],5:[function(require,module,exports){
+/*
+ This file is part of ethereum.js.
+
+ ethereum.js is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ ethereum.js is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file eth.js
+ * @authors:
+ * Marek Kotewicz <marek@ethdev.com>
+ * @date 2015
+ */
+
+/// @returns an array of objects describing web3.eth api methods
+var methods = function () {
+ var blockCall = function (args) {
+ return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber";
+ };
+
+ var transactionCall = function (args) {
+ return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber';
+ };
+
+ var uncleCall = function (args) {
+ return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber';
+ };
+
+ var transactionCountCall = function (args) {
+ return typeof args[0] === "string" ? 'eth_transactionCountByHash' : 'eth_transactionCountByNumber';
+ };
+
+ var uncleCountCall = function (args) {
+ return typeof args[0] === "string" ? 'eth_uncleCountByHash' : 'eth_uncleCountByNumber';
+ };
+
+ return [
+ { name: 'balanceAt', call: 'eth_balanceAt' },
+ { name: 'stateAt', call: 'eth_stateAt' },
+ { name: 'storageAt', call: 'eth_storageAt' },
+ { name: 'countAt', call: 'eth_countAt'},
+ { name: 'codeAt', call: 'eth_codeAt' },
+ { name: 'transact', call: 'eth_transact' },
+ { name: 'call', call: 'eth_call' },
+ { name: 'block', call: blockCall },
+ { name: 'transaction', call: transactionCall },
+ { name: 'uncle', call: uncleCall },
+ { name: 'compilers', call: 'eth_compilers' },
+ { name: 'flush', call: 'eth_flush' },
+ { name: 'lll', call: 'eth_lll' },
+ { name: 'solidity', call: 'eth_solidity' },
+ { name: 'serpent', call: 'eth_serpent' },
+ { name: 'logs', call: 'eth_logs' },
+ { name: 'transactionCount', call: transactionCountCall },
+ { name: 'uncleCount', call: uncleCountCall }
+ ];
+};
+
+/// @returns an array of objects describing web3.eth api properties
+var properties = function () {
+ return [
+ { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },
+ { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },
+ { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },
+ { name: 'gasPrice', getter: 'eth_gasPrice' },
+ { name: 'accounts', getter: 'eth_accounts' },
+ { name: 'peerCount', getter: 'eth_peerCount' },
+ { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },
+ { name: 'number', getter: 'eth_number'}
+ ];
+};
+
+module.exports = {
+ methods: methods,
+ properties: properties
+};
+
+
+},{}],6:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -571,9 +697,9 @@ var getArgumentsObject = function (inputs, indexed, notIndexed) {
return inputs.reduce(function (acc, current) {
var value;
if (current.indexed)
- value = indexed.splice(0, 1)[0];
+ value = indexedCopy.splice(0, 1)[0];
else
- value = notIndexed.splice(0, 1)[0];
+ value = notIndexedCopy.splice(0, 1)[0];
acc[current.name] = value;
return acc;
@@ -589,6 +715,7 @@ var outputParser = function (event) {
args: {}
};
+ output.topics = output.topic; // fallback for go-ethereum
if (!output.topic) {
return result;
}
@@ -624,7 +751,7 @@ module.exports = {
};
-},{"./abi":1,"./utils":12}],5:[function(require,module,exports){
+},{"./abi":1,"./utils":15}],7:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -650,84 +777,96 @@ module.exports = {
* @date 2014
*/
-var web3 = require('./web3'); // jshint ignore:line
-
-/// should be used when we want to watch something
-/// it's using inner polling mechanism and is notified about changes
-/// TODO: change 'options' name cause it may be not the best matching one, since we have events
-var Filter = function(options, impl) {
-
- if (typeof options !== "string") {
-
- // topics property is deprecated, warn about it!
- if (options.topics) {
- console.warn('"topics" is deprecated, use "topic" instead');
- }
-
- this._onWatchResult = options._onWatchEventResult;
-
- // evaluate lazy properties
- options = {
- to: options.to,
- topic: options.topic,
- earliest: options.earliest,
- latest: options.latest,
- max: options.max,
- skip: options.skip,
- address: options.address
- };
-
+/// Should be called to check if filter implementation is valid
+/// @returns true if it is, otherwise false
+var implementationIsValid = function (i) {
+ return !!i &&
+ typeof i.newFilter === 'function' &&
+ typeof i.getMessages === 'function' &&
+ typeof i.uninstallFilter === 'function' &&
+ typeof i.startPolling === 'function' &&
+ typeof i.stopPolling === 'function';
+};
+
+/// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones
+/// @param should be string or object
+/// @returns options string or object
+var getOptions = function (options) {
+ if (typeof options === 'string') {
+ return options;
+ }
+
+ options = options || {};
+
+ if (options.topics) {
+ console.warn('"topics" is deprecated, is "topic" instead');
}
-
- this.impl = impl;
- this.callbacks = [];
- this.id = impl.newFilter(options);
- web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this));
+ // evaluate lazy properties
+ return {
+ to: options.to,
+ topic: options.topic,
+ earliest: options.earliest,
+ latest: options.latest,
+ max: options.max,
+ skip: options.skip,
+ address: options.address
+ };
};
-/// alias for changed*
-Filter.prototype.arrived = function(callback) {
- this.changed(callback);
-};
-Filter.prototype.happened = function(callback) {
- this.changed(callback);
-};
+/// Should be used when we want to watch something
+/// it's using inner polling mechanism and is notified about changes
+/// @param options are filter options
+/// @param implementation, an abstract polling implementation
+/// @param formatter (optional), callback function which formats output before 'real' callback
+var filter = function(options, implementation, formatter) {
+ if (!implementationIsValid(implementation)) {
+ console.error('filter implemenation is invalid');
+ return;
+ }
-/// gets called when there is new eth/shh message
-Filter.prototype.changed = function(callback) {
- this.callbacks.push(callback);
-};
+ options = getOptions(options);
+ var callbacks = [];
+ var filterId = implementation.newFilter(options);
+ var onMessages = function (messages) {
+ messages.forEach(function (message) {
+ message = formatter ? formatter(message) : message;
+ callbacks.forEach(function (callback) {
+ callback(message);
+ });
+ });
+ };
-/// trigger calling new message from people
-Filter.prototype.trigger = function(messages) {
- for (var i = 0; i < this.callbacks.length; i++) {
- for (var j = 0; j < messages.length; j++) {
- var message = this._onWatchResult ? this._onWatchResult(messages[j]) : messages[j];
- this.callbacks[i].call(this, message);
- }
- }
-};
+ implementation.startPolling(filterId, onMessages, implementation.uninstallFilter);
-/// should be called to uninstall current filter
-Filter.prototype.uninstall = function() {
- this.impl.uninstallFilter(this.id);
- web3.provider.stopPolling(this.id);
-};
+ var changed = function (callback) {
+ callbacks.push(callback);
+ };
-/// should be called to manually trigger getting latest messages from the client
-Filter.prototype.messages = function() {
- return this.impl.getMessages(this.id);
-};
+ var messages = function () {
+ return implementation.getMessages(filterId);
+ };
+
+ var uninstall = function () {
+ implementation.stopPolling(filterId);
+ implementation.uninstallFilter(filterId);
+ callbacks = [];
+ };
-/// alias for messages
-Filter.prototype.logs = function () {
- return this.messages();
+ return {
+ changed: changed,
+ arrived: changed,
+ happened: changed,
+ messages: messages,
+ logs: messages,
+ uninstall: uninstall
+ };
};
-module.exports = Filter;
+module.exports = filter;
+
-},{"./web3":13}],6:[function(require,module,exports){
+},{}],8:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -770,6 +909,7 @@ var padLeft = function (string, chars, sign) {
/// If the value is floating point, round it down
/// @returns right-aligned byte representation of int
var formatInputInt = function (value) {
+ /*jshint maxcomplexity:7 */
var padding = c.ETH_PADDING * 2;
if (value instanceof BigNumber || typeof value === 'number') {
if (typeof value === 'number')
@@ -883,7 +1023,7 @@ module.exports = {
};
-},{"./const":2,"./utils":12}],7:[function(require,module,exports){
+},{"./const":2,"./utils":15}],9:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -918,20 +1058,22 @@ var HttpSyncProvider = function (host) {
HttpSyncProvider.prototype.send = function (payload) {
//var data = formatJsonRpcObject(payload);
-
+
var request = new XMLHttpRequest();
request.open('POST', this.host, false);
request.send(JSON.stringify(payload));
-
- // check request.status
+
var result = request.responseText;
+ // check request.status
+ if(request.status !== 200)
+ return;
return JSON.parse(result);
};
module.exports = HttpSyncProvider;
-},{}],8:[function(require,module,exports){
+},{}],10:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -998,7 +1140,7 @@ module.exports = {
-},{}],9:[function(require,module,exports){
+},{}],11:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -1015,7 +1157,42 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/** @file providermanager.js
+/** @file qtsync.js
+ * @authors:
+ * Marek Kotewicz <marek@ethdev.com>
+ * Marian Oancea <marian@ethdev.com>
+ * @date 2014
+ */
+
+var QtSyncProvider = function () {
+};
+
+QtSyncProvider.prototype.send = function (payload) {
+ var result = navigator.qt.callMethod(JSON.stringify(payload));
+ return JSON.parse(result);
+};
+
+module.exports = QtSyncProvider;
+
+
+},{}],12:[function(require,module,exports){
+/*
+ This file is part of ethereum.js.
+
+ ethereum.js is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ ethereum.js is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file requestmanager.js
* @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
@@ -1024,85 +1201,95 @@ module.exports = {
* @date 2014
*/
-var web3 = require('./web3');
var jsonrpc = require('./jsonrpc');
-
+var c = require('./const');
/**
- * Provider manager object prototype
* It's responsible for passing messages to providers
- * If no provider is set it's responsible for queuing requests
* It's also responsible for polling the ethereum node for incoming messages
- * Default poll timeout is 12 seconds
- * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling,
- * and provider manager polling mechanism is not used
+ * Default poll timeout is 1 second
*/
-var ProviderManager = function() {
- this.polls = [];
- this.provider = undefined;
+var requestManager = function() {
+ var polls = [];
+ var timeout = null;
+ var provider;
- var self = this;
- var poll = function () {
- self.polls.forEach(function (data) {
- var result = self.send(data.data);
-
- if (!(result instanceof Array) || result.length === 0) {
- return;
- }
+ var send = function (data) {
+ var payload = jsonrpc.toPayload(data.method, data.params);
+
+ if (!provider) {
+ console.error('provider is not set');
+ return null;
+ }
- data.callback(result);
- });
+ var result = provider.send(payload);
- setTimeout(poll, 1000);
+ if (!jsonrpc.isValidResponse(result)) {
+ console.log(result);
+ return null;
+ }
+
+ return result.result;
};
- poll();
-};
-
-/// sends outgoing requests
-/// @params data - an object with at least 'method' property
-ProviderManager.prototype.send = function(data) {
- var payload = jsonrpc.toPayload(data.method, data.params);
- if (this.provider === undefined) {
- console.error('provider is not set');
- return null;
- }
+ var setProvider = function (p) {
+ provider = p;
+ };
- var result = this.provider.send(payload);
+ /*jshint maxparams:4 */
+ var startPolling = function (data, pollId, callback, uninstall) {
+ polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});
+ };
+ /*jshint maxparams:3 */
- if (!jsonrpc.isValidResponse(result)) {
- console.log(result);
- return null;
- }
+ var stopPolling = function (pollId) {
+ for (var i = polls.length; i--;) {
+ var poll = polls[i];
+ if (poll.id === pollId) {
+ polls.splice(i, 1);
+ }
+ }
+ };
- return result.result;
-};
+ var reset = function () {
+ polls.forEach(function (poll) {
+ poll.uninstall(poll.id);
+ });
+ polls = [];
-/// setups provider, which will be used for sending messages
-ProviderManager.prototype.set = function(provider) {
- this.provider = provider;
-};
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = null;
+ }
+ poll();
+ };
-/// this method is only used, when we do not have native qt bindings and have to do polling on our own
-/// should be callled, on start watching for eth/shh changes
-ProviderManager.prototype.startPolling = function (data, pollId, callback) {
- this.polls.push({data: data, id: pollId, callback: callback});
-};
+ var poll = function () {
+ polls.forEach(function (data) {
+ var result = send(data.data);
+ if (!(result instanceof Array) || result.length === 0) {
+ return;
+ }
+ data.callback(result);
+ });
+ timeout = setTimeout(poll, c.ETH_POLLING_TIMEOUT);
+ };
+
+ poll();
-/// should be called to stop polling for certain watch changes
-ProviderManager.prototype.stopPolling = function (pollId) {
- for (var i = this.polls.length; i--;) {
- var poll = this.polls[i];
- if (poll.id === pollId) {
- this.polls.splice(i, 1);
- }
- }
+ return {
+ send: send,
+ setProvider: setProvider,
+ startPolling: startPolling,
+ stopPolling: stopPolling,
+ reset: reset
+ };
};
-module.exports = ProviderManager;
+module.exports = requestManager;
-},{"./jsonrpc":8,"./web3":13}],10:[function(require,module,exports){
+},{"./const":2,"./jsonrpc":10}],13:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -1119,25 +1306,29 @@ module.exports = ProviderManager;
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/** @file qtsync.js
+/** @file shh.js
* @authors:
* Marek Kotewicz <marek@ethdev.com>
- * Marian Oancea <marian@ethdev.com>
- * @date 2014
+ * @date 2015
*/
-var QtSyncProvider = function () {
+/// @returns an array of objects describing web3.shh api methods
+var methods = function () {
+ return [
+ { name: 'post', call: 'shh_post' },
+ { name: 'newIdentity', call: 'shh_newIdentity' },
+ { name: 'haveIdentity', call: 'shh_haveIdentity' },
+ { name: 'newGroup', call: 'shh_newGroup' },
+ { name: 'addToGroup', call: 'shh_addToGroup' }
+ ];
};
-QtSyncProvider.prototype.send = function (payload) {
- var result = navigator.qt.callMethod(JSON.stringify(payload));
- return JSON.parse(result);
+module.exports = {
+ methods: methods
};
-module.exports = QtSyncProvider;
-
-},{}],11:[function(require,module,exports){
+},{}],14:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -1218,7 +1409,7 @@ module.exports = {
};
-},{"./formatters":6}],12:[function(require,module,exports){
+},{"./formatters":8}],15:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -1328,6 +1519,7 @@ var filterEvents = function (json) {
/// TODO: use BigNumber.js to parse int
/// TODO: add tests for it!
var toEth = function (str) {
+ /*jshint maxcomplexity:7 */
var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;
var unit = 0;
var units = c.ETH_UNITS;
@@ -1362,7 +1554,7 @@ module.exports = {
};
-},{"./const":2}],13:[function(require,module,exports){
+},{"./const":2}],16:[function(require,module,exports){
/*
This file is part of ethereum.js.
@@ -1379,102 +1571,14 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/
-/** @file web3.js
+/** @file watches.js
* @authors:
- * Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com>
- * Marian Oancea <marian@ethdev.com>
- * Gav Wood <g@ethdev.com>
- * @date 2014
+ * @date 2015
*/
-if ("build" !== 'build') {/*
- var BigNumber = require('bignumber.js');
-*/}
-
-var utils = require('./utils');
-
-/// @returns an array of objects describing web3 api methods
-var web3Methods = function () {
- return [
- { name: 'sha3', call: 'web3_sha3' }
- ];
-};
-
-/// @returns an array of objects describing web3.eth api methods
-var ethMethods = function () {
- var blockCall = function (args) {
- return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber";
- };
-
- var transactionCall = function (args) {
- return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber';
- };
-
- var uncleCall = function (args) {
- return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber';
- };
-
- var methods = [
- { name: 'balanceAt', call: 'eth_balanceAt' },
- { name: 'register', call: 'eth_register' },
- { name: 'unregister', call: 'eth_unregister' },
- { name: 'stateAt', call: 'eth_stateAt' },
- { name: 'storageAt', call: 'eth_storageAt' },
- { name: 'countAt', call: 'eth_countAt'},
- { name: 'codeAt', call: 'eth_codeAt' },
- { name: 'transact', call: 'eth_transact' },
- { name: 'call', call: 'eth_call' },
- { name: 'block', call: blockCall },
- { name: 'transaction', call: transactionCall },
- { name: 'uncle', call: uncleCall },
- { name: 'compilers', call: 'eth_compilers' },
- { name: 'flush', call: 'eth_flush' },
- { name: 'lll', call: 'eth_lll' },
- { name: 'solidity', call: 'eth_solidity' },
- { name: 'serpent', call: 'eth_serpent' },
- { name: 'logs', call: 'eth_logs' }
- ];
- return methods;
-};
-
-/// @returns an array of objects describing web3.eth api properties
-var ethProperties = function () {
- return [
- { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' },
- { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' },
- { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' },
- { name: 'gasPrice', getter: 'eth_gasPrice' },
- { name: 'accounts', getter: 'eth_accounts' },
- { name: 'peerCount', getter: 'eth_peerCount' },
- { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' },
- { name: 'number', getter: 'eth_number'}
- ];
-};
-
-/// @returns an array of objects describing web3.db api methods
-var dbMethods = function () {
- return [
- { name: 'put', call: 'db_put' },
- { name: 'get', call: 'db_get' },
- { name: 'putString', call: 'db_putString' },
- { name: 'getString', call: 'db_getString' }
- ];
-};
-
-/// @returns an array of objects describing web3.shh api methods
-var shhMethods = function () {
- return [
- { name: 'post', call: 'shh_post' },
- { name: 'newIdentity', call: 'shh_newIdentity' },
- { name: 'haveIdentity', call: 'shh_haveIdentity' },
- { name: 'newGroup', call: 'shh_newGroup' },
- { name: 'addToGroup', call: 'shh_addToGroup' }
- ];
-};
-
/// @returns an array of objects describing web3.eth.watch api methods
-var ethWatchMethods = function () {
+var eth = function () {
var newFilter = function (args) {
return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';
};
@@ -1487,7 +1591,7 @@ var ethWatchMethods = function () {
};
/// @returns an array of objects describing web3.shh.watch api methods
-var shhWatchMethods = function () {
+var shh = function () {
return [
{ name: 'newFilter', call: 'shh_newFilter' },
{ name: 'uninstallFilter', call: 'shh_uninstallFilter' },
@@ -1495,6 +1599,57 @@ var shhWatchMethods = function () {
];
};
+module.exports = {
+ eth: eth,
+ shh: shh
+};
+
+
+},{}],17:[function(require,module,exports){
+/*
+ This file is part of ethereum.js.
+
+ ethereum.js is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ ethereum.js is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
+*/
+/** @file web3.js
+ * @authors:
+ * Jeffrey Wilcke <jeff@ethdev.com>
+ * Marek Kotewicz <marek@ethdev.com>
+ * Marian Oancea <marian@ethdev.com>
+ * Gav Wood <g@ethdev.com>
+ * @date 2014
+ */
+
+if ("build" !== 'build') {/*
+ var BigNumber = require('bignumber.js');
+*/}
+
+var eth = require('./eth');
+var db = require('./db');
+var shh = require('./shh');
+var watches = require('./watches');
+var filter = require('./filter');
+var utils = require('./utils');
+var requestManager = require('./requestmanager');
+
+/// @returns an array of objects describing web3 api methods
+var web3Methods = function () {
+ return [
+ { name: 'sha3', call: 'web3_sha3' }
+ ];
+};
+
/// creates methods in a given object based on method description on input
/// setups api calls for these methods
var setupMethods = function (obj, methods) {
@@ -1502,7 +1657,7 @@ var setupMethods = function (obj, methods) {
obj[method.name] = function () {
var args = Array.prototype.slice.call(arguments);
var call = typeof method.call === 'function' ? method.call(args) : method.call;
- return web3.provider.send({
+ return web3.manager.send({
method: call,
params: args
});
@@ -1516,14 +1671,14 @@ var setupProperties = function (obj, properties) {
properties.forEach(function (property) {
var proto = {};
proto.get = function () {
- return web3.provider.send({
+ return web3.manager.send({
method: property.getter
});
};
if (property.setter) {
proto.set = function (val) {
- return web3.provider.send({
+ return web3.manager.send({
method: property.setter,
params: [val]
});
@@ -1533,10 +1688,32 @@ var setupProperties = function (obj, properties) {
});
};
+/*jshint maxparams:4 */
+var startPolling = function (method, id, callback, uninstall) {
+ web3.manager.startPolling({
+ method: method,
+ params: [id]
+ }, id, callback, uninstall);
+};
+/*jshint maxparams:3 */
+
+var stopPolling = function (id) {
+ web3.manager.stopPolling(id);
+};
+
+var ethWatch = {
+ startPolling: startPolling.bind(null, 'eth_changed'),
+ stopPolling: stopPolling
+};
+
+var shhWatch = {
+ startPolling: startPolling.bind(null, 'shh_changed'),
+ stopPolling: stopPolling
+};
+
/// setups web3 object, and it's in-browser executed methods
var web3 = {
- _callbacks: {},
- _events: {},
+ manager: requestManager(),
providers: {},
/// @returns ascii string representation of hex value prefixed with 0x
@@ -1575,12 +1752,15 @@ var web3 = {
/// @param filter may be a string, object or event
/// @param indexed is optional, this is an object with optional event indexed params
/// @param options is optional, this is an object with optional event options ('max'...)
- watch: function (filter, indexed, options) {
- if (filter._isEvent) {
- return filter(indexed, options);
+ /// TODO: fix it, 4 params? no way
+ /*jshint maxparams:4 */
+ watch: function (fil, indexed, options, formatter) {
+ if (fil._isEvent) {
+ return fil(indexed, options);
}
- return new web3.filter(filter, ethWatch);
+ return filter(fil, ethWatch, formatter);
}
+ /*jshint maxparams:3 */
},
/// db object prototype
@@ -1588,54 +1768,44 @@ var web3 = {
/// shh object prototype
shh: {
-
/// @param filter may be a string, object or event
- watch: function (filter, indexed) {
- return new web3.filter(filter, shhWatch);
+ watch: function (fil) {
+ return filter(fil, shhWatch);
}
},
+ setProvider: function (provider) {
+ web3.manager.setProvider(provider);
+ },
+
+ /// Should be called to reset state of web3 object
+ /// Resets everything except manager
+ reset: function () {
+ web3.manager.reset();
+ }
};
/// setups all api methods
setupMethods(web3, web3Methods());
-setupMethods(web3.eth, ethMethods());
-setupProperties(web3.eth, ethProperties());
-setupMethods(web3.db, dbMethods());
-setupMethods(web3.shh, shhMethods());
-
-var ethWatch = {
- changed: 'eth_changed'
-};
-
-setupMethods(ethWatch, ethWatchMethods());
-
-var shhWatch = {
- changed: 'shh_changed'
-};
-
-setupMethods(shhWatch, shhWatchMethods());
-
-web3.setProvider = function(provider) {
- web3.provider.set(provider);
-};
+setupMethods(web3.eth, eth.methods());
+setupProperties(web3.eth, eth.properties());
+setupMethods(web3.db, db.methods());
+setupMethods(web3.shh, shh.methods());
+setupMethods(ethWatch, watches.eth());
+setupMethods(shhWatch, watches.shh());
module.exports = web3;
-},{"./utils":12}],"web3":[function(require,module,exports){
+},{"./db":4,"./eth":5,"./filter":7,"./requestmanager":12,"./shh":13,"./utils":15,"./watches":16}],"web3":[function(require,module,exports){
var web3 = require('./lib/web3');
-var ProviderManager = require('./lib/providermanager');
-web3.provider = new ProviderManager();
-web3.filter = require('./lib/filter');
web3.providers.HttpSyncProvider = require('./lib/httpsync');
web3.providers.QtSyncProvider = require('./lib/qtsync');
web3.eth.contract = require('./lib/contract');
web3.abi = require('./lib/abi');
-
module.exports = web3;
-},{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":9,"./lib/qtsync":10,"./lib/web3":13}]},{},["web3"])
+},{"./lib/abi":1,"./lib/contract":3,"./lib/httpsync":9,"./lib/qtsync":11,"./lib/web3":17}]},{},["web3"])
//# sourceMappingURL=ethereum.js.map
diff --git a/cmd/mist/assets/qml/main.qml b/cmd/mist/assets/qml/main.qml
index edf253418..f9ee6939d 100644
--- a/cmd/mist/assets/qml/main.qml
+++ b/cmd/mist/assets/qml/main.qml
@@ -981,7 +981,7 @@ ApplicationWindow {
anchors.top: parent.top
anchors.topMargin: 30
font.pointSize: 12
- text: "<h2>Mist (0.8.5)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br>Gustav Simonsson<br><h3>UX/UI</h3>Alex van de Sande<br>Fabian Vogelsteller"
+ text: "<h2>Mist (0.8.6)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br>Gustav Simonsson<br><h3>UX/UI</h3>Alex van de Sande<br>Fabian Vogelsteller"
}
}
diff --git a/cmd/mist/ext_app.go b/cmd/mist/ext_app.go
index 7ac51db0b..84041a553 100644
--- a/cmd/mist/ext_app.go
+++ b/cmd/mist/ext_app.go
@@ -24,7 +24,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/ui/qt"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/qml"
)
@@ -116,7 +115,3 @@ func (app *ExtApplication) mainLoop() {
}
}
}
-
-func (self *ExtApplication) Watch(filterOptions map[string]interface{}, identifier string) {
- self.filters[identifier] = qt.NewFilterFromMap(filterOptions, self.eth)
-}
diff --git a/cmd/mist/flags.go b/cmd/mist/flags.go
index d9487de9e..139af5923 100644
--- a/cmd/mist/flags.go
+++ b/cmd/mist/flags.go
@@ -26,80 +26,46 @@ import (
"fmt"
"log"
"os"
- "os/user"
"path"
- "path/filepath"
"runtime"
- "bitbucket.org/kardianos/osext"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/vm"
)
var (
- Identifier string
- KeyRing string
- KeyStore string
- StartRpc bool
- StartWebSockets bool
- RpcPort int
- WsPort int
- OutboundPort string
- ShowGenesis bool
- AddPeer string
- MaxPeer int
- GenAddr bool
- BootNodes string
- NodeKey *ecdsa.PrivateKey
- NAT nat.Interface
- SecretFile string
- ExportDir string
- NonInteractive bool
- Datadir string
- LogFile string
- ConfigFile string
- DebugFile string
- LogLevel int
- VmType int
- MinerThreads int
+ Identifier string
+ KeyRing string
+ KeyStore string
+ StartRpc bool
+ RpcListenAddress string
+ RpcPort int
+ OutboundPort string
+ ShowGenesis bool
+ AddPeer string
+ MaxPeer int
+ GenAddr bool
+ BootNodes string
+ NodeKey *ecdsa.PrivateKey
+ NAT nat.Interface
+ SecretFile string
+ ExportDir string
+ NonInteractive bool
+ Datadir string
+ LogFile string
+ ConfigFile string
+ DebugFile string
+ LogLevel int
+ VmType int
+ MinerThreads int
)
// flags specific to gui client
var AssetPath string
-
-//TODO: If we re-use the one defined in cmd.go the binary osx image crashes. If somebody finds out why we can dry this up.
-func defaultAssetPath() string {
- var assetPath string
- // If the current working directory is the go-ethereum dir
- // assume a debug build and use the source directory as
- // asset directory.
- pwd, _ := os.Getwd()
- if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") {
- assetPath = path.Join(pwd, "assets")
- } else {
- switch runtime.GOOS {
- case "darwin":
- // Get Binary Directory
- exedir, _ := osext.ExecutableFolder()
- assetPath = filepath.Join(exedir, "../Resources")
- case "linux":
- assetPath = "/usr/share/mist"
- case "windows":
- assetPath = "./assets"
- default:
- assetPath = "."
- }
- }
- return assetPath
-}
-func defaultDataDir() string {
- usr, _ := user.Current()
- return path.Join(usr.HomeDir, ".ethereum")
-}
-
-var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
+var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
func Init() {
// TODO: move common flag processing to cmd/utils
@@ -111,22 +77,21 @@ func Init() {
flag.IntVar(&VmType, "vm", 0, "Virtual Machine type: 0-1: standard, debug")
flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
- flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
+ flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file")
+ flag.StringVar(&RpcListenAddress, "rpcaddr", "127.0.0.1", "address for json-rpc server to listen on")
flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
- flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on")
flag.BoolVar(&StartRpc, "rpc", true, "start rpc server")
- flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
- flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use")
+ flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
- flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
+ flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5 (= silent,error,warn,info,debug,debug detail)")
- flag.StringVar(&AssetPath, "asset_path", defaultAssetPath(), "absolute path to GUI assets directory")
+ flag.StringVar(&AssetPath, "asset_path", ethutil.DefaultAssetPath(), "absolute path to GUI assets directory")
// Network stuff
var (
diff --git a/cmd/mist/main.go b/cmd/mist/main.go
index ad6eb5bec..1d4403848 100644
--- a/cmd/mist/main.go
+++ b/cmd/mist/main.go
@@ -36,7 +36,7 @@ import (
const (
ClientIdentifier = "Mist"
- Version = "0.8.5"
+ Version = "0.8.6"
)
var ethereum *eth.Ethereum
@@ -73,11 +73,7 @@ func run() error {
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
if StartRpc {
- utils.StartRpc(ethereum, RpcPort)
- }
-
- if StartWebSockets {
- utils.StartWebSockets(ethereum, WsPort)
+ utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
}
gui := NewWindow(ethereum, config, KeyRing, LogLevel)
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index bc8fafafb..723cfa887 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -25,12 +25,8 @@ import (
"fmt"
"os"
"os/signal"
- "path"
- "path/filepath"
"regexp"
- "runtime"
- "bitbucket.org/kardianos/osext"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
@@ -39,7 +35,6 @@ import (
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/rlp"
rpchttp "github.com/ethereum/go-ethereum/rpc/http"
- rpcws "github.com/ethereum/go-ethereum/rpc/ws"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/xeth"
)
@@ -132,31 +127,6 @@ func StartEthereum(ethereum *eth.Ethereum) {
})
}
-func DefaultAssetPath() string {
- var assetPath string
- // If the current working directory is the go-ethereum dir
- // assume a debug build and use the source directory as
- // asset directory.
- pwd, _ := os.Getwd()
- if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") {
- assetPath = path.Join(pwd, "assets")
- } else {
- switch runtime.GOOS {
- case "darwin":
- // Get Binary Directory
- exedir, _ := osext.ExecutableFolder()
- assetPath = filepath.Join(exedir, "../Resources")
- case "linux":
- assetPath = "/usr/share/mist"
- case "windows":
- assetPath = "./assets"
- default:
- assetPath = "."
- }
- }
- return assetPath
-}
-
func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
var err error
@@ -189,9 +159,9 @@ func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, Secre
clilogger.Infof("Main address %x\n", keyManager.Address())
}
-func StartRpc(ethereum *eth.Ethereum, RpcPort int) {
+func StartRpc(ethereum *eth.Ethereum, RpcListenAddress string, RpcPort int) {
var err error
- ethereum.RpcServer, err = rpchttp.NewRpcHttpServer(xeth.New(ethereum), RpcPort)
+ ethereum.RpcServer, err = rpchttp.NewRpcHttpServer(xeth.New(ethereum), RpcListenAddress, RpcPort)
if err != nil {
clilogger.Errorf("Could not start RPC interface (port %v): %v", RpcPort, err)
} else {
@@ -199,18 +169,6 @@ func StartRpc(ethereum *eth.Ethereum, RpcPort int) {
}
}
-func StartWebSockets(eth *eth.Ethereum, wsPort int) {
- clilogger.Infoln("Starting WebSockets")
-
- var err error
- eth.WsServer, err = rpcws.NewWebSocketServer(xeth.New(eth), wsPort)
- if err != nil {
- clilogger.Errorf("Could not start RPC interface (port %v): %v", wsPort, err)
- } else {
- go eth.WsServer.Start()
- }
-}
-
var gminer *miner.Miner
func GetMiner() *miner.Miner {
diff --git a/core/block_processor.go b/core/block_processor.go
index fd591a29d..7eaeb5be0 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -48,9 +48,8 @@ type BlockProcessor struct {
func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
sm := &BlockProcessor{
- db: db,
- mem: make(map[string]*big.Int),
- //Pow: &ethash.Ethash{},
+ db: db,
+ mem: make(map[string]*big.Int),
Pow: ezp.New(),
bc: chainManager,
eventMux: eventMux,
@@ -62,7 +61,7 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM
func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) {
coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase)
- coinbase.SetGasPool(CalcGasLimit(parent, block))
+ coinbase.SetGasPool(block.Header().GasLimit)
// Process the transactions on to parent state
receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess)
@@ -100,7 +99,8 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
// Notify all subscribers
if !transientProcess {
go self.eventMux.Post(TxPostEvent{tx})
- go self.eventMux.Post(statedb.Logs())
+ logs := statedb.Logs()
+ go self.eventMux.Post(logs)
}
return receipt, txGas, err
@@ -247,6 +247,11 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd)
}
+ expl := CalcGasLimit(parent, block)
+ if expl.Cmp(block.Header().GasLimit) != 0 {
+ return fmt.Errorf("GasLimit check failed for block %v, %v", block.Header().GasLimit, expl)
+ }
+
if block.Time() < parent.Time() {
return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time)
}
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 9ef091c3c..959bfd398 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -85,12 +85,14 @@ type ChainManager struct {
lastBlockHash []byte
transState *state.StateDB
+ txState *state.StateDB
}
func NewChainManager(db ethutil.Database, mux *event.TypeMux) *ChainManager {
bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: mux}
bc.setLastBlock()
bc.transState = bc.State().Copy()
+ bc.txState = bc.State().Copy()
return bc
}
@@ -138,6 +140,19 @@ func (self *ChainManager) TransState() *state.StateDB {
return self.transState
}
+func (self *ChainManager) TxState() *state.StateDB {
+ self.tsmu.RLock()
+ defer self.tsmu.RUnlock()
+
+ return self.txState
+}
+
+func (self *ChainManager) setTxState(state *state.StateDB) {
+ self.tsmu.Lock()
+ defer self.tsmu.Unlock()
+ self.txState = state
+}
+
func (self *ChainManager) setTransState(statedb *state.StateDB) {
self.transState = statedb
}
@@ -268,7 +283,6 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain
break
}
}
- fmt.Printf("get hash %x (%d)\n", hash, len(chain))
return
}
@@ -363,6 +377,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
defer self.tsmu.Unlock()
for _, block := range chain {
+ // Call in to the block processor and check for errors. It's likely that if one block fails
+ // all others will fail too (unless a known block is returned).
td, err := self.processor.Process(block)
if err != nil {
if IsKnownBlockErr(err) {
@@ -377,11 +393,15 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
}
block.Td = td
- var chain, split bool
+ var canonical, split bool
self.mu.Lock()
{
+ // Write block to database. Eventually we'll have to improve on this and throw away blocks that are
+ // not in the canonical chain.
self.write(block)
cblock := self.currentBlock
+ // Compare the TD of the last known block in the canonical chain to make sure it's greater.
+ // At this point it's possible that a different chain (fork) becomes the new canonical chain.
if td.Cmp(self.td) > 0 {
if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 {
chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td)
@@ -391,17 +411,18 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
self.setTotalDifficulty(td)
self.insert(block)
- chain = true
+ canonical = true
}
}
self.mu.Unlock()
- if chain {
+ if canonical {
+ self.setTransState(state.New(block.Root(), self.db))
self.eventMux.Post(ChainEvent{block, td})
}
if split {
- self.setTransState(state.New(block.Root(), self.db))
+ self.setTxState(state.New(block.Root(), self.db))
self.eventMux.Post(ChainSplitEvent{block})
}
}
diff --git a/core/filter.go b/core/filter.go
index cdf7b282d..c61c9e998 100644
--- a/core/filter.go
+++ b/core/filter.go
@@ -17,7 +17,7 @@ type FilterOptions struct {
Latest int64
Address [][]byte
- Topics [][]byte
+ Topics [][][]byte
Skip int
Max int
@@ -31,7 +31,7 @@ type Filter struct {
skip int
address [][]byte
max int
- topics [][]byte
+ topics [][][]byte
BlockCallback func(*types.Block)
PendingCallback func(*types.Block)
@@ -44,6 +44,8 @@ func NewFilter(eth Backend) *Filter {
return &Filter{eth: eth}
}
+// SetOptions copies the filter options to the filter it self. The reason for this "silly" copy
+// is simply because named arguments in this case is extremely nice and readable.
func (self *Filter) SetOptions(options FilterOptions) {
self.earliest = options.Earliest
self.latest = options.Latest
@@ -69,7 +71,7 @@ func (self *Filter) SetAddress(addr [][]byte) {
self.address = addr
}
-func (self *Filter) SetTopics(topics [][]byte) {
+func (self *Filter) SetTopics(topics [][][]byte) {
self.topics = topics
}
@@ -149,10 +151,18 @@ Logs:
continue
}
- max := int(math.Min(float64(len(self.topics)), float64(len(log.Topics()))))
- for i := 0; i < max; i++ {
- if !bytes.Equal(log.Topics()[i], self.topics[i]) {
- continue Logs
+ logTopics := make([][]byte, len(self.topics))
+ copy(logTopics, log.Topics())
+
+ for i, topics := range self.topics {
+ for _, topic := range topics {
+ var match bool
+ if bytes.Equal(log.Topics()[i], topic) {
+ match = true
+ }
+ if !match {
+ continue Logs
+ }
}
}
@@ -177,8 +187,15 @@ func (self *Filter) bloomFilter(block *types.Block) bool {
}
}
- for _, topic := range self.topics {
- if !types.BloomLookup(block.Bloom(), topic) {
+ for _, sub := range self.topics {
+ var included bool
+ for _, topic := range sub {
+ if types.BloomLookup(block.Bloom(), topic) {
+ included = true
+ break
+ }
+ }
+ if !included {
return false
}
}
diff --git a/core/genesis.go b/core/genesis.go
index 75b4fc100..decffc541 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -51,8 +51,6 @@ func GenesisBlock(db ethutil.Database) *types.Block {
statedb.Sync()
genesis.Header().Root = statedb.Root()
- fmt.Printf("+++ genesis +++\nRoot: %x\nHash: %x\n", genesis.Header().Root, genesis.Hash())
-
return genesis
}
diff --git a/core/state_transition.go b/core/state_transition.go
index 36ffa23d9..7331fdd4a 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -126,7 +126,7 @@ func (self *StateTransition) BuyGas() error {
self.AddGas(self.msg.Gas())
self.initialGas.Set(self.msg.Gas())
- sender.SubAmount(MessageGasValue(self.msg))
+ sender.SubBalance(MessageGasValue(self.msg))
return nil
}
@@ -251,7 +251,7 @@ func (self *StateTransition) RefundGas() {
coinbase, sender := self.Coinbase(), self.From()
// Return remaining gas
remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice())
- sender.AddAmount(remaining)
+ sender.AddBalance(remaining)
uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2)
for addr, ref := range self.state.Refunds() {
diff --git a/crypto/key_store_plain.go b/crypto/key_store_plain.go
index 6b76962a0..338a4a2c3 100644
--- a/crypto/key_store_plain.go
+++ b/crypto/key_store_plain.go
@@ -30,7 +30,6 @@ import (
"io"
"io/ioutil"
"os"
- "os/user"
"path"
)
@@ -48,12 +47,6 @@ type keyStorePlain struct {
keysDirPath string
}
-// TODO: copied from cmd/ethereum/flags.go
-func DefaultDataDir() string {
- usr, _ := user.Current()
- return path.Join(usr.HomeDir, ".ethereum")
-}
-
func NewKeyStorePlain(path string) KeyStore2 {
return &keyStorePlain{path}
}
@@ -126,8 +119,11 @@ func GetKeyAddresses(keysDirPath string) (addresses [][]byte, err error) {
}
addresses = make([][]byte, len(fileInfos))
for i, fileInfo := range fileInfos {
- addresses[i] = make([]byte, 40)
- addresses[i] = []byte(fileInfo.Name())
+ address, err := hex.DecodeString(fileInfo.Name())
+ if err != nil {
+ continue
+ }
+ addresses[i] = address
}
return addresses, err
}
diff --git a/crypto/key_store_test.go b/crypto/key_store_test.go
index 485d8f536..11531d460 100644
--- a/crypto/key_store_test.go
+++ b/crypto/key_store_test.go
@@ -2,12 +2,13 @@ package crypto
import (
"github.com/ethereum/go-ethereum/crypto/randentropy"
+ "github.com/ethereum/go-ethereum/ethutil"
"reflect"
"testing"
)
func TestKeyStorePlain(t *testing.T) {
- ks := NewKeyStorePlain(DefaultDataDir())
+ ks := NewKeyStorePlain(ethutil.DefaultDataDir())
pass := "" // not used but required by API
k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
if err != nil {
@@ -35,7 +36,7 @@ func TestKeyStorePlain(t *testing.T) {
}
func TestKeyStorePassphrase(t *testing.T) {
- ks := NewKeyStorePassphrase(DefaultDataDir())
+ ks := NewKeyStorePassphrase(ethutil.DefaultDataDir())
pass := "foo"
k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
if err != nil {
@@ -61,7 +62,7 @@ func TestKeyStorePassphrase(t *testing.T) {
}
func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
- ks := NewKeyStorePassphrase(DefaultDataDir())
+ ks := NewKeyStorePassphrase(ethutil.DefaultDataDir())
pass := "foo"
k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
if err != nil {
@@ -89,7 +90,7 @@ func TestImportPreSaleKey(t *testing.T) {
// python pyethsaletool.py genwallet
// with password "foo"
fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}"
- ks := NewKeyStorePassphrase(DefaultDataDir())
+ ks := NewKeyStorePassphrase(ethutil.DefaultDataDir())
pass := "foo"
_, err := ImportPreSaleKey(ks, []byte(fileContent), pass)
if err != nil {
diff --git a/eth/backend.go b/eth/backend.go
index 0e5d24429..efdd43bf5 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event"
- ethlogger "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
@@ -23,8 +23,8 @@ import (
)
var (
- logger = ethlogger.NewLogger("SERV")
- jsonlogger = ethlogger.NewJsonLogger()
+ ethlogger = logger.NewLogger("SERV")
+ jsonlogger = logger.NewJsonLogger()
defaultBootNodes = []*discover.Node{
// ETH/DEV cmd/bootnode
@@ -74,7 +74,7 @@ func (cfg *Config) parseBootNodes() []*discover.Node {
}
n, err := discover.ParseNode(url)
if err != nil {
- logger.Errorf("Bootstrap URL %s: %v\n", url, err)
+ ethlogger.Errorf("Bootstrap URL %s: %v\n", url, err)
continue
}
ns = append(ns, n)
@@ -98,7 +98,7 @@ func (cfg *Config) nodeKey() (*ecdsa.PrivateKey, error) {
return nil, fmt.Errorf("could not generate server key: %v", err)
}
if err := ioutil.WriteFile(keyfile, crypto.FromECDSA(key), 0600); err != nil {
- logger.Errorln("could not persist nodekey: ", err)
+ ethlogger.Errorln("could not persist nodekey: ", err)
}
return key, nil
}
@@ -127,17 +127,16 @@ type Ethereum struct {
miner *miner.Miner
RpcServer rpc.RpcServer
- WsServer rpc.RpcServer
keyManager *crypto.KeyManager
- logger ethlogger.LogSystem
+ logger logger.LogSystem
Mining bool
}
func New(config *Config) (*Ethereum, error) {
// Boostrap database
- logger := ethlogger.New(config.DataDir, config.LogFile, config.LogLevel, config.LogFormat)
+ ethlogger := logger.New(config.DataDir, config.LogFile, config.LogLevel, config.LogFormat)
db, err := ethdb.NewLDBDatabase("blockchain")
if err != nil {
return nil, err
@@ -147,7 +146,8 @@ func New(config *Config) (*Ethereum, error) {
d, _ := db.Get([]byte("ProtocolVersion"))
protov := ethutil.NewValue(d).Uint()
if protov != ProtocolVersion && protov != 0 {
- return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, ethutil.Config.ExecPath+"/database")
+ path := path.Join(config.DataDir, "blockchain")
+ return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, path)
}
// Create new keymanager
@@ -173,7 +173,7 @@ func New(config *Config) (*Ethereum, error) {
keyManager: keyManager,
blacklist: p2p.NewBlacklist(),
eventMux: &event.TypeMux{},
- logger: logger,
+ logger: ethlogger,
}
eth.chainManager = core.NewChainManager(db, eth.EventMux())
@@ -215,7 +215,7 @@ func New(config *Config) (*Ethereum, error) {
}
func (s *Ethereum) KeyManager() *crypto.KeyManager { return s.keyManager }
-func (s *Ethereum) Logger() ethlogger.LogSystem { return s.logger }
+func (s *Ethereum) Logger() logger.LogSystem { return s.logger }
func (s *Ethereum) Name() string { return s.net.Name }
func (s *Ethereum) ChainManager() *core.ChainManager { return s.chainManager }
func (s *Ethereum) BlockProcessor() *core.BlockProcessor { return s.blockProcessor }
@@ -233,7 +233,7 @@ func (s *Ethereum) Coinbase() []byte { return nil } // TODO
// Start the ethereum
func (s *Ethereum) Start() error {
- jsonlogger.LogJson(&ethlogger.LogStarting{
+ jsonlogger.LogJson(&logger.LogStarting{
ClientString: s.net.Name,
ProtocolVersion: ProtocolVersion,
})
@@ -259,7 +259,7 @@ func (s *Ethereum) Start() error {
s.blockSub = s.eventMux.Subscribe(core.NewMinedBlockEvent{})
go s.blockBroadcastLoop()
- logger.Infoln("Server started")
+ ethlogger.Infoln("Server started")
return nil
}
@@ -284,9 +284,7 @@ func (s *Ethereum) Stop() {
if s.RpcServer != nil {
s.RpcServer.Stop()
}
- if s.WsServer != nil {
- s.WsServer.Stop()
- }
+
s.txPool.Stop()
s.eventMux.Stop()
s.blockPool.Stop()
@@ -294,7 +292,7 @@ func (s *Ethereum) Stop() {
s.whisper.Stop()
}
- logger.Infoln("Server stopped")
+ ethlogger.Infoln("Server stopped")
close(s.shutdownChan)
}
diff --git a/eth/block_pool.go b/eth/block_pool.go
index 13016c694..124a9e8c0 100644
--- a/eth/block_pool.go
+++ b/eth/block_pool.go
@@ -12,11 +12,11 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethutil"
- ethlogger "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
)
-var poolLogger = ethlogger.NewLogger("Blockpool")
+var poolLogger = logger.NewLogger("Blockpool")
const (
blockHashesBatchSize = 256
diff --git a/eth/block_pool_test.go b/eth/block_pool_test.go
index 331dbe504..3d1b28315 100644
--- a/eth/block_pool_test.go
+++ b/eth/block_pool_test.go
@@ -12,19 +12,19 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
- ethlogger "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
)
const waitTimeout = 60 // seconds
-var logsys = ethlogger.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlogger.LogLevel(ethlogger.DebugDetailLevel))
+var logsys = logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.LogLevel(logger.DebugDetailLevel))
var ini = false
func logInit() {
if !ini {
- ethlogger.AddLogSystem(logsys)
+ logger.AddLogSystem(logsys)
ini = true
}
}
diff --git a/eth/protocol.go b/eth/protocol.go
index 8221c1b29..a5cc8ee1a 100644
--- a/eth/protocol.go
+++ b/eth/protocol.go
@@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethutil"
+ "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -137,6 +138,12 @@ func (self *ethProtocol) handle() error {
if err := msg.Decode(&txs); err != nil {
return self.protoError(ErrDecode, "msg %v: %v", msg, err)
}
+ for _, tx := range txs {
+ jsonlogger.LogJson(&logger.EthTxReceived{
+ TxHash: ethutil.Bytes2Hex(tx.Hash()),
+ RemoteId: self.peer.ID().String(),
+ })
+ }
self.txPool.AddTransactions(txs)
case GetBlockHashesMsg:
diff --git a/eth/protocol_test.go b/eth/protocol_test.go
index a91806a1c..87d8974d5 100644
--- a/eth/protocol_test.go
+++ b/eth/protocol_test.go
@@ -12,12 +12,12 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
- ethlogger "github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
)
-var sys = ethlogger.NewStdLogSystem(os.Stdout, log.LstdFlags, ethlogger.LogLevel(ethlogger.DebugDetailLevel))
+var sys = logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.LogLevel(logger.DebugDetailLevel))
type testMsgReadWriter struct {
in chan p2p.Msg
diff --git a/ethutil/common.go b/ethutil/common.go
index 2ef2440c7..9b66763b8 100644
--- a/ethutil/common.go
+++ b/ethutil/common.go
@@ -3,10 +3,60 @@ package ethutil
import (
"fmt"
"math/big"
+ "os"
+ "os/user"
+ "path"
+ "path/filepath"
"runtime"
"time"
+
+ "github.com/kardianos/osext"
)
+func DefaultAssetPath() string {
+ var assetPath string
+ pwd, _ := os.Getwd()
+ srcdir := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist")
+
+ // If the current working directory is the go-ethereum dir
+ // assume a debug build and use the source directory as
+ // asset directory.
+ if pwd == srcdir {
+ assetPath = path.Join(pwd, "assets")
+ } else {
+ switch runtime.GOOS {
+ case "darwin":
+ // Get Binary Directory
+ exedir, _ := osext.ExecutableFolder()
+ assetPath = filepath.Join(exedir, "../Resources")
+ case "linux":
+ assetPath = "/usr/share/mist"
+ case "windows":
+ assetPath = "./assets"
+ default:
+ assetPath = "."
+ }
+ }
+
+ // Check if the assetPath exists. If not, try the source directory
+ // This happens when binary is run from outside cmd/mist directory
+ if _, err := os.Stat(assetPath); os.IsNotExist(err) {
+ assetPath = path.Join(srcdir, "assets")
+ }
+
+ return assetPath
+}
+
+func DefaultDataDir() string {
+ usr, _ := user.Current()
+ if runtime.GOOS == "darwin" {
+ return path.Join(usr.HomeDir, "Library/Ethereum")
+ } else if runtime.GOOS == "windows" {
+ return path.Join(usr.HomeDir, "AppData/Roaming/Ethereum")
+ } else {
+ return path.Join(usr.HomeDir, ".ethereum")
+ }
+}
func IsWindows() bool {
return runtime.GOOS == "windows"
}
diff --git a/event/filter/eth_filter.go b/event/filter/eth_filter.go
index 73d2cd935..4ba66a7e0 100644
--- a/event/filter/eth_filter.go
+++ b/event/filter/eth_filter.go
@@ -3,7 +3,6 @@ package filter
// TODO make use of the generic filtering system
import (
- "fmt"
"sync"
"github.com/ethereum/go-ethereum/core"
@@ -75,7 +74,6 @@ out:
case event := <-events.Chan():
switch event := event.(type) {
case core.ChainEvent:
- fmt.Println("filter start")
self.filterMu.RLock()
for _, filter := range self.filters {
if filter.BlockCallback != nil {
@@ -83,7 +81,6 @@ out:
}
}
self.filterMu.RUnlock()
- fmt.Println("filter stop")
case core.PendingBlockEvent:
self.filterMu.RLock()
diff --git a/install.sh b/install.sh
deleted file mode 100755
index 30a3802e4..000000000
--- a/install.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/sh
-
-if [ "$1" == "" ]; then
- echo "Usage $0 executable branch"
- echo "executable ethereum | mist"
- echo "branch develop | master"
- exit
-fi
-
-exe=$1
-path=$exe
-branch=$2
-
-if [ "$branch" == "develop" ]; then
- path="cmd/$exe"
-fi
-
-# Test if go is installed
-command -v go >/dev/null 2>&1 || { echo >&2 "Unable to find 'go'. This script requires go."; exit 1; }
-
-# Test if $GOPATH is set
-if [ "$GOPATH" == "" ]; then
- echo "\$GOPATH not set"
- exit
-fi
-
-echo "changing branch to $branch"
-cd $GOPATH/src/github.com/ethereum/go-ethereum
-git checkout $branch
-
-# installing package dependencies doesn't work for develop
-# branch as go get always pulls from master head
-# so build will continue to fail, but this installs locally
-# for people who git clone since go install will manage deps
-
-#echo "go get -u -d github.com/ethereum/go-ethereum/$path"
-#go get -v -u -d github.com/ethereum/go-ethereum/$path
-#if [ $? != 0 ]; then
-# echo "go get failed"
-# exit
-#fi
-
-cd $GOPATH/src/github.com/ethereum/go-ethereum/$path
-
-if [ "$exe" == "mist" ]; then
- echo "Building Mist GUI. Assuming Qt is installed. If this step"
- echo "fails; please refer to: https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)"
-else
- echo "Building ethereum CLI."
-fi
-
-go install
-echo "done. Please run $exe :-)"
diff --git a/javascript/javascript_runtime.go b/javascript/javascript_runtime.go
index 0aa0f73e2..beaca45b9 100644
--- a/javascript/javascript_runtime.go
+++ b/javascript/javascript_runtime.go
@@ -24,7 +24,7 @@ var jsrelogger = logger.NewLogger("JSRE")
type JSRE struct {
ethereum *eth.Ethereum
Vm *otto.Otto
- pipe *xeth.XEth
+ xeth *xeth.XEth
events event.Subscription
@@ -67,7 +67,7 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE {
// We have to make sure that, whoever calls this, calls "Stop"
go re.mainLoop()
- re.Bind("eth", &JSEthereum{re.pipe, re.Vm, ethereum})
+ re.Bind("eth", &JSEthereum{re.xeth, re.Vm, ethereum})
re.initStdFuncs()
@@ -113,12 +113,10 @@ func (self *JSRE) mainLoop() {
func (self *JSRE) initStdFuncs() {
t, _ := self.Vm.Get("eth")
eth := t.Object()
- eth.Set("watch", self.watch)
- eth.Set("addPeer", self.addPeer)
+ eth.Set("connect", self.connect)
eth.Set("require", self.require)
eth.Set("stopMining", self.stopMining)
eth.Set("startMining", self.startMining)
- eth.Set("execBlock", self.execBlock)
eth.Set("dump", self.dump)
eth.Set("export", self.export)
}
@@ -152,7 +150,8 @@ func (self *JSRE) dump(call otto.FunctionCall) otto.Value {
}
statedb := state.New(block.Root(), self.ethereum.Db())
- v, _ := self.Vm.ToValue(statedb.Dump())
+
+ v, _ := self.Vm.ToValue(statedb.RawDump())
return v
}
@@ -167,36 +166,7 @@ func (self *JSRE) startMining(call otto.FunctionCall) otto.Value {
return v
}
-// eth.watch
-func (self *JSRE) watch(call otto.FunctionCall) otto.Value {
- addr, _ := call.Argument(0).ToString()
- var storageAddr string
- var cb otto.Value
- var storageCallback bool
- if len(call.ArgumentList) > 2 {
- storageCallback = true
- storageAddr, _ = call.Argument(1).ToString()
- cb = call.Argument(2)
- } else {
- cb = call.Argument(1)
- }
-
- if storageCallback {
- self.objectCb[addr+storageAddr] = append(self.objectCb[addr+storageAddr], cb)
-
- // event := "storage:" + string(ethutil.Hex2Bytes(addr)) + ":" + string(ethutil.Hex2Bytes(storageAddr))
- // self.ethereum.EventMux().Subscribe(event, self.changeChan)
- } else {
- self.objectCb[addr] = append(self.objectCb[addr], cb)
-
- // event := "object:" + string(ethutil.Hex2Bytes(addr))
- // self.ethereum.EventMux().Subscribe(event, self.changeChan)
- }
-
- return otto.UndefinedValue()
-}
-
-func (self *JSRE) addPeer(call otto.FunctionCall) otto.Value {
+func (self *JSRE) connect(call otto.FunctionCall) otto.Value {
nodeURL, err := call.Argument(0).ToString()
if err != nil {
return otto.FalseValue()
@@ -222,22 +192,12 @@ func (self *JSRE) require(call otto.FunctionCall) otto.Value {
return t
}
-func (self *JSRE) execBlock(call otto.FunctionCall) otto.Value {
- hash, err := call.Argument(0).ToString()
- if err != nil {
- return otto.UndefinedValue()
- }
-
- err = utils.BlockDo(self.ethereum, ethutil.Hex2Bytes(hash))
- if err != nil {
- fmt.Println(err)
+func (self *JSRE) export(call otto.FunctionCall) otto.Value {
+ if len(call.ArgumentList) == 0 {
+ fmt.Println("err: require file name")
return otto.FalseValue()
}
- return otto.TrueValue()
-}
-
-func (self *JSRE) export(call otto.FunctionCall) otto.Value {
fn, err := call.Argument(0).ToString()
if err != nil {
fmt.Println(err)
diff --git a/javascript/js_lib.go b/javascript/js_lib.go
index dd1fe5f4d..f828ca389 100644
--- a/javascript/js_lib.go
+++ b/javascript/js_lib.go
@@ -16,7 +16,7 @@ function pp(object) {
str += " ]";
} else if(typeof(object) === "object") {
str += "{ ";
- var last = Object.keys(object).sort().pop()
+ var last = Object.keys(object).pop()
for(var k in object) {
str += k + ": " + pp(object[k]);
diff --git a/javascript/types.go b/javascript/types.go
index 17f1b739e..b4da160fc 100644
--- a/javascript/types.go
+++ b/javascript/types.go
@@ -6,7 +6,6 @@ import (
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/state"
- "github.com/ethereum/go-ethereum/ui"
"github.com/ethereum/go-ethereum/xeth"
"github.com/obscuren/otto"
)
@@ -96,17 +95,3 @@ func (self *JSEthereum) toVal(v interface{}) otto.Value {
return result
}
-
-func (self *JSEthereum) Messages(object map[string]interface{}) otto.Value {
- filter := ui.NewFilterFromMap(object, self.ethereum)
-
- logs := filter.Find()
- var jslogs []JSLog
- for _, m := range logs {
- jslogs = append(jslogs, NewJSLog(m))
- }
-
- v, _ := self.vm.ToValue(jslogs)
-
- return v
-}
diff --git a/logger/types.go b/logger/types.go
index 7ab4a2b8c..86408620e 100644
--- a/logger/types.go
+++ b/logger/types.go
@@ -1,6 +1,7 @@
package logger
import (
+ "math/big"
"time"
)
@@ -53,10 +54,10 @@ func (l *P2PDisconnected) EventName() string {
}
type EthMinerNewBlock struct {
- BlockHash string `json:"block_hash"`
- BlockNumber int `json:"block_number"`
- ChainHeadHash string `json:"chain_head_hash"`
- BlockPrevHash string `json:"block_prev_hash"`
+ BlockHash string `json:"block_hash"`
+ BlockNumber *big.Int `json:"block_number"`
+ ChainHeadHash string `json:"chain_head_hash"`
+ BlockPrevHash string `json:"block_prev_hash"`
LogEvent
}
diff --git a/miner/miner.go b/miner/miner.go
index 0cc2361c8..6b416be8e 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -52,10 +52,5 @@ func (self *Miner) Stop() {
}
func (self *Miner) HashRate() int64 {
- var tot int64
- for _, agent := range self.worker.agents {
- tot += agent.Pow().GetHashrate()
- }
-
- return tot
+ return self.worker.HashRate()
}
diff --git a/miner/worker.go b/miner/worker.go
index 1f3a52ab5..bc1c8e194 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -5,16 +5,20 @@ import (
"math/big"
"sort"
"sync"
+ "time"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/state"
"gopkg.in/fatih/set.v0"
)
+var jsonlogger = logger.NewJsonLogger()
+
type environment struct {
totalUsedGas *big.Int
state *state.StateDB
@@ -111,6 +115,8 @@ func (self *worker) register(agent Agent) {
func (self *worker) update() {
events := self.mux.Subscribe(core.ChainEvent{}, core.NewMinedBlockEvent{})
+ timer := time.NewTicker(2 * time.Second)
+
out:
for {
select {
@@ -129,6 +135,8 @@ out:
agent.Stop()
}
break out
+ case <-timer.C:
+ minerlogger.Debugln("Hash rate:", self.HashRate(), "Khash")
}
}
@@ -141,7 +149,12 @@ func (self *worker) wait() {
block := self.current.block
if block.Number().Uint64() == work.Number && block.Nonce() == nil {
self.current.block.Header().Nonce = work.Nonce
-
+ jsonlogger.LogJson(&logger.EthMinerNewBlock{
+ BlockHash: ethutil.Bytes2Hex(block.Hash()),
+ BlockNumber: block.Number(),
+ ChainHeadHash: ethutil.Bytes2Hex(block.ParentHeaderHash),
+ BlockPrevHash: ethutil.Bytes2Hex(block.ParentHeaderHash),
+ })
if err := self.chain.InsertChain(types.Blocks{self.current.block}); err == nil {
self.mux.Post(core.NewMinedBlockEvent{self.current.block})
} else {
@@ -197,7 +210,7 @@ gasLimit:
}
self.eth.TxPool().RemoveSet(remove)
- self.current.coinbase.AddAmount(core.BlockReward)
+ self.current.coinbase.AddBalance(core.BlockReward)
self.current.state.Update(ethutil.Big0)
self.push()
@@ -225,7 +238,7 @@ func (self *worker) commitUncle(uncle *types.Header) error {
}
uncleAccount := self.current.state.GetAccount(uncle.Coinbase)
- uncleAccount.AddAmount(uncleReward)
+ uncleAccount.AddBalance(uncleReward)
self.current.coinbase.AddBalance(uncleReward)
@@ -244,3 +257,12 @@ func (self *worker) commitTransaction(tx *types.Transaction) error {
return nil
}
+
+func (self *worker) HashRate() int64 {
+ var tot int64
+ for _, agent := range self.agents {
+ tot += agent.Pow().GetHashrate()
+ }
+
+ return tot
+}
diff --git a/rpc/packages.go b/rpc/api.go
index b51bde7ce..28024c206 100644
--- a/rpc/packages.go
+++ b/rpc/api.go
@@ -20,18 +20,24 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil"
+ "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/ui"
"github.com/ethereum/go-ethereum/xeth"
)
-const (
- defaultGasPrice = "10000000000000"
- defaultGas = "10000"
+var (
+ defaultGasPrice = big.NewInt(10000000000000)
+ defaultGas = big.NewInt(10000)
+ filterTickerTime = 15 * time.Second
)
type EthereumApi struct {
- xeth *xeth.XEth
+ eth *xeth.XEth
+ xethMu sync.RWMutex
+ mux *event.TypeMux
+
quit chan struct{}
filterManager *filter.FilterManager
@@ -45,17 +51,21 @@ type EthereumApi struct {
register map[string][]*NewTxArgs
db ethutil.Database
+
+ defaultBlockAge int64
}
func NewEthereumApi(eth *xeth.XEth) *EthereumApi {
db, _ := ethdb.NewLDBDatabase("dapps")
api := &EthereumApi{
- xeth: eth,
- quit: make(chan struct{}),
- filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
- logs: make(map[int]*logFilter),
- messages: make(map[int]*whisperFilter),
- db: db,
+ eth: eth,
+ mux: eth.Backend().EventMux(),
+ quit: make(chan struct{}),
+ filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
+ logs: make(map[int]*logFilter),
+ messages: make(map[int]*whisperFilter),
+ db: db,
+ defaultBlockAge: -1,
}
go api.filterManager.Start()
go api.start()
@@ -63,6 +73,64 @@ func NewEthereumApi(eth *xeth.XEth) *EthereumApi {
return api
}
+func (self *EthereumApi) setStateByBlockNumber(num int64) {
+ chain := self.xeth().Backend().ChainManager()
+ var block *types.Block
+
+ if self.defaultBlockAge < 0 {
+ num = chain.CurrentBlock().Number().Int64() + num + 1
+ }
+ block = chain.GetBlockByNumber(uint64(num))
+
+ if block != nil {
+ self.useState(state.New(block.Root(), self.xeth().Backend().Db()))
+ } else {
+ self.useState(chain.State())
+ }
+}
+
+func (self *EthereumApi) start() {
+ timer := time.NewTicker(filterTickerTime)
+ events := self.mux.Subscribe(core.ChainEvent{})
+
+done:
+ for {
+ select {
+ case ev := <-events.Chan():
+ switch ev.(type) {
+ case core.ChainEvent:
+ if self.defaultBlockAge < 0 {
+ self.setStateByBlockNumber(self.defaultBlockAge)
+ }
+ }
+ case <-timer.C:
+ self.logMut.Lock()
+ self.messagesMut.Lock()
+ for id, filter := range self.logs {
+ if time.Since(filter.timeout) > 20*time.Second {
+ self.filterManager.UninstallFilter(id)
+ delete(self.logs, id)
+ }
+ }
+
+ for id, filter := range self.messages {
+ if time.Since(filter.timeout) > 20*time.Second {
+ self.xeth().Whisper().Unwatch(id)
+ delete(self.messages, id)
+ }
+ }
+ self.logMut.Unlock()
+ self.messagesMut.Unlock()
+ case <-self.quit:
+ break done
+ }
+ }
+}
+
+func (self *EthereumApi) stop() {
+ close(self.quit)
+}
+
func (self *EthereumApi) Register(args string, reply *interface{}) error {
self.regmut.Lock()
defer self.regmut.Unlock()
@@ -95,7 +163,7 @@ func (self *EthereumApi) WatchTx(args string, reply *interface{}) error {
func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error {
var id int
- filter := core.NewFilter(self.xeth.Backend())
+ filter := core.NewFilter(self.xeth().Backend())
filter.SetOptions(toFilterOptions(args))
filter.LogsCallback = func(logs state.Logs) {
self.logMut.Lock()
@@ -120,16 +188,12 @@ func (self *EthereumApi) UninstallFilter(id int, reply *interface{}) error {
func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error {
var id int
- filter := core.NewFilter(self.xeth.Backend())
+ filter := core.NewFilter(self.xeth().Backend())
callback := func(block *types.Block) {
self.logMut.Lock()
defer self.logMut.Unlock()
- if self.logs[id] == nil {
- self.logs[id] = &logFilter{timeout: time.Now()}
- }
-
self.logs[id].add(&state.StateLog{})
}
if args == "pending" {
@@ -139,6 +203,7 @@ func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error
}
id = self.filterManager.InstallFilter(filter)
+ self.logs[id] = &logFilter{timeout: time.Now()}
*reply = id
return nil
@@ -168,7 +233,7 @@ func (self *EthereumApi) Logs(id int, reply *interface{}) error {
}
func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error {
- filter := core.NewFilter(self.xeth.Backend())
+ filter := core.NewFilter(self.xeth().Backend())
filter.SetOptions(toFilterOptions(args))
*reply = toLogs(filter.Find())
@@ -177,41 +242,54 @@ func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error
}
func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *interface{}) error {
- err := args.requirements()
- if err != nil {
- return err
- }
-
- if args.BlockNumber > 0 {
- *reply = p.xeth.BlockByNumber(args.BlockNumber)
+ // This seems a bit precarious Maybe worth splitting to discrete functions
+ if len(args.Hash) > 0 {
+ *reply = p.xeth().BlockByHash(args.Hash)
} else {
- *reply = p.xeth.BlockByHash(args.Hash)
+ *reply = p.xeth().BlockByNumber(args.BlockNumber)
}
return nil
}
func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error {
if len(args.Gas) == 0 {
- args.Gas = defaultGas
+ args.Gas = defaultGas.String()
}
if len(args.GasPrice) == 0 {
- args.GasPrice = defaultGasPrice
+ args.GasPrice = defaultGasPrice.String()
}
// TODO if no_private_key then
- if _, exists := p.register[args.From]; exists {
- p.register[args.From] = append(p.register[args.From], args)
- } else {
- result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
- *reply = result
- }
+ //if _, exists := p.register[args.From]; exists {
+ // p.register[args.From] = append(p.register[args.From], args)
+ //} else {
+ /*
+ account := accounts.Get(fromHex(args.From))
+ if account != nil {
+ if account.Unlocked() {
+ if !unlockAccount(account) {
+ return
+ }
+ }
+
+ result, _ := account.Transact(fromHex(args.To), fromHex(args.Value), fromHex(args.Gas), fromHex(args.GasPrice), fromHex(args.Data))
+ if len(result) > 0 {
+ *reply = toHex(result)
+ }
+ } else if _, exists := p.register[args.From]; exists {
+ p.register[ags.From] = append(p.register[args.From], args)
+ }
+ */
+ result, _ := p.xeth().Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
+ *reply = result
+ //}
return nil
}
func (p *EthereumApi) Call(args *NewTxArgs, reply *interface{}) error {
- result, err := p.xeth.Call( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
+ result, err := p.xeth().Call( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
if err != nil {
return err
}
@@ -225,7 +303,7 @@ func (p *EthereumApi) PushTx(args *PushTxArgs, reply *interface{}) error {
if err != nil {
return err
}
- result, _ := p.xeth.PushTx(args.Tx)
+ result, _ := p.xeth().PushTx(args.Tx)
*reply = result
return nil
}
@@ -236,7 +314,7 @@ func (p *EthereumApi) GetStateAt(args *GetStateArgs, reply *interface{}) error {
return err
}
- state := p.xeth.State().SafeGet(args.Address)
+ state := p.xeth().State().SafeGet(args.Address)
value := state.StorageString(args.Key)
var hx string
@@ -258,42 +336,55 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) err
return err
}
- *reply = p.xeth.State().SafeGet(args.Address).Storage()
+ *reply = p.xeth().State().SafeGet(args.Address).Storage()
return nil
}
func (p *EthereumApi) GetPeerCount(reply *interface{}) error {
- *reply = p.xeth.PeerCount()
+ *reply = p.xeth().PeerCount()
return nil
}
func (p *EthereumApi) GetIsListening(reply *interface{}) error {
- *reply = p.xeth.IsListening()
+ *reply = p.xeth().IsListening()
return nil
}
func (p *EthereumApi) GetCoinbase(reply *interface{}) error {
- *reply = p.xeth.Coinbase()
+ *reply = p.xeth().Coinbase()
return nil
}
func (p *EthereumApi) Accounts(reply *interface{}) error {
- *reply = p.xeth.Accounts()
+ *reply = p.xeth().Accounts()
return nil
}
func (p *EthereumApi) GetIsMining(reply *interface{}) error {
- *reply = p.xeth.IsMining()
+ *reply = p.xeth().IsMining()
return nil
}
func (p *EthereumApi) SetMining(shouldmine bool, reply *interface{}) error {
- *reply = p.xeth.SetMining(shouldmine)
+ *reply = p.xeth().SetMining(shouldmine)
+ return nil
+}
+
+func (p *EthereumApi) GetDefaultBlockAge(reply *interface{}) error {
+ *reply = p.defaultBlockAge
+ return nil
+}
+
+func (p *EthereumApi) SetDefaultBlockAge(defaultBlockAge int64, reply *interface{}) error {
+ p.defaultBlockAge = defaultBlockAge
+ p.setStateByBlockNumber(p.defaultBlockAge)
+
+ *reply = true
return nil
}
func (p *EthereumApi) BlockNumber(reply *interface{}) error {
- *reply = p.xeth.Backend().ChainManager().CurrentBlock().Number()
+ *reply = p.xeth().Backend().ChainManager().CurrentBlock().Number()
return nil
}
@@ -302,7 +393,7 @@ func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *interface{}) err
if err != nil {
return err
}
- *reply = p.xeth.TxCountAt(args.Address)
+ *reply = p.xeth().TxCountAt(args.Address)
return nil
}
@@ -311,7 +402,7 @@ func (p *EthereumApi) GetBalanceAt(args *GetBalanceArgs, reply *interface{}) err
if err != nil {
return err
}
- state := p.xeth.State().SafeGet(args.Address)
+ state := p.xeth().State().SafeGet(args.Address)
*reply = toHex(state.Balance().Bytes())
return nil
}
@@ -321,7 +412,7 @@ func (p *EthereumApi) GetCodeAt(args *GetCodeAtArgs, reply *interface{}) error {
if err != nil {
return err
}
- *reply = p.xeth.CodeAt(args.Address)
+ *reply = p.xeth().CodeAt(args.Address)
return nil
}
@@ -368,7 +459,7 @@ func (p *EthereumApi) DbGet(args *DbArgs, reply *interface{}) error {
}
func (p *EthereumApi) NewWhisperIdentity(reply *interface{}) error {
- *reply = p.xeth.Whisper().NewIdentity()
+ *reply = p.xeth().Whisper().NewIdentity()
return nil
}
@@ -377,12 +468,10 @@ func (p *EthereumApi) NewWhisperFilter(args *xeth.Options, reply *interface{}) e
args.Fn = func(msg xeth.WhisperMessage) {
p.messagesMut.Lock()
defer p.messagesMut.Unlock()
- if p.messages[id] == nil {
- p.messages[id] = &whisperFilter{timeout: time.Now()}
- }
p.messages[id].add(msg) // = append(p.messages[id], msg)
}
- id = p.xeth.Whisper().Watch(args)
+ id = p.xeth().Whisper().Watch(args)
+ p.messages[id] = &whisperFilter{timeout: time.Now()}
*reply = id
return nil
}
@@ -399,7 +488,7 @@ func (self *EthereumApi) MessagesChanged(id int, reply *interface{}) error {
}
func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{}) error {
- err := p.xeth.Whisper().Post(args.Payload, args.To, args.From, args.Topic, args.Priority, args.Ttl)
+ err := p.xeth().Whisper().Post(args.Payload, args.To, args.From, args.Topic, args.Priority, args.Ttl)
if err != nil {
return err
}
@@ -409,17 +498,17 @@ func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{})
}
func (p *EthereumApi) HasWhisperIdentity(args string, reply *interface{}) error {
- *reply = p.xeth.Whisper().HasIdentity(args)
+ *reply = p.xeth().Whisper().HasIdentity(args)
return nil
}
func (p *EthereumApi) WhisperMessages(id int, reply *interface{}) error {
- *reply = p.xeth.Whisper().Messages(id)
+ *reply = p.xeth().Whisper().Messages(id)
return nil
}
func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error {
- // Spec at https://github.com/ethereum/wiki/wiki/Generic-ON-RPC
+ // Spec at https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC
rpclogger.DebugDetailf("%T %s", req.Params, req.Params)
switch req.Method {
case "eth_coinbase":
@@ -434,6 +523,14 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return err
}
return p.SetMining(args, reply)
+ case "eth_defaultBlock":
+ return p.GetDefaultBlockAge(reply)
+ case "eth_setDefaultBlock":
+ args, err := req.ToIntArgs()
+ if err != nil {
+ return err
+ }
+ return p.SetDefaultBlockAge(int64(args), reply)
case "eth_peerCount":
return p.GetPeerCount(reply)
case "eth_number":
@@ -525,7 +622,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
}
return p.AllLogs(args, reply)
case "eth_gasPrice":
- *reply = defaultGasPrice
+ *reply = toHex(defaultGasPrice.Bytes())
return nil
case "eth_register":
args, err := req.ToRegisterArgs()
@@ -604,42 +701,34 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
}
return p.WhisperMessages(args, reply)
default:
- return NewErrorResponse(fmt.Sprintf("%v %s", ErrorNotImplemented, req.Method))
+ return NewErrorWithMessage(errNotImplemented, req.Method)
}
rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
return nil
}
-var filterTickerTime = 15 * time.Second
+func (self *EthereumApi) xeth() *xeth.XEth {
+ self.xethMu.RLock()
+ defer self.xethMu.RUnlock()
-func (self *EthereumApi) start() {
- timer := time.NewTicker(filterTickerTime)
-done:
- for {
- select {
- case <-timer.C:
- self.logMut.Lock()
- self.messagesMut.Lock()
- for id, filter := range self.logs {
- if time.Since(filter.timeout) > 20*time.Second {
- delete(self.logs, id)
- }
- }
+ return self.eth
+}
- for id, filter := range self.messages {
- if time.Since(filter.timeout) > 20*time.Second {
- delete(self.messages, id)
- }
- }
- self.logMut.Unlock()
- self.messagesMut.Unlock()
- case <-self.quit:
- break done
- }
- }
+func (self *EthereumApi) useState(statedb *state.StateDB) {
+ self.xethMu.Lock()
+ defer self.xethMu.Unlock()
+
+ self.eth = self.eth.UseState(statedb)
}
-func (self *EthereumApi) stop() {
- close(self.quit)
+func t(f ui.Frontend) {
+ // Call the password dialog
+ ret, err := f.Call("PasswordDialog")
+ if err != nil {
+ fmt.Println(err)
+ }
+ // Get the first argument
+ t, _ := ret.Get(0)
+ fmt.Println("return:", t)
}
diff --git a/rpc/packages_test.go b/rpc/api_test.go
index 037fd78b3..a9fc16cd3 100644
--- a/rpc/packages_test.go
+++ b/rpc/api_test.go
@@ -7,6 +7,7 @@ import (
)
func TestFilterClose(t *testing.T) {
+ t.Skip()
api := &EthereumApi{
logs: make(map[int]*logFilter),
messages: make(map[int]*whisperFilter),
diff --git a/rpc/args.go b/rpc/args.go
index f730819fd..ea8489585 100644
--- a/rpc/args.go
+++ b/rpc/args.go
@@ -19,14 +19,7 @@ func (obj *GetBlockArgs) UnmarshalJSON(b []byte) (err error) {
obj.Hash = argstr
return
}
- return NewErrorResponse(ErrorDecodeArgs)
-}
-
-func (obj *GetBlockArgs) requirements() error {
- if obj.BlockNumber == 0 && obj.Hash == "" {
- return NewErrorResponse("GetBlock requires either a block 'number' or a block 'hash' as argument")
- }
- return nil
+ return errDecodeArgs
}
type NewTxArgs struct {
@@ -64,7 +57,7 @@ func (obj *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
return
}
- return NewErrorResponse(ErrorDecodeArgs)
+ return errDecodeArgs
}
type PushTxArgs struct {
@@ -77,12 +70,12 @@ func (obj *PushTxArgs) UnmarshalJSON(b []byte) (err error) {
obj.Tx = arg0
return
}
- return NewErrorResponse(ErrorDecodeArgs)
+ return errDecodeArgs
}
func (a *PushTxArgs) requirementsPushTx() error {
if a.Tx == "" {
- return NewErrorResponse("PushTx requires a 'tx' as argument")
+ return NewErrorWithMessage(errArguments, "PushTx requires a 'tx' as argument")
}
return nil
}
@@ -93,14 +86,14 @@ type GetStorageArgs struct {
func (obj *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
if err = json.Unmarshal(b, &obj.Address); err != nil {
- return NewErrorResponse(ErrorDecodeArgs)
+ return errDecodeArgs
}
return
}
func (a *GetStorageArgs) requirements() error {
if len(a.Address) == 0 {
- return NewErrorResponse("GetStorageAt requires an 'address' value as argument")
+ return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'address' value as argument")
}
return nil
}
@@ -116,64 +109,39 @@ func (obj *GetStateArgs) UnmarshalJSON(b []byte) (err error) {
obj.Address = arg0
return
}
- return NewErrorResponse(ErrorDecodeArgs)
+ return errDecodeArgs
}
func (a *GetStateArgs) requirements() error {
if a.Address == "" {
- return NewErrorResponse("GetStorageAt requires an 'address' value as argument")
+ return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'address' value as argument")
}
if a.Key == "" {
- return NewErrorResponse("GetStorageAt requires an 'key' value as argument")
+ return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'key' value as argument")
}
return nil
}
-type GetStorageAtRes struct {
- Key string `json:"key"`
- Value string `json:"value"`
-}
-
type GetTxCountArgs struct {
Address string `json:"address"`
}
-// type GetTxCountRes struct {
-// Nonce int `json:"nonce"`
-// }
-
func (obj *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
arg0 := ""
if err = json.Unmarshal(b, &arg0); err == nil {
obj.Address = arg0
return
}
- return NewErrorResponse("Could not determine JSON parameters")
+ return errDecodeArgs
}
func (a *GetTxCountArgs) requirements() error {
if a.Address == "" {
- return NewErrorResponse("GetTxCountAt requires an 'address' value as argument")
+ return NewErrorWithMessage(errArguments, "GetTxCountAt requires an 'address' value as argument")
}
return nil
}
-// type GetPeerCountRes struct {
-// PeerCount int `json:"peerCount"`
-// }
-
-// type GetListeningRes struct {
-// IsListening bool `json:"isListening"`
-// }
-
-// type GetCoinbaseRes struct {
-// Coinbase string `json:"coinbase"`
-// }
-
-// type GetMiningRes struct {
-// IsMining bool `json:"isMining"`
-// }
-
type GetBalanceArgs struct {
Address string
}
@@ -184,21 +152,16 @@ func (obj *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
obj.Address = arg0
return
}
- return NewErrorResponse("Could not determine JSON parameters")
+ return errDecodeArgs
}
func (a *GetBalanceArgs) requirements() error {
if a.Address == "" {
- return NewErrorResponse("GetBalanceAt requires an 'address' value as argument")
+ return NewErrorWithMessage(errArguments, "GetBalanceAt requires an 'address' value as argument")
}
return nil
}
-type BalanceRes struct {
- Balance string `json:"balance"`
- Address string `json:"address"`
-}
-
type GetCodeAtArgs struct {
Address string
}
@@ -209,12 +172,12 @@ func (obj *GetCodeAtArgs) UnmarshalJSON(b []byte) (err error) {
obj.Address = arg0
return
}
- return NewErrorResponse(ErrorDecodeArgs)
+ return errDecodeArgs
}
func (a *GetCodeAtArgs) requirements() error {
if a.Address == "" {
- return NewErrorResponse("GetCodeAt requires an 'address' value as argument")
+ return NewErrorWithMessage(errArguments, "GetCodeAt requires an 'address' value as argument")
}
return nil
}
@@ -225,7 +188,7 @@ type Sha3Args struct {
func (obj *Sha3Args) UnmarshalJSON(b []byte) (err error) {
if err = json.Unmarshal(b, &obj.Data); err != nil {
- return NewErrorResponse(ErrorDecodeArgs)
+ return errDecodeArgs
}
return
}
@@ -234,7 +197,7 @@ type FilterOptions struct {
Earliest int64
Latest int64
Address interface{}
- Topic []string
+ Topic []interface{}
Skip int
Max int
}
@@ -257,10 +220,20 @@ func toFilterOptions(options *FilterOptions) core.FilterOptions {
opts.Earliest = options.Earliest
opts.Latest = options.Latest
- opts.Topics = make([][]byte, len(options.Topic))
- for i, topic := range options.Topic {
- opts.Topics[i] = fromHex(topic)
+
+ topics := make([][][]byte, len(options.Topic))
+ for i, topicDat := range options.Topic {
+ if slice, ok := topicDat.([]interface{}); ok {
+ topics[i] = make([][]byte, len(slice))
+ for j, topic := range slice {
+ topics[i][j] = fromHex(topic.(string))
+ }
+ } else if str, ok := topicDat.(string); ok {
+ topics[i] = make([][]byte, 1)
+ topics[i][0] = fromHex(str)
+ }
}
+ opts.Topics = topics
return opts
}
@@ -277,10 +250,10 @@ type DbArgs struct {
func (a *DbArgs) requirements() error {
if len(a.Database) == 0 {
- return NewErrorResponse("DbPutArgs requires an 'Database' value as argument")
+ return NewErrorWithMessage(errArguments, "DbPutArgs requires an 'Database' value as argument")
}
if len(a.Key) == 0 {
- return NewErrorResponse("DbPutArgs requires an 'Key' value as argument")
+ return NewErrorWithMessage(errArguments, "DbPutArgs requires an 'Key' value as argument")
}
return nil
}
diff --git a/rpc/http/server.go b/rpc/http/server.go
index dd6ba68e3..452b7c9af 100644
--- a/rpc/http/server.go
+++ b/rpc/http/server.go
@@ -29,8 +29,8 @@ import (
var rpchttplogger = logger.NewLogger("RPC-HTTP")
var JSON rpc.JsonWrapper
-func NewRpcHttpServer(pipe *xeth.XEth, port int) (*RpcHttpServer, error) {
- sport := fmt.Sprintf("127.0.0.1:%d", port)
+func NewRpcHttpServer(pipe *xeth.XEth, address string, port int) (*RpcHttpServer, error) {
+ sport := fmt.Sprintf("%s:%d", address, port)
l, err := net.Listen("tcp", sport)
if err != nil {
return nil, err
@@ -41,6 +41,7 @@ func NewRpcHttpServer(pipe *xeth.XEth, port int) (*RpcHttpServer, error) {
quit: make(chan bool),
pipe: pipe,
port: port,
+ addr: address,
}, nil
}
@@ -49,6 +50,7 @@ type RpcHttpServer struct {
listener net.Listener
pipe *xeth.XEth
port int
+ addr string
}
func (s *RpcHttpServer) exitHandler() {
@@ -69,7 +71,7 @@ func (s *RpcHttpServer) Stop() {
}
func (s *RpcHttpServer) Start() {
- rpchttplogger.Infof("Starting RPC-HTTP server on port %d", s.port)
+ rpchttplogger.Infof("Starting RPC-HTTP server on %s:%d", s.addr, s.port)
go s.exitHandler()
api := rpc.NewEthereumApi(s.pipe)
@@ -92,7 +94,7 @@ func (s *RpcHttpServer) apiHandler(api *rpc.EthereumApi) http.Handler {
reqParsed, reqerr := JSON.ParseRequestBody(req)
if reqerr != nil {
- jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest}
+ jsonerr := &rpc.RpcErrorObject{-32700, "Error: Could not parse request"}
JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
return
}
diff --git a/rpc/message.go b/rpc/messages.go
index 825ede05b..b37d8229d 100644
--- a/rpc/message.go
+++ b/rpc/messages.go
@@ -25,12 +25,11 @@ import (
"github.com/ethereum/go-ethereum/xeth"
)
-const (
- ErrorArguments = "Error: Insufficient arguments"
- ErrorNotImplemented = "Error: Method not implemented"
- ErrorUnknown = "Error: Unknown error"
- ErrorParseRequest = "Error: Could not parse request"
- ErrorDecodeArgs = "Error: Could not decode arguments"
+var (
+ errArguments = errors.New("Error: Insufficient arguments")
+ errNotImplemented = errors.New("Error: Method not implemented")
+ errUnknown = errors.New("Error: Unknown error")
+ errDecodeArgs = errors.New("Error: Could not decode arguments")
)
type RpcRequest struct {
@@ -58,76 +57,72 @@ type RpcErrorObject struct {
// Data interface{} `json:"data"`
}
-func NewErrorResponse(msg string) error {
- return errors.New(msg)
-}
-
-func NewErrorResponseWithError(msg string, err error) error {
- return fmt.Errorf("%s: %v", msg, err)
+func NewErrorWithMessage(err error, msg string) error {
+ return fmt.Errorf("%s: %s", err.Error(), msg)
}
func (req *RpcRequest) ToSha3Args() (*Sha3Args, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(Sha3Args)
r := bytes.NewReader(req.Params[0])
if err := json.NewDecoder(r).Decode(args); err != nil {
- return nil, NewErrorResponse(ErrorDecodeArgs)
+ return nil, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToGetBlockArgs() (*GetBlockArgs, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(GetBlockArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
- return nil, NewErrorResponse(ErrorDecodeArgs)
+ return nil, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToNewTxArgs() (*NewTxArgs, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(NewTxArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
- return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
+ return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToPushTxArgs() (*PushTxArgs, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(PushTxArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
- return nil, NewErrorResponse(ErrorDecodeArgs)
+ return nil, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToGetStateArgs() (*GetStateArgs, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(GetStateArgs)
@@ -135,234 +130,241 @@ func (req *RpcRequest) ToGetStateArgs() (*GetStateArgs, error) {
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
- return nil, NewErrorResponse(ErrorDecodeArgs)
+ return nil, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToStorageAtArgs() (*GetStorageArgs, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(GetStorageArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
- return nil, NewErrorResponse(ErrorDecodeArgs)
+ return nil, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToGetTxCountArgs() (*GetTxCountArgs, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(GetTxCountArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
- return nil, NewErrorResponse(ErrorDecodeArgs)
+ return nil, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToGetBalanceArgs() (*GetBalanceArgs, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(GetBalanceArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
- return nil, NewErrorResponse(ErrorDecodeArgs)
+ return nil, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToGetCodeAtArgs() (*GetCodeAtArgs, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(GetCodeAtArgs)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
- return nil, NewErrorResponse(ErrorDecodeArgs)
+ return nil, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToBoolArgs() (bool, error) {
if len(req.Params) < 1 {
- return false, NewErrorResponse(ErrorArguments)
+ return false, errArguments
}
var args bool
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
- return false, NewErrorResponse(ErrorDecodeArgs)
+ return false, errDecodeArgs
+ }
+
+ return args, nil
+}
+
+func (req *RpcRequest) ToIntArgs() (int, error) {
+ if len(req.Params) < 1 {
+ return 0, errArguments
+ }
+
+ var args int
+ if err := json.Unmarshal(req.Params[0], &args); err != nil {
+ return 0, errArguments
}
- rpclogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToCompileArgs() (string, error) {
if len(req.Params) < 1 {
- return "", NewErrorResponse(ErrorArguments)
+ return "", errArguments
}
var args string
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
- return "", NewErrorResponse(ErrorDecodeArgs)
+ return "", errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToFilterArgs() (*FilterOptions, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
args := new(FilterOptions)
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args)
if err != nil {
- return nil, NewErrorResponse(ErrorDecodeArgs)
+ return nil, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToFilterStringArgs() (string, error) {
if len(req.Params) < 1 {
- return "", NewErrorResponse(ErrorArguments)
+ return "", errArguments
}
var args string
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
- return "", NewErrorResponse(ErrorDecodeArgs)
+ return "", errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToUninstallFilterArgs() (int, error) {
if len(req.Params) < 1 {
- return 0, NewErrorResponse(ErrorArguments)
+ return 0, errArguments
}
var args int
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
- return 0, NewErrorResponse(ErrorDecodeArgs)
+ return 0, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", args, args)
return args, nil
}
func (req *RpcRequest) ToFilterChangedArgs() (int, error) {
if len(req.Params) < 1 {
- return 0, NewErrorResponse(ErrorArguments)
+ return 0, errArguments
}
var id int
r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(&id)
if err != nil {
- return 0, NewErrorResponse(ErrorDecodeArgs)
+ return 0, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", id, id)
return id, nil
}
func (req *RpcRequest) ToDbPutArgs() (*DbArgs, error) {
if len(req.Params) < 3 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
var args DbArgs
err := json.Unmarshal(req.Params[0], &args.Database)
if err != nil {
- return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
+ return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
err = json.Unmarshal(req.Params[1], &args.Key)
if err != nil {
- return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
+ return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
err = json.Unmarshal(req.Params[2], &args.Value)
if err != nil {
- return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
+ return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return &args, nil
}
func (req *RpcRequest) ToDbGetArgs() (*DbArgs, error) {
if len(req.Params) < 2 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
var args DbArgs
err := json.Unmarshal(req.Params[0], &args.Database)
if err != nil {
- return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
+ return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
err = json.Unmarshal(req.Params[1], &args.Key)
if err != nil {
- return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
+ return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return &args, nil
}
func (req *RpcRequest) ToWhisperFilterArgs() (*xeth.Options, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
var args xeth.Options
err := json.Unmarshal(req.Params[0], &args)
if err != nil {
- return nil, NewErrorResponseWithError(ErrorDecodeArgs, err)
+ return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return &args, nil
}
func (req *RpcRequest) ToIdArgs() (int, error) {
if len(req.Params) < 1 {
- return 0, NewErrorResponse(ErrorArguments)
+ return 0, errArguments
}
var id int
err := json.Unmarshal(req.Params[0], &id)
if err != nil {
- return 0, NewErrorResponse(ErrorDecodeArgs)
+ return 0, errDecodeArgs
}
- rpclogger.DebugDetailf("%T %v", id, id)
+
return id, nil
}
func (req *RpcRequest) ToWhisperPostArgs() (*WhisperMessageArgs, error) {
if len(req.Params) < 1 {
- return nil, NewErrorResponse(ErrorArguments)
+ return nil, errArguments
}
var args WhisperMessageArgs
@@ -370,13 +372,13 @@ func (req *RpcRequest) ToWhisperPostArgs() (*WhisperMessageArgs, error) {
if err != nil {
return nil, err
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return &args, nil
}
func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) {
if len(req.Params) < 1 {
- return "", NewErrorResponse(ErrorArguments)
+ return "", errArguments
}
var args string
@@ -384,13 +386,13 @@ func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) {
if err != nil {
return "", err
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToRegisterArgs() (string, error) {
if len(req.Params) < 1 {
- return "", NewErrorResponse(ErrorArguments)
+ return "", errArguments
}
var args string
@@ -398,13 +400,13 @@ func (req *RpcRequest) ToRegisterArgs() (string, error) {
if err != nil {
return "", err
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
func (req *RpcRequest) ToWatchTxArgs() (string, error) {
if len(req.Params) < 1 {
- return "", NewErrorResponse(ErrorArguments)
+ return "", errArguments
}
var args string
@@ -412,6 +414,6 @@ func (req *RpcRequest) ToWatchTxArgs() (string, error) {
if err != nil {
return "", err
}
- rpclogger.DebugDetailf("%T %v", args, args)
+
return args, nil
}
diff --git a/rpc/util.go b/rpc/util.go
index 1939b3474..3e8ca3fef 100644
--- a/rpc/util.go
+++ b/rpc/util.go
@@ -82,7 +82,7 @@ type RpcServer interface {
type Log struct {
Address string `json:"address"`
- Topic []string `json:"topics"`
+ Topic []string `json:"topic"`
Data string `json:"data"`
Number uint64 `json:"number"`
}
@@ -108,6 +108,7 @@ func toLogs(logs state.Logs) (ls []Log) {
type whisperFilter struct {
messages []xeth.WhisperMessage
timeout time.Time
+ id int
}
func (w *whisperFilter) add(msgs ...xeth.WhisperMessage) {
@@ -123,6 +124,7 @@ func (w *whisperFilter) get() []xeth.WhisperMessage {
type logFilter struct {
logs state.Logs
timeout time.Time
+ id int
}
func (l *logFilter) add(logs ...state.Log) {
diff --git a/rpc/ws/server.go b/rpc/ws/server.go
deleted file mode 100644
index b8cc2fa6b..000000000
--- a/rpc/ws/server.go
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- This file is part of go-ethereum
-
- go-ethereum is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- go-ethereum is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
-*/
-package rpcws
-
-import (
- "fmt"
- "net"
- "net/http"
-
- "github.com/ethereum/go-ethereum/logger"
- "github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/xeth"
- "golang.org/x/net/websocket"
-)
-
-var wslogger = logger.NewLogger("RPC-WS")
-var JSON rpc.JsonWrapper
-
-type WebSocketServer struct {
- pipe *xeth.XEth
- port int
- doneCh chan bool
- listener net.Listener
-}
-
-func NewWebSocketServer(pipe *xeth.XEth, port int) (*WebSocketServer, error) {
- sport := fmt.Sprintf(":%d", port)
- l, err := net.Listen("tcp", sport)
- if err != nil {
- return nil, err
- }
-
- return &WebSocketServer{
- pipe,
- port,
- make(chan bool),
- l,
- }, nil
-}
-
-func (self *WebSocketServer) handlerLoop() {
- for {
- select {
- case <-self.doneCh:
- wslogger.Infoln("Shutdown RPC-WS server")
- return
- }
- }
-}
-
-func (self *WebSocketServer) Stop() {
- close(self.doneCh)
-}
-
-func (self *WebSocketServer) Start() {
- wslogger.Infof("Starting RPC-WS server on port %d", self.port)
- go self.handlerLoop()
-
- api := rpc.NewEthereumApi(self.pipe)
- h := self.apiHandler(api)
- http.Handle("/ws", h)
-
- err := http.Serve(self.listener, nil)
- if err != nil {
- wslogger.Errorln("Error on RPC-WS interface:", err)
- }
-}
-
-func (s *WebSocketServer) apiHandler(api *rpc.EthereumApi) http.Handler {
- fn := func(w http.ResponseWriter, req *http.Request) {
- h := sockHandler(api)
- s := websocket.Server{Handler: h}
- s.ServeHTTP(w, req)
- }
-
- return http.HandlerFunc(fn)
-}
-
-func sockHandler(api *rpc.EthereumApi) websocket.Handler {
- var jsonrpcver string = "2.0"
- fn := func(conn *websocket.Conn) {
- for {
- wslogger.Debugln("Handling connection")
- var reqParsed rpc.RpcRequest
-
- // reqParsed, reqerr := JSON.ParseRequestBody(conn.Request())
- if err := websocket.JSON.Receive(conn, &reqParsed); err != nil {
- jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest}
- JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
- continue
- }
-
- var response interface{}
- reserr := api.GetRequestReply(&reqParsed, &response)
- if reserr != nil {
- wslogger.Warnln(reserr)
- jsonerr := &rpc.RpcErrorObject{-32603, reserr.Error()}
- JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Error: jsonerr})
- continue
- }
-
- wslogger.Debugf("Generated response: %T %s", response, response)
- JSON.Send(conn, &rpc.RpcSuccessResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Result: response})
- }
- }
- return websocket.Handler(fn)
-}
diff --git a/state/dump.go b/state/dump.go
index 81895f1a3..2c611d76b 100644
--- a/state/dump.go
+++ b/state/dump.go
@@ -20,7 +20,7 @@ type World struct {
Accounts map[string]Account `json:"accounts"`
}
-func (self *StateDB) Dump() []byte {
+func (self *StateDB) RawDump() World {
world := World{
Root: ethutil.Bytes2Hex(self.trie.Root()),
Accounts: make(map[string]Account),
@@ -35,12 +35,15 @@ func (self *StateDB) Dump() []byte {
storageIt := stateObject.State.trie.Iterator()
for storageIt.Next() {
- account.Storage[ethutil.Bytes2Hex(it.Key)] = ethutil.Bytes2Hex(it.Value)
+ account.Storage[ethutil.Bytes2Hex(storageIt.Key)] = ethutil.Bytes2Hex(storageIt.Value)
}
world.Accounts[ethutil.Bytes2Hex(it.Key)] = account
}
+ return world
+}
- json, err := json.MarshalIndent(world, "", " ")
+func (self *StateDB) Dump() []byte {
+ json, err := json.MarshalIndent(self.RawDump(), "", " ")
if err != nil {
fmt.Println("dump err", err)
}
diff --git a/state/state_object.go b/state/state_object.go
index 477b912a1..487952a02 100644
--- a/state/state_object.go
+++ b/state/state_object.go
@@ -19,6 +19,14 @@ func (self Code) String() string {
type Storage map[string]*ethutil.Value
+func (self Storage) String() (str string) {
+ for key, value := range self {
+ str += fmt.Sprintf("%X : %X\n", key, value.Bytes())
+ }
+
+ return
+}
+
func (self Storage) Copy() Storage {
cpy := make(Storage)
for key, value := range self {
@@ -119,10 +127,9 @@ func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value {
}
func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) {
self.SetState(key.Bytes(), value)
- self.dirty = true
}
-func (self *StateObject) Storage() map[string]*ethutil.Value {
+func (self *StateObject) Storage() Storage {
return self.storage
}
@@ -172,20 +179,22 @@ func (c *StateObject) AddBalance(amount *big.Int) {
statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount)
}
-func (c *StateObject) AddAmount(amount *big.Int) { c.AddBalance(amount) }
func (c *StateObject) SubBalance(amount *big.Int) {
c.SetBalance(new(big.Int).Sub(c.balance, amount))
statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount)
}
-func (c *StateObject) SubAmount(amount *big.Int) { c.SubBalance(amount) }
func (c *StateObject) SetBalance(amount *big.Int) {
c.balance = amount
c.dirty = true
}
+func (c *StateObject) St() Storage {
+ return c.storage
+}
+
//
// Gas setters and getters
//
@@ -198,7 +207,7 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error {
return fmt.Errorf("insufficient amount: %v, %v", c.balance, total)
}
- c.SubAmount(total)
+ c.SubBalance(total)
c.dirty = true
@@ -221,7 +230,7 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error {
rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price)
- self.AddAmount(rGas)
+ self.AddBalance(rGas)
self.dirty = true
diff --git a/state/statedb.go b/state/statedb.go
index 7e2b24b94..ff8242e1a 100644
--- a/state/statedb.go
+++ b/state/statedb.go
@@ -54,7 +54,7 @@ func (self *StateDB) Refund(addr []byte, gas *big.Int) {
// Retrieve the balance from the given address or 0 if object not found
func (self *StateDB) GetBalance(addr []byte) *big.Int {
- stateObject := self.GetStateObject(addr)
+ stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
return stateObject.balance
}
@@ -63,14 +63,14 @@ func (self *StateDB) GetBalance(addr []byte) *big.Int {
}
func (self *StateDB) AddBalance(addr []byte, amount *big.Int) {
- stateObject := self.GetStateObject(addr)
+ stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.AddBalance(amount)
}
}
func (self *StateDB) GetNonce(addr []byte) uint64 {
- stateObject := self.GetStateObject(addr)
+ stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
return stateObject.nonce
}
@@ -79,7 +79,7 @@ func (self *StateDB) GetNonce(addr []byte) uint64 {
}
func (self *StateDB) GetCode(addr []byte) []byte {
- stateObject := self.GetStateObject(addr)
+ stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
return stateObject.code
}
@@ -88,7 +88,7 @@ func (self *StateDB) GetCode(addr []byte) []byte {
}
func (self *StateDB) GetState(a, b []byte) []byte {
- stateObject := self.GetStateObject(a)
+ stateObject := self.GetOrNewStateObject(a)
if stateObject != nil {
return stateObject.GetState(b).Bytes()
}
@@ -97,28 +97,28 @@ func (self *StateDB) GetState(a, b []byte) []byte {
}
func (self *StateDB) SetNonce(addr []byte, nonce uint64) {
- stateObject := self.GetStateObject(addr)
+ stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetNonce(nonce)
}
}
func (self *StateDB) SetCode(addr, code []byte) {
- stateObject := self.GetStateObject(addr)
+ stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetCode(code)
}
}
func (self *StateDB) SetState(addr, key []byte, value interface{}) {
- stateObject := self.GetStateObject(addr)
+ stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.SetState(key, ethutil.NewValue(value))
}
}
func (self *StateDB) Delete(addr []byte) bool {
- stateObject := self.GetStateObject(addr)
+ stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.MarkForDeletion()
diff --git a/ui/filter.go b/ui/filter.go
index 0d1746915..5b1faa293 100644
--- a/ui/filter.go
+++ b/ui/filter.go
@@ -1,77 +1 @@
package ui
-
-import (
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/ethutil"
-)
-
-func fromHex(s string) []byte {
- if len(s) > 1 {
- if s[0:2] == "0x" {
- s = s[2:]
- }
- return ethutil.Hex2Bytes(s)
- }
- return nil
-}
-
-func NewFilterFromMap(object map[string]interface{}, eth core.Backend) *core.Filter {
- filter := core.NewFilter(eth)
-
- if object["earliest"] != nil {
- val := ethutil.NewValue(object["earliest"])
- filter.SetEarliestBlock(val.Int())
- }
-
- if object["latest"] != nil {
- val := ethutil.NewValue(object["latest"])
- filter.SetLatestBlock(val.Int())
- }
-
- if object["address"] != nil {
- //val := ethutil.NewValue(object["address"])
- //filter.SetAddress(fromHex(val.Str()))
- }
-
- if object["max"] != nil {
- val := ethutil.NewValue(object["max"])
- filter.SetMax(int(val.Uint()))
- }
-
- if object["skip"] != nil {
- val := ethutil.NewValue(object["skip"])
- filter.SetSkip(int(val.Uint()))
- }
-
- if object["topics"] != nil {
- filter.SetTopics(MakeTopics(object["topics"]))
- }
-
- return filter
-}
-
-// Conversion methodn
-func mapToAccountChange(m map[string]interface{}) (d core.AccountChange) {
- if str, ok := m["id"].(string); ok {
- d.Address = fromHex(str)
- }
-
- if str, ok := m["at"].(string); ok {
- d.StateAddress = fromHex(str)
- }
-
- return
-}
-
-// data can come in in the following formats:
-// ["aabbccdd", {id: "ccddee", at: "11223344"}], "aabbcc", {id: "ccddee", at: "1122"}
-func MakeTopics(v interface{}) (d [][]byte) {
- if str, ok := v.(string); ok {
- d = append(d, fromHex(str))
- } else if slice, ok := v.([]string); ok {
- for _, item := range slice {
- d = append(d, fromHex(item))
- }
- }
- return
-}
diff --git a/ui/frontend.go b/ui/frontend.go
new file mode 100644
index 000000000..22dc64fdf
--- /dev/null
+++ b/ui/frontend.go
@@ -0,0 +1,18 @@
+package ui
+
+// ReturnInterface is returned by the Intercom interface when a method is called
+type ReturnInterface interface {
+ Get(i int) (interface{}, error)
+ Size() int
+}
+
+// Frontend is the basic interface for calling arbitrary methods on something that
+// implements a front end (GUI, CLI, etc)
+type Frontend interface {
+ // Checks whether a specific method is implemented
+ Supports(method string) bool
+ // Call calls the given method on interface it implements. This will return
+ // an error with errNotImplemented if the method hasn't been implemented
+ // and will return a ReturnInterface if it does.
+ Call(method string) (ReturnInterface, error)
+}
diff --git a/ui/qt/filter.go b/ui/qt/filter.go
index 48e8a7fae..090260e4e 100644
--- a/ui/qt/filter.go
+++ b/ui/qt/filter.go
@@ -1,30 +1 @@
package qt
-
-import (
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/ui"
- "github.com/obscuren/qml"
-)
-
-func NewFilterFromMap(object map[string]interface{}, eth core.Backend) *core.Filter {
- filter := ui.NewFilterFromMap(object, eth)
-
- if object["topics"] != nil {
- filter.SetTopics(makeTopics(object["topics"]))
- }
-
- return filter
-}
-
-func makeTopics(v interface{}) (d [][]byte) {
- if qList, ok := v.(*qml.List); ok {
- var s []string
- qList.Convert(&s)
-
- d = ui.MakeTopics(s)
- } else if str, ok := v.(string); ok {
- d = ui.MakeTopics(str)
- }
-
- return
-}
diff --git a/vm/vm.go b/vm/vm.go
index f9efeed96..1f386d47c 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -16,6 +16,8 @@ type Vm struct {
logStr string
err error
+ // For logging
+ debug bool
Dbg Debugger
@@ -32,7 +34,7 @@ func New(env Environment) *Vm {
lt = LogTyDiff
}
- return &Vm{env: env, logTy: lt, Recoverable: true}
+ return &Vm{debug: false, env: env, logTy: lt, Recoverable: true}
}
func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
@@ -664,6 +666,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
}
addr = ref.Address()
+ fmt.Printf("CREATE %X\n", addr)
stack.Push(ethutil.BigD(addr))
}
@@ -727,7 +730,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self.Printf(" => (%x) %v", receiver.Address()[:4], balance)
- receiver.AddAmount(balance)
+ receiver.AddBalance(balance)
statedb.Delete(context.Address())
fallthrough
@@ -828,7 +831,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
// 0 => non 0
mult = ethutil.Big3
} else if len(val) > 0 && len(y.Bytes()) == 0 {
- statedb.Refund(caller.Address(), GasSStoreRefund)
+ statedb.Refund(self.env.Origin(), GasSStoreRefund)
mult = ethutil.Big0
} else {
@@ -937,17 +940,21 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, callData []byte, context *
}
func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine {
- if self.logTy == LogTyPretty {
- self.logStr += fmt.Sprintf(format, v...)
+ if self.debug {
+ if self.logTy == LogTyPretty {
+ self.logStr += fmt.Sprintf(format, v...)
+ }
}
return self
}
func (self *Vm) Endl() VirtualMachine {
- if self.logTy == LogTyPretty {
- vmlogger.Debugln(self.logStr)
- self.logStr = ""
+ if self.debug {
+ if self.logTy == LogTyPretty {
+ vmlogger.Debugln(self.logStr)
+ self.logStr = ""
+ }
}
return self
diff --git a/vm/vm_jit.go b/vm/vm_jit.go
index 38cab57da..9d26957f0 100644
--- a/vm/vm_jit.go
+++ b/vm/vm_jit.go
@@ -50,6 +50,7 @@ type RuntimeData struct {
timestamp int64
code *byte
codeSize uint64
+ codeHash i256
}
func hash2llvm(h []byte) i256 {
@@ -180,6 +181,7 @@ func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *bi
self.data.timestamp = self.env.Time()
self.data.code = getDataPtr(code)
self.data.codeSize = uint64(len(code))
+ self.data.codeHash = hash2llvm(crypto.Sha3(code)) // TODO: Get already computed hash?
jit := C.evmjit_create()
retCode := C.evmjit_run(jit, unsafe.Pointer(&self.data), unsafe.Pointer(self))
@@ -197,12 +199,12 @@ func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *bi
receiverAddr := llvm2hashRef(bswap(&self.data.address))
receiver := state.GetOrNewStateObject(receiverAddr)
balance := state.GetBalance(me.Address())
- receiver.AddAmount(balance)
+ receiver.AddBalance(balance)
state.Delete(me.Address())
}
}
-
- C.evmjit_destroy(jit);
+
+ C.evmjit_destroy(jit)
return
}
@@ -278,7 +280,7 @@ func env_blockhash(_vm unsafe.Pointer, _number unsafe.Pointer, _result unsafe.Po
}
//export env_call
-func env_call(_vm unsafe.Pointer, _gas unsafe.Pointer, _receiveAddr unsafe.Pointer, _value unsafe.Pointer, inDataPtr unsafe.Pointer, inDataLen uint64, outDataPtr *byte, outDataLen uint64, _codeAddr unsafe.Pointer) bool {
+func env_call(_vm unsafe.Pointer, _gas *int64, _receiveAddr unsafe.Pointer, _value unsafe.Pointer, inDataPtr unsafe.Pointer, inDataLen uint64, outDataPtr *byte, outDataLen uint64, _codeAddr unsafe.Pointer) bool {
vm := (*JitVm)(_vm)
//fmt.Printf("env_call (depth %d)\n", vm.Env().Depth())
@@ -297,8 +299,7 @@ func env_call(_vm unsafe.Pointer, _gas unsafe.Pointer, _receiveAddr unsafe.Point
inData := C.GoBytes(inDataPtr, C.int(inDataLen))
outData := llvm2bytesRef(outDataPtr, outDataLen)
codeAddr := llvm2hash((*i256)(_codeAddr))
- llvmGas := (*i256)(_gas)
- gas := llvm2big(llvmGas)
+ gas := big.NewInt(*_gas)
var out []byte
var err error
if bytes.Equal(codeAddr, receiveAddr) {
@@ -306,7 +307,7 @@ func env_call(_vm unsafe.Pointer, _gas unsafe.Pointer, _receiveAddr unsafe.Point
} else {
out, err = vm.env.CallCode(vm.me, codeAddr, inData, gas, vm.price, value)
}
- *llvmGas = big2llvm(gas)
+ *_gas = gas.Int64()
if err == nil {
copy(outData, out)
return true
@@ -317,7 +318,7 @@ func env_call(_vm unsafe.Pointer, _gas unsafe.Pointer, _receiveAddr unsafe.Point
}
//export env_create
-func env_create(_vm unsafe.Pointer, _gas unsafe.Pointer, _value unsafe.Pointer, initDataPtr unsafe.Pointer, initDataLen uint64, _result unsafe.Pointer) {
+func env_create(_vm unsafe.Pointer, _gas *int64, _value unsafe.Pointer, initDataPtr unsafe.Pointer, initDataLen uint64, _result unsafe.Pointer) {
vm := (*JitVm)(_vm)
value := llvm2big((*i256)(_value))
@@ -325,9 +326,7 @@ func env_create(_vm unsafe.Pointer, _gas unsafe.Pointer, _value unsafe.Pointer,
result := (*i256)(_result)
*result = i256{}
- llvmGas := (*i256)(_gas)
- gas := llvm2big(llvmGas)
-
+ gas := big.NewInt(*_gas)
ret, suberr, ref := vm.env.Create(vm.me, nil, initData, gas, vm.price, value)
if suberr == nil {
dataGas := big.NewInt(int64(len(ret))) // TODO: Nto the best design. env.Create can do it, it has the reference to gas counter
@@ -335,7 +334,7 @@ func env_create(_vm unsafe.Pointer, _gas unsafe.Pointer, _value unsafe.Pointer,
gas.Sub(gas, dataGas)
*result = hash2llvm(ref.Address())
}
- *llvmGas = big2llvm(gas)
+ *_gas = gas.Int64()
}
//export env_log
@@ -358,7 +357,7 @@ func env_log(_vm unsafe.Pointer, dataPtr unsafe.Pointer, dataLen uint64, _topic1
topics = append(topics, llvm2hash((*i256)(_topic4)))
}
- vm.Env().AddLog(state.NewLog(vm.me.Address(), topics, data))
+ vm.Env().AddLog(state.NewLog(vm.me.Address(), topics, data, vm.env.BlockNumber().Uint64()))
}
//export env_extcode
diff --git a/whisper/whisper.go b/whisper/whisper.go
index 50c2f98fd..13209f9a6 100644
--- a/whisper/whisper.go
+++ b/whisper/whisper.go
@@ -127,6 +127,10 @@ func (self *Whisper) Watch(opts Filter) int {
})
}
+func (self *Whisper) Unwatch(id int) {
+ self.filters.Uninstall(id)
+}
+
func (self *Whisper) Messages(id int) (messages []*Message) {
filter := self.filters.Get(id)
if filter != nil {
diff --git a/xeth/world.go b/xeth/state.go
index 9cbdd9461..e2562613c 100644
--- a/xeth/world.go
+++ b/xeth/state.go
@@ -3,19 +3,20 @@ package xeth
import "github.com/ethereum/go-ethereum/state"
type State struct {
- xeth *XEth
+ xeth *XEth
+ state *state.StateDB
}
-func NewState(xeth *XEth) *State {
- return &State{xeth}
+func NewState(xeth *XEth, statedb *state.StateDB) *State {
+ return &State{xeth, statedb}
}
func (self *State) State() *state.StateDB {
- return self.xeth.chainManager.TransState()
+ return self.state
}
func (self *State) Get(addr string) *Object {
- return &Object{self.State().GetStateObject(fromHex(addr))}
+ return &Object{self.state.GetStateObject(fromHex(addr))}
}
func (self *State) SafeGet(addr string) *Object {
@@ -23,7 +24,7 @@ func (self *State) SafeGet(addr string) *Object {
}
func (self *State) safeGet(addr string) *state.StateObject {
- object := self.State().GetStateObject(fromHex(addr))
+ object := self.state.GetStateObject(fromHex(addr))
if object == nil {
object = state.NewStateObject(fromHex(addr), self.xeth.eth.Db())
}
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 5907a8329..677d40fd5 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -17,6 +17,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/whisper"
)
@@ -54,13 +55,26 @@ func New(eth Backend) *XEth {
whisper: NewWhisper(eth.Whisper()),
miner: eth.Miner(),
}
- xeth.state = NewState(xeth)
+ xeth.state = NewState(xeth, xeth.chainManager.TransState())
return xeth
}
-func (self *XEth) Backend() Backend { return self.eth }
-func (self *XEth) State() *State { return self.state }
+func (self *XEth) Backend() Backend { return self.eth }
+func (self *XEth) UseState(statedb *state.StateDB) *XEth {
+ xeth := &XEth{
+ eth: self.eth,
+ blockProcessor: self.blockProcessor,
+ chainManager: self.chainManager,
+ whisper: self.whisper,
+ miner: self.miner,
+ }
+
+ xeth.state = NewState(xeth, statedb)
+ return xeth
+}
+func (self *XEth) State() *State { return self.state }
+
func (self *XEth) Whisper() *Whisper { return self.whisper }
func (self *XEth) Miner() *miner.Miner { return self.miner }
@@ -229,7 +243,7 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st
}
var (
- statedb = self.chainManager.TransState()
+ statedb = self.State().State() //self.chainManager.TransState()
key = self.eth.KeyManager().KeyPair()
from = statedb.GetOrNewStateObject(key.Address())
block = self.chainManager.CurrentBlock()
@@ -277,7 +291,7 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string)
}
var err error
- state := self.eth.ChainManager().TransState()
+ state := self.eth.ChainManager().TxState()
if balance := state.GetBalance(key.Address()); balance.Cmp(tx.Value()) < 0 {
return "", fmt.Errorf("insufficient balance. balance=%v tx=%v", balance, tx.Value())
}
@@ -286,14 +300,6 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string)
tx.SetNonce(nonce)
tx.Sign(key.PrivateKey)
- //fmt.Printf("create tx: %x %v\n", tx.Hash()[:4], tx.Nonce())
-
- // Do some pre processing for our "pre" events and hooks
- block := self.chainManager.NewBlock(key.Address())
- coinbase := state.GetOrNewStateObject(key.Address())
- coinbase.SetGasPool(block.GasLimit())
- self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true)
-
err = self.eth.TxPool().Add(tx)
if err != nil {
return "", err