Commit af6971f8 authored by zelig's avatar zelig

Merge remote-tracking branch 'upstream/develop' into blockpool2

parents a60a18b0 65cad14f
language: go language: go
go: go:
- 1.4.1 - 1.4.2
before_install: 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 update -qq
- sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine - sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine
install: install:
......
FROM ubuntu:14.04.1 FROM ubuntu:14.04.2
## Environment setup ## Environment setup
ENV HOME /root ENV HOME /root
...@@ -12,22 +12,22 @@ ENV DEBIAN_FRONTEND noninteractive ...@@ -12,22 +12,22 @@ ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get upgrade -y 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 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) ## Install Qt5.4.1 (not required for CLI)
# RUN add-apt-repository ppa:beineri/opt-qt54-trusty -y # RUN add-apt-repository ppa:beineri/opt-qt541-trusty -y
# RUN apt-get update -y # RUN apt-get update -y
# RUN apt-get install -y qt54quickcontrols qt54webengine mesa-common-dev libglu1-mesa-dev # RUN apt-get install -y qt54quickcontrols qt54webengine mesa-common-dev libglu1-mesa-dev
# ENV PKG_CONFIG_PATH /opt/qt54/lib/pkgconfig # ENV PKG_CONFIG_PATH /opt/qt54/lib/pkgconfig
# Install Golang # 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 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 # 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 ADD https://api.github.com/repos/ethereum/go-ethereum/git/refs/heads/develop file_does_not_exist
## Fetch and install go-ethereum ## Fetch and install go-ethereum
RUN go get -v github.com/tools/godep RUN go get github.com/tools/godep
RUN go get -v -d github.com/ethereum/go-ethereum/... RUN go get -d github.com/ethereum/go-ethereum/...
WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum
RUN git checkout develop RUN git checkout develop
RUN godep restore RUN godep restore
......
{ {
"ImportPath": "github.com/ethereum/go-ethereum", "ImportPath": "github.com/ethereum/go-ethereum",
"GoVersion": "go1.4.1", "GoVersion": "go1.4.2",
"Packages": [ "Packages": [
"./..." "./..."
], ],
"Deps": [ "Deps": [
{
"ImportPath": "bitbucket.org/kardianos/osext",
"Comment": "null-13",
"Rev": "5d3ddcf53a508cc2f7404eaebf546ef2cb5cdb6e"
},
{ {
"ImportPath": "code.google.com/p/go-uuid/uuid", "ImportPath": "code.google.com/p/go-uuid/uuid",
"Comment": "null-12", "Comment": "null-12",
...@@ -37,6 +32,10 @@ ...@@ -37,6 +32,10 @@
"ImportPath": "github.com/jackpal/go-nat-pmp", "ImportPath": "github.com/jackpal/go-nat-pmp",
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1" "Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
}, },
{
"ImportPath": "github.com/kardianos/osext",
"Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
},
{ {
"ImportPath": "github.com/obscuren/otto", "ImportPath": "github.com/obscuren/otto",
"Rev": "cf13cc4228c5e5ce0fe27a7aea90bc10091c4f19" "Rev": "cf13cc4228c5e5ce0fe27a7aea90bc10091c4f19"
......
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.
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.
### 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.
...@@ -25,8 +25,3 @@ func ExecutableFolder() (string, error) { ...@@ -25,8 +25,3 @@ func ExecutableFolder() (string, error) {
folder, _ := filepath.Split(p) folder, _ := filepath.Split(p)
return folder, nil return folder, nil
} }
// Depricated. Same as Executable().
func GetExePath() (exePath string, err error) {
return Executable()
}
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
package osext package osext
import ( import (
"syscall"
"os" "os"
"strconv" "strconv"
"syscall"
) )
func executable() (string, error) { func executable() (string, error) {
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux netbsd openbsd // +build linux netbsd openbsd solaris dragonfly
package osext package osext
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"runtime" "runtime"
) )
...@@ -18,8 +19,10 @@ func executable() (string, error) { ...@@ -18,8 +19,10 @@ func executable() (string, error) {
return os.Readlink("/proc/self/exe") return os.Readlink("/proc/self/exe")
case "netbsd": case "netbsd":
return os.Readlink("/proc/curproc/exe") return os.Readlink("/proc/curproc/exe")
case "openbsd": case "openbsd", "dragonfly":
return os.Readlink("/proc/curproc/file") 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) return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
} }
...@@ -34,9 +34,16 @@ package accounts ...@@ -34,9 +34,16 @@ package accounts
import ( import (
crand "crypto/rand" crand "crypto/rand"
"errors"
"sync"
"time"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
var ErrLocked = errors.New("account is locked; please request passphrase")
// TODO: better name for this struct? // TODO: better name for this struct?
type Account struct { type Account struct {
Address []byte Address []byte
...@@ -44,14 +51,17 @@ type Account struct { ...@@ -44,14 +51,17 @@ type Account struct {
type AccountManager struct { 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 func NewAccountManager(keyStore crypto.KeyStore2, unlockMilliseconds time.Duration) AccountManager {
keysMap := make(map[string]crypto.Key)
// TODO: pass through passphrase for APIs which require access to private key?
func NewAccountManager(keyStore crypto.KeyStore2) AccountManager {
am := &AccountManager{ am := &AccountManager{
keyStore: keyStore, keyStore: keyStore,
unlockedKeys: keysMap,
unlockMilliseconds: unlockMilliseconds,
} }
return *am return *am
} }
...@@ -60,11 +70,26 @@ func (am AccountManager) DeleteAccount(address []byte, auth string) error { ...@@ -60,11 +70,26 @@ func (am AccountManager) DeleteAccount(address []byte, auth string) error {
return am.keyStore.DeleteKey(address, auth) return am.keyStore.DeleteKey(address, auth)
} }
func (am *AccountManager) Sign(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) { 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) key, err := am.keyStore.GetKey(fromAccount.Address, keyAuth)
if err != nil { if err != nil {
return nil, err 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) signature, err = crypto.Sign(toSign, key.PrivateKey)
return signature, err return signature, err
} }
...@@ -80,8 +105,6 @@ func (am AccountManager) NewAccount(auth string) (*Account, error) { ...@@ -80,8 +105,6 @@ func (am AccountManager) NewAccount(auth string) (*Account, error) {
return ua, err 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) { func (am *AccountManager) Accounts() ([]Account, error) {
addresses, err := am.keyStore.GetKeyAddresses() addresses, err := am.keyStore.GetKeyAddresses()
if err != nil { if err != nil {
...@@ -97,3 +120,13 @@ func (am *AccountManager) Accounts() ([]Account, error) { ...@@ -97,3 +120,13 @@ func (am *AccountManager) Accounts() ([]Account, error) {
} }
return accounts, err 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()
}
...@@ -6,19 +6,68 @@ import ( ...@@ -6,19 +6,68 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/randentropy" "github.com/ethereum/go-ethereum/crypto/randentropy"
"github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/ethutil"
"time"
) )
func TestAccountManager(t *testing.T) { func TestAccountManager(t *testing.T) {
ks := crypto.NewKeyStorePlain(ethutil.DefaultDataDir() + "/testaccounts") ks := crypto.NewKeyStorePlain(ethutil.DefaultDataDir() + "/testaccounts")
am := NewAccountManager(ks) am := NewAccountManager(ks, 100)
pass := "" // not used but required by API pass := "" // not used but required by API
a1, err := am.NewAccount(pass) a1, err := am.NewAccount(pass)
toSign := randentropy.GetEntropyCSPRNG(32) toSign := randentropy.GetEntropyCSPRNG(32)
_, err = am.Sign(a1, pass, toSign) _, err = am.SignLocked(a1, pass, toSign)
if err != nil { if err != nil {
t.Fatal(err) 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 // Cleanup
accounts, err := am.Accounts() accounts, err := am.Accounts()
if err != nil { if err != nil {
......
...@@ -27,6 +27,7 @@ import ( ...@@ -27,6 +27,7 @@ import (
"log" "log"
"os" "os"
"path" "path"
"runtime"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/ethutil"
...@@ -43,6 +44,7 @@ var ( ...@@ -43,6 +44,7 @@ var (
KeyStore string KeyStore string
StartRpc bool StartRpc bool
StartWebSockets bool StartWebSockets bool
RpcListenAddress string
RpcPort int RpcPort int
WsPort int WsPort int
OutboundPort string OutboundPort string
...@@ -70,6 +72,7 @@ var ( ...@@ -70,6 +72,7 @@ var (
SHH bool SHH bool
Dial bool Dial bool
PrintVersion bool PrintVersion bool
MinerThreads int
) )
// flags specific to cli client // flags specific to cli client
...@@ -93,6 +96,7 @@ func Init() { ...@@ -93,6 +96,7 @@ func Init() {
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use") 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 (db)")
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(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket 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(&StartRpc, "rpc", false, "start rpc server")
...@@ -119,6 +123,7 @@ func Init() { ...@@ -119,6 +123,7 @@ func Init() {
flag.BoolVar(&StartMining, "mine", false, "start dagger mining") flag.BoolVar(&StartMining, "mine", false, "start dagger mining")
flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console") flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console")
flag.BoolVar(&PrintVersion, "version", false, "prints version number") flag.BoolVar(&PrintVersion, "version", false, "prints version number")
flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads")
// Network stuff // Network stuff
var ( var (
...@@ -135,6 +140,12 @@ func Init() { ...@@ -135,6 +140,12 @@ func Init() {
flag.Parse() 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 var err error
if NAT, err = nat.Parse(*natstr); err != nil { if NAT, err = nat.Parse(*natstr); err != nil {
log.Fatalf("-nat: %v", err) log.Fatalf("-nat: %v", err)
......
...@@ -37,7 +37,7 @@ import ( ...@@ -37,7 +37,7 @@ import (
const ( const (
ClientIdentifier = "Ethereum(G)" ClientIdentifier = "Ethereum(G)"
Version = "0.8.5" Version = "0.8.6"
) )
var clilogger = logger.NewLogger("CLI") var clilogger = logger.NewLogger("CLI")
...@@ -76,6 +76,7 @@ func main() { ...@@ -76,6 +76,7 @@ func main() {
Dial: Dial, Dial: Dial,
BootNodes: BootNodes, BootNodes: BootNodes,
NodeKey: NodeKey, NodeKey: NodeKey,
MinerThreads: MinerThreads,
}) })
if err != nil { if err != nil {
...@@ -113,10 +114,6 @@ func main() { ...@@ -113,10 +114,6 @@ func main() {
return return
} }
if StartMining {
utils.StartMining(ethereum)
}
if len(ImportChain) > 0 { if len(ImportChain) > 0 {
start := time.Now() start := time.Now()
err := utils.ImportChain(ethereum, ImportChain) err := utils.ImportChain(ethereum, ImportChain)
...@@ -128,7 +125,7 @@ func main() { ...@@ -128,7 +125,7 @@ func main() {
} }
if StartRpc { if StartRpc {
utils.StartRpc(ethereum, RpcPort) utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
} }
if StartWebSockets { if StartWebSockets {
...@@ -137,6 +134,12 @@ func main() { ...@@ -137,6 +134,12 @@ func main() {
utils.StartEthereum(ethereum) utils.StartEthereum(ethereum)
fmt.Printf("Welcome to the FRONTIER\n")
if StartMining {
ethereum.Miner().Start()
}
if StartJsConsole { if StartJsConsole {
InitJsConsole(ethereum) InitJsConsole(ethereum)
} else if len(InputFile) > 0 { } else if len(InputFile) > 0 {
......
...@@ -60,6 +60,7 @@ func (self *JSRepl) Start() { ...@@ -60,6 +60,7 @@ func (self *JSRepl) Start() {
if !self.running { if !self.running {
self.running = true self.running = true
repllogger.Infoln("init JS Console") repllogger.Infoln("init JS Console")
reader := bufio.NewReader(self.history) reader := bufio.NewReader(self.history)
for { for {
line, err := reader.ReadString('\n') line, err := reader.ReadString('\n')
......
...@@ -62,6 +62,8 @@ ...@@ -62,6 +62,8 @@
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545')); web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545'));
eth.defaultBlock = -2
document.querySelector("#number").innerHTML = eth.number; document.querySelector("#number").innerHTML = eth.number;
document.querySelector("#coinbase").innerHTML = eth.coinbase document.querySelector("#coinbase").innerHTML = eth.coinbase
document.querySelector("#peer_count").innerHTML = eth.peerCount; document.querySelector("#peer_count").innerHTML = eth.peerCount;
...@@ -75,6 +77,7 @@ ...@@ -75,6 +77,7 @@
document.querySelector("#number").innerHTML = eth.number; document.querySelector("#number").innerHTML = eth.number;
}); });
</script> </script>
</html> </html>
......
...@@ -53,7 +53,6 @@ var inputTypes = types.inputTypes(); ...@@ -53,7 +53,6 @@ var inputTypes = types.inputTypes();
/// @returns bytes representation of input params /// @returns bytes representation of input params
var formatInput = function (inputs, params) { var formatInput = function (inputs, params) {
var bytes = ""; var bytes = "";
var padding = c.ETH_PADDING * 2;
/// first we iterate in search for dynamic /// first we iterate in search for dynamic
inputs.forEach(function (input, index) { inputs.forEach(function (input, index) {
...@@ -110,6 +109,7 @@ var formatOutput = function (outs, output) { ...@@ -110,6 +109,7 @@ var formatOutput = function (outs, output) {
output = output.slice(dynamicPartLength); output = output.slice(dynamicPartLength);
outs.forEach(function (out, i) { outs.forEach(function (out, i) {
/*jshint maxcomplexity:6 */
var typeMatch = false; var typeMatch = false;
for (var j = 0; j < outputTypes.length && !typeMatch; j++) { for (var j = 0; j < outputTypes.length && !typeMatch; j++) {
typeMatch = outputTypes[j].type(outs[i].type); typeMatch = outputTypes[j].type(outs[i].type);
...@@ -210,7 +210,7 @@ module.exports = { ...@@ -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. This file is part of ethereum.js.
...@@ -264,7 +264,8 @@ module.exports = { ...@@ -264,7 +264,8 @@ module.exports = {
ETH_PADDING: 32, ETH_PADDING: 32,
ETH_SIGNATURE_LENGTH: 4, ETH_SIGNATURE_LENGTH: 4,
ETH_UNITS: ETH_UNITS, 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) { ...@@ -340,6 +341,7 @@ var addFunctionsToContract = function (contract, desc, address) {
var typeName = utils.extractTypeName(method.name); var typeName = utils.extractTypeName(method.name);
var impl = function () { var impl = function () {
/*jshint maxcomplexity:7 */
var params = Array.prototype.slice.call(arguments); var params = Array.prototype.slice.call(arguments);
var signature = abi.signatureFromAscii(method.name); var signature = abi.signatureFromAscii(method.name);
var parsed = inputParser[displayName][typeName].apply(null, params); var parsed = inputParser[displayName][typeName].apply(null, params);
...@@ -416,11 +418,11 @@ var addEventsToContract = function (contract, desc, address) { ...@@ -416,11 +418,11 @@ var addEventsToContract = function (contract, desc, address) {
var signature = abi.eventSignatureFromAscii(e.name); var signature = abi.eventSignatureFromAscii(e.name);
var event = eventImpl.inputParser(address, signature, e); var event = eventImpl.inputParser(address, signature, e);
var o = event.apply(null, params); var o = event.apply(null, params);
o._onWatchEventResult = function (data) { var outputFormatter = function (data) {
var parser = eventImpl.outputParser(e); var parser = eventImpl.outputParser(e);
return parser(data); 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 // this property should be used by eth.filter to check if object is an event
...@@ -487,7 +489,131 @@ var contract = function (address, desc) { ...@@ -487,7 +489,131 @@ var contract = function (address, desc) {
module.exports = contract; 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. This file is part of ethereum.js.
...@@ -571,9 +697,9 @@ var getArgumentsObject = function (inputs, indexed, notIndexed) { ...@@ -571,9 +697,9 @@ var getArgumentsObject = function (inputs, indexed, notIndexed) {
return inputs.reduce(function (acc, current) { return inputs.reduce(function (acc, current) {
var value; var value;
if (current.indexed) if (current.indexed)
value = indexed.splice(0, 1)[0]; value = indexedCopy.splice(0, 1)[0];
else else
value = notIndexed.splice(0, 1)[0]; value = notIndexedCopy.splice(0, 1)[0];
acc[current.name] = value; acc[current.name] = value;
return acc; return acc;
...@@ -589,6 +715,7 @@ var outputParser = function (event) { ...@@ -589,6 +715,7 @@ var outputParser = function (event) {
args: {} args: {}
}; };
output.topics = output.topic; // fallback for go-ethereum
if (!output.topic) { if (!output.topic) {
return result; return result;
} }
...@@ -624,7 +751,7 @@ module.exports = { ...@@ -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. This file is part of ethereum.js.
...@@ -650,24 +777,33 @@ module.exports = { ...@@ -650,24 +777,33 @@ module.exports = {
* @date 2014 * @date 2014
*/ */
var web3 = require('./web3'); // jshint ignore:line /// Should be called to check if filter implementation is valid
/// @returns true if it is, otherwise false
/// should be used when we want to watch something var implementationIsValid = function (i) {
/// it's using inner polling mechanism and is notified about changes return !!i &&
/// TODO: change 'options' name cause it may be not the best matching one, since we have events typeof i.newFilter === 'function' &&
var Filter = function(options, impl) { 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;
}
if (typeof options !== "string") { options = options || {};
// topics property is deprecated, warn about it!
if (options.topics) { if (options.topics) {
console.warn('"topics" is deprecated, use "topic" instead'); console.warn('"topics" is deprecated, is "topic" instead');
} }
this._onWatchResult = options._onWatchEventResult;
// evaluate lazy properties // evaluate lazy properties
options = { return {
to: options.to, to: options.to,
topic: options.topic, topic: options.topic,
earliest: options.earliest, earliest: options.earliest,
...@@ -676,58 +812,61 @@ var Filter = function(options, impl) { ...@@ -676,58 +812,61 @@ var Filter = function(options, impl) {
skip: options.skip, skip: options.skip,
address: options.address address: options.address
}; };
};
/// 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;
} }
this.impl = impl; options = getOptions(options);
this.callbacks = []; 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);
});
});
};
this.id = impl.newFilter(options); implementation.startPolling(filterId, onMessages, implementation.uninstallFilter);
web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this));
};
/// alias for changed* var changed = function (callback) {
Filter.prototype.arrived = function(callback) { callbacks.push(callback);
this.changed(callback); };
};
Filter.prototype.happened = function(callback) {
this.changed(callback);
};
/// gets called when there is new eth/shh message
Filter.prototype.changed = function(callback) {
this.callbacks.push(callback);
};
/// trigger calling new message from people var messages = function () {
Filter.prototype.trigger = function(messages) { return implementation.getMessages(filterId);
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);
}
}
};
/// should be called to uninstall current filter var uninstall = function () {
Filter.prototype.uninstall = function() { implementation.stopPolling(filterId);
this.impl.uninstallFilter(this.id); implementation.uninstallFilter(filterId);
web3.provider.stopPolling(this.id); callbacks = [];
}; };
/// should be called to manually trigger getting latest messages from the client return {
Filter.prototype.messages = function() { changed: changed,
return this.impl.getMessages(this.id); arrived: changed,
happened: changed,
messages: messages,
logs: messages,
uninstall: uninstall
};
}; };
/// alias for messages module.exports = filter;
Filter.prototype.logs = function () {
return this.messages();
};
module.exports = Filter;
},{"./web3":13}],6:[function(require,module,exports){ },{}],8:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
...@@ -770,6 +909,7 @@ var padLeft = function (string, chars, sign) { ...@@ -770,6 +909,7 @@ var padLeft = function (string, chars, sign) {
/// If the value is floating point, round it down /// If the value is floating point, round it down
/// @returns right-aligned byte representation of int /// @returns right-aligned byte representation of int
var formatInputInt = function (value) { var formatInputInt = function (value) {
/*jshint maxcomplexity:7 */
var padding = c.ETH_PADDING * 2; var padding = c.ETH_PADDING * 2;
if (value instanceof BigNumber || typeof value === 'number') { if (value instanceof BigNumber || typeof value === 'number') {
if (typeof value === 'number') if (typeof value === 'number')
...@@ -883,7 +1023,7 @@ module.exports = { ...@@ -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. This file is part of ethereum.js.
...@@ -923,15 +1063,17 @@ HttpSyncProvider.prototype.send = function (payload) { ...@@ -923,15 +1063,17 @@ HttpSyncProvider.prototype.send = function (payload) {
request.open('POST', this.host, false); request.open('POST', this.host, false);
request.send(JSON.stringify(payload)); request.send(JSON.stringify(payload));
// check request.status
var result = request.responseText; var result = request.responseText;
// check request.status
if(request.status !== 200)
return;
return JSON.parse(result); return JSON.parse(result);
}; };
module.exports = HttpSyncProvider; module.exports = HttpSyncProvider;
},{}],8:[function(require,module,exports){ },{}],10:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
...@@ -998,7 +1140,7 @@ module.exports = { ...@@ -998,7 +1140,7 @@ module.exports = {
},{}],9:[function(require,module,exports){ },{}],11:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
...@@ -1015,7 +1157,42 @@ module.exports = { ...@@ -1015,7 +1157,42 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License 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/>. 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: * @authors:
* Jeffrey Wilcke <jeff@ethdev.com> * Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com> * Marek Kotewicz <marek@ethdev.com>
...@@ -1024,51 +1201,28 @@ module.exports = { ...@@ -1024,51 +1201,28 @@ module.exports = {
* @date 2014 * @date 2014
*/ */
var web3 = require('./web3');
var jsonrpc = require('./jsonrpc'); var jsonrpc = require('./jsonrpc');
var c = require('./const');
/** /**
* Provider manager object prototype
* It's responsible for passing messages to providers * 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 * It's also responsible for polling the ethereum node for incoming messages
* Default poll timeout is 12 seconds * Default poll timeout is 1 second
* 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
*/ */
var ProviderManager = function() { var requestManager = function() {
this.polls = []; var polls = [];
this.provider = undefined; 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;
}
data.callback(result);
});
setTimeout(poll, 1000);
};
poll();
};
/// sends outgoing requests var send = function (data) {
/// @params data - an object with at least 'method' property
ProviderManager.prototype.send = function(data) {
var payload = jsonrpc.toPayload(data.method, data.params); var payload = jsonrpc.toPayload(data.method, data.params);
if (this.provider === undefined) { if (!provider) {
console.error('provider is not set'); console.error('provider is not set');
return null; return null;
} }
var result = this.provider.send(payload); var result = provider.send(payload);
if (!jsonrpc.isValidResponse(result)) { if (!jsonrpc.isValidResponse(result)) {
console.log(result); console.log(result);
...@@ -1076,33 +1230,66 @@ ProviderManager.prototype.send = function(data) { ...@@ -1076,33 +1230,66 @@ ProviderManager.prototype.send = function(data) {
} }
return result.result; return result.result;
}; };
/// setups provider, which will be used for sending messages var setProvider = function (p) {
ProviderManager.prototype.set = function(provider) { provider = p;
this.provider = provider; };
};
/// this method is only used, when we do not have native qt bindings and have to do polling on our own /*jshint maxparams:4 */
/// should be callled, on start watching for eth/shh changes var startPolling = function (data, pollId, callback, uninstall) {
ProviderManager.prototype.startPolling = function (data, pollId, callback) { polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall});
this.polls.push({data: data, id: pollId, callback: callback}); };
}; /*jshint maxparams:3 */
/// should be called to stop polling for certain watch changes var stopPolling = function (pollId) {
ProviderManager.prototype.stopPolling = function (pollId) { for (var i = polls.length; i--;) {
for (var i = this.polls.length; i--;) { var poll = polls[i];
var poll = this.polls[i];
if (poll.id === pollId) { if (poll.id === pollId) {
this.polls.splice(i, 1); polls.splice(i, 1);
} }
} }
};
var reset = function () {
polls.forEach(function (poll) {
poll.uninstall(poll.id);
});
polls = [];
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
poll();
};
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();
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. This file is part of ethereum.js.
...@@ -1119,25 +1306,29 @@ module.exports = ProviderManager; ...@@ -1119,25 +1306,29 @@ module.exports = ProviderManager;
You should have received a copy of the GNU Lesser General Public License 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/>. along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file qtsync.js /** @file shh.js
* @authors: * @authors:
* Marek Kotewicz <marek@ethdev.com> * Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com> * @date 2015
* @date 2014
*/ */
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) { module.exports = {
var result = navigator.qt.callMethod(JSON.stringify(payload)); methods: methods
return JSON.parse(result);
}; };
module.exports = QtSyncProvider;
},{}],11:[function(require,module,exports){ },{}],14:[function(require,module,exports){
/* /*
This file is part of ethereum.js. This file is part of ethereum.js.
...@@ -1218,7 +1409,7 @@ module.exports = { ...@@ -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. This file is part of ethereum.js.
...@@ -1328,6 +1519,7 @@ var filterEvents = function (json) { ...@@ -1328,6 +1519,7 @@ var filterEvents = function (json) {
/// TODO: use BigNumber.js to parse int /// TODO: use BigNumber.js to parse int
/// TODO: add tests for it! /// TODO: add tests for it!
var toEth = function (str) { 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 val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str;
var unit = 0; var unit = 0;
var units = c.ETH_UNITS; var units = c.ETH_UNITS;
...@@ -1362,7 +1554,7 @@ module.exports = { ...@@ -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. This file is part of ethereum.js.
...@@ -1379,102 +1571,14 @@ module.exports = { ...@@ -1379,102 +1571,14 @@ module.exports = {
You should have received a copy of the GNU Lesser General Public License 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/>. along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file web3.js /** @file watches.js
* @authors: * @authors:
* Jeffrey Wilcke <jeff@ethdev.com>
* Marek Kotewicz <marek@ethdev.com> * Marek Kotewicz <marek@ethdev.com>
* Marian Oancea <marian@ethdev.com> * @date 2015
* Gav Wood <g@ethdev.com>
* @date 2014
*/ */
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 /// @returns an array of objects describing web3.eth.watch api methods
var ethWatchMethods = function () { var eth = function () {
var newFilter = function (args) { var newFilter = function (args) {
return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter';
}; };
...@@ -1487,7 +1591,7 @@ var ethWatchMethods = function () { ...@@ -1487,7 +1591,7 @@ var ethWatchMethods = function () {
}; };
/// @returns an array of objects describing web3.shh.watch api methods /// @returns an array of objects describing web3.shh.watch api methods
var shhWatchMethods = function () { var shh = function () {
return [ return [
{ name: 'newFilter', call: 'shh_newFilter' }, { name: 'newFilter', call: 'shh_newFilter' },
{ name: 'uninstallFilter', call: 'shh_uninstallFilter' }, { name: 'uninstallFilter', call: 'shh_uninstallFilter' },
...@@ -1495,6 +1599,57 @@ var shhWatchMethods = function () { ...@@ -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 /// creates methods in a given object based on method description on input
/// setups api calls for these methods /// setups api calls for these methods
var setupMethods = function (obj, methods) { var setupMethods = function (obj, methods) {
...@@ -1502,7 +1657,7 @@ var setupMethods = function (obj, methods) { ...@@ -1502,7 +1657,7 @@ var setupMethods = function (obj, methods) {
obj[method.name] = function () { obj[method.name] = function () {
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
var call = typeof method.call === 'function' ? method.call(args) : method.call; var call = typeof method.call === 'function' ? method.call(args) : method.call;
return web3.provider.send({ return web3.manager.send({
method: call, method: call,
params: args params: args
}); });
...@@ -1516,14 +1671,14 @@ var setupProperties = function (obj, properties) { ...@@ -1516,14 +1671,14 @@ var setupProperties = function (obj, properties) {
properties.forEach(function (property) { properties.forEach(function (property) {
var proto = {}; var proto = {};
proto.get = function () { proto.get = function () {
return web3.provider.send({ return web3.manager.send({
method: property.getter method: property.getter
}); });
}; };
if (property.setter) { if (property.setter) {
proto.set = function (val) { proto.set = function (val) {
return web3.provider.send({ return web3.manager.send({
method: property.setter, method: property.setter,
params: [val] params: [val]
}); });
...@@ -1533,10 +1688,32 @@ var setupProperties = function (obj, properties) { ...@@ -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 /// setups web3 object, and it's in-browser executed methods
var web3 = { var web3 = {
_callbacks: {}, manager: requestManager(),
_events: {},
providers: {}, providers: {},
/// @returns ascii string representation of hex value prefixed with 0x /// @returns ascii string representation of hex value prefixed with 0x
...@@ -1575,12 +1752,15 @@ var web3 = { ...@@ -1575,12 +1752,15 @@ var web3 = {
/// @param filter may be a string, object or event /// @param filter may be a string, object or event
/// @param indexed is optional, this is an object with optional event indexed params /// @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'...) /// @param options is optional, this is an object with optional event options ('max'...)
watch: function (filter, indexed, options) { /// TODO: fix it, 4 params? no way
if (filter._isEvent) { /*jshint maxparams:4 */
return filter(indexed, options); 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 /// db object prototype
...@@ -1588,54 +1768,44 @@ var web3 = { ...@@ -1588,54 +1768,44 @@ var web3 = {
/// shh object prototype /// shh object prototype
shh: { shh: {
/// @param filter may be a string, object or event /// @param filter may be a string, object or event
watch: function (filter, indexed) { watch: function (fil) {
return new web3.filter(filter, shhWatch); 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 /// setups all api methods
setupMethods(web3, web3Methods()); setupMethods(web3, web3Methods());
setupMethods(web3.eth, ethMethods()); setupMethods(web3.eth, eth.methods());
setupProperties(web3.eth, ethProperties()); setupProperties(web3.eth, eth.properties());
setupMethods(web3.db, dbMethods()); setupMethods(web3.db, db.methods());
setupMethods(web3.shh, shhMethods()); setupMethods(web3.shh, shh.methods());
setupMethods(ethWatch, watches.eth());
var ethWatch = { setupMethods(shhWatch, watches.shh());
changed: 'eth_changed'
};
setupMethods(ethWatch, ethWatchMethods());
var shhWatch = {
changed: 'shh_changed'
};
setupMethods(shhWatch, shhWatchMethods());
web3.setProvider = function(provider) {
web3.provider.set(provider);
};
module.exports = web3; 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 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.HttpSyncProvider = require('./lib/httpsync');
web3.providers.QtSyncProvider = require('./lib/qtsync'); web3.providers.QtSyncProvider = require('./lib/qtsync');
web3.eth.contract = require('./lib/contract'); web3.eth.contract = require('./lib/contract');
web3.abi = require('./lib/abi'); web3.abi = require('./lib/abi');
module.exports = web3; 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 //# sourceMappingURL=ethereum.js.map
...@@ -964,7 +964,7 @@ ApplicationWindow { ...@@ -964,7 +964,7 @@ ApplicationWindow {
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 30 anchors.topMargin: 30
font.pointSize: 12 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"
} }
} }
......
...@@ -27,10 +27,8 @@ import ( ...@@ -27,10 +27,8 @@ import (
"log" "log"
"os" "os"
"path" "path"
"path/filepath"
"runtime" "runtime"
"bitbucket.org/kardianos/osext"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
...@@ -44,6 +42,7 @@ var ( ...@@ -44,6 +42,7 @@ var (
KeyStore string KeyStore string
StartRpc bool StartRpc bool
StartWebSockets bool StartWebSockets bool
RpcListenAddress string
RpcPort int RpcPort int
WsPort int WsPort int
OutboundPort string OutboundPort string
...@@ -68,33 +67,6 @@ var ( ...@@ -68,33 +67,6 @@ var (
// flags specific to gui client // flags specific to gui client
var AssetPath string 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
}
var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini") var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
func Init() { func Init() {
...@@ -108,6 +80,7 @@ func Init() { ...@@ -108,6 +80,7 @@ func Init() {
flag.StringVar(&Identifier, "id", "", "Custom client identifier") flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use") 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 (db)")
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(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket 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(&StartRpc, "rpc", true, "start rpc server")
...@@ -122,7 +95,7 @@ func Init() { ...@@ -122,7 +95,7 @@ func Init() {
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") 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 // Network stuff
var ( var (
......
...@@ -36,7 +36,7 @@ import ( ...@@ -36,7 +36,7 @@ import (
const ( const (
ClientIdentifier = "Mist" ClientIdentifier = "Mist"
Version = "0.8.5" Version = "0.8.6"
) )
var ethereum *eth.Ethereum var ethereum *eth.Ethereum
...@@ -73,7 +73,7 @@ func run() error { ...@@ -73,7 +73,7 @@ func run() error {
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive) utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
if StartRpc { if StartRpc {
utils.StartRpc(ethereum, RpcPort) utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
} }
if StartWebSockets { if StartWebSockets {
......
...@@ -25,12 +25,8 @@ import ( ...@@ -25,12 +25,8 @@ import (
"fmt" "fmt"
"os" "os"
"os/signal" "os/signal"
"path"
"path/filepath"
"regexp" "regexp"
"runtime"
"bitbucket.org/kardianos/osext"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
...@@ -132,31 +128,6 @@ func StartEthereum(ethereum *eth.Ethereum) { ...@@ -132,31 +128,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) { func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
var err error var err error
...@@ -189,9 +160,9 @@ func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, Secre ...@@ -189,9 +160,9 @@ func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, Secre
clilogger.Infof("Main address %x\n", keyManager.Address()) 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 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 { if err != nil {
clilogger.Errorf("Could not start RPC interface (port %v): %v", RpcPort, err) clilogger.Errorf("Could not start RPC interface (port %v): %v", RpcPort, err)
} else { } else {
......
...@@ -50,7 +50,6 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM ...@@ -50,7 +50,6 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM
sm := &BlockProcessor{ sm := &BlockProcessor{
db: db, db: db,
mem: make(map[string]*big.Int), mem: make(map[string]*big.Int),
//Pow: &ethash.Ethash{},
Pow: ezp.New(), Pow: ezp.New(),
bc: chainManager, bc: chainManager,
eventMux: eventMux, eventMux: eventMux,
...@@ -62,7 +61,7 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM ...@@ -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) { 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 := statedb.GetOrNewStateObject(block.Header().Coinbase)
coinbase.SetGasPool(CalcGasLimit(parent, block)) coinbase.SetGasPool(block.Header().GasLimit)
// Process the transactions on to parent state // Process the transactions on to parent state
receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess) receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess)
...@@ -100,7 +99,8 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated ...@@ -100,7 +99,8 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
// Notify all subscribers // Notify all subscribers
if !transientProcess { if !transientProcess {
go self.eventMux.Post(TxPostEvent{tx}) go self.eventMux.Post(TxPostEvent{tx})
go self.eventMux.Post(statedb.Logs()) logs := statedb.Logs()
go self.eventMux.Post(logs)
} }
return receipt, txGas, err return receipt, txGas, err
...@@ -247,6 +247,11 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { ...@@ -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) 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() { if block.Time() < parent.Time() {
return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time) return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time)
} }
......
...@@ -51,8 +51,6 @@ func GenesisBlock(db ethutil.Database) *types.Block { ...@@ -51,8 +51,6 @@ func GenesisBlock(db ethutil.Database) *types.Block {
statedb.Sync() statedb.Sync()
genesis.Header().Root = statedb.Root() genesis.Header().Root = statedb.Root()
fmt.Printf("+++ genesis +++\nRoot: %x\nHash: %x\n", genesis.Header().Root, genesis.Hash())
return genesis return genesis
} }
......
...@@ -126,7 +126,7 @@ func (self *StateTransition) BuyGas() error { ...@@ -126,7 +126,7 @@ func (self *StateTransition) BuyGas() error {
self.AddGas(self.msg.Gas()) self.AddGas(self.msg.Gas())
self.initialGas.Set(self.msg.Gas()) self.initialGas.Set(self.msg.Gas())
sender.SubAmount(MessageGasValue(self.msg)) sender.SubBalance(MessageGasValue(self.msg))
return nil return nil
} }
...@@ -251,7 +251,7 @@ func (self *StateTransition) RefundGas() { ...@@ -251,7 +251,7 @@ func (self *StateTransition) RefundGas() {
coinbase, sender := self.Coinbase(), self.From() coinbase, sender := self.Coinbase(), self.From()
// Return remaining gas // Return remaining gas
remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice()) 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) uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2)
for addr, ref := range self.state.Refunds() { for addr, ref := range self.state.Refunds() {
......
...@@ -148,7 +148,8 @@ func New(config *Config) (*Ethereum, error) { ...@@ -148,7 +148,8 @@ func New(config *Config) (*Ethereum, error) {
d, _ := db.Get([]byte("ProtocolVersion")) d, _ := db.Get([]byte("ProtocolVersion"))
protov := ethutil.NewValue(d).Uint() protov := ethutil.NewValue(d).Uint()
if protov != ProtocolVersion && protov != 0 { 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, "database")
return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, path)
} }
// Create new keymanager // Create new keymanager
......
...@@ -3,12 +3,50 @@ package ethutil ...@@ -3,12 +3,50 @@ package ethutil
import ( import (
"fmt" "fmt"
"math/big" "math/big"
"os"
"os/user" "os/user"
"path" "path"
"path/filepath"
"runtime" "runtime"
"time" "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 { func DefaultDataDir() string {
usr, _ := user.Current() usr, _ := user.Current()
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
......
...@@ -24,7 +24,7 @@ var jsrelogger = logger.NewLogger("JSRE") ...@@ -24,7 +24,7 @@ var jsrelogger = logger.NewLogger("JSRE")
type JSRE struct { type JSRE struct {
ethereum *eth.Ethereum ethereum *eth.Ethereum
Vm *otto.Otto Vm *otto.Otto
pipe *xeth.XEth xeth *xeth.XEth
events event.Subscription events event.Subscription
...@@ -67,7 +67,7 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE { ...@@ -67,7 +67,7 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE {
// We have to make sure that, whoever calls this, calls "Stop" // We have to make sure that, whoever calls this, calls "Stop"
go re.mainLoop() go re.mainLoop()
re.Bind("eth", &JSEthereum{re.pipe, re.Vm, ethereum}) re.Bind("eth", &JSEthereum{re.xeth, re.Vm, ethereum})
re.initStdFuncs() re.initStdFuncs()
...@@ -113,12 +113,10 @@ func (self *JSRE) mainLoop() { ...@@ -113,12 +113,10 @@ func (self *JSRE) mainLoop() {
func (self *JSRE) initStdFuncs() { func (self *JSRE) initStdFuncs() {
t, _ := self.Vm.Get("eth") t, _ := self.Vm.Get("eth")
eth := t.Object() eth := t.Object()
eth.Set("watch", self.watch) eth.Set("connect", self.connect)
eth.Set("addPeer", self.addPeer)
eth.Set("require", self.require) eth.Set("require", self.require)
eth.Set("stopMining", self.stopMining) eth.Set("stopMining", self.stopMining)
eth.Set("startMining", self.startMining) eth.Set("startMining", self.startMining)
eth.Set("execBlock", self.execBlock)
eth.Set("dump", self.dump) eth.Set("dump", self.dump)
eth.Set("export", self.export) eth.Set("export", self.export)
} }
...@@ -152,7 +150,8 @@ func (self *JSRE) dump(call otto.FunctionCall) otto.Value { ...@@ -152,7 +150,8 @@ func (self *JSRE) dump(call otto.FunctionCall) otto.Value {
} }
statedb := state.New(block.Root(), self.ethereum.Db()) statedb := state.New(block.Root(), self.ethereum.Db())
v, _ := self.Vm.ToValue(statedb.Dump())
v, _ := self.Vm.ToValue(statedb.RawDump())
return v return v
} }
...@@ -167,36 +166,7 @@ func (self *JSRE) startMining(call otto.FunctionCall) otto.Value { ...@@ -167,36 +166,7 @@ func (self *JSRE) startMining(call otto.FunctionCall) otto.Value {
return v return v
} }
// eth.watch func (self *JSRE) connect(call otto.FunctionCall) otto.Value {
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 {
nodeURL, err := call.Argument(0).ToString() nodeURL, err := call.Argument(0).ToString()
if err != nil { if err != nil {
return otto.FalseValue() return otto.FalseValue()
...@@ -222,22 +192,12 @@ func (self *JSRE) require(call otto.FunctionCall) otto.Value { ...@@ -222,22 +192,12 @@ func (self *JSRE) require(call otto.FunctionCall) otto.Value {
return t return t
} }
func (self *JSRE) execBlock(call otto.FunctionCall) otto.Value { func (self *JSRE) export(call otto.FunctionCall) otto.Value {
hash, err := call.Argument(0).ToString() if len(call.ArgumentList) == 0 {
if err != nil { fmt.Println("err: require file name")
return otto.UndefinedValue()
}
err = utils.BlockDo(self.ethereum, ethutil.Hex2Bytes(hash))
if err != nil {
fmt.Println(err)
return otto.FalseValue() return otto.FalseValue()
} }
return otto.TrueValue()
}
func (self *JSRE) export(call otto.FunctionCall) otto.Value {
fn, err := call.Argument(0).ToString() fn, err := call.Argument(0).ToString()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
......
...@@ -16,7 +16,7 @@ function pp(object) { ...@@ -16,7 +16,7 @@ function pp(object) {
str += " ]"; str += " ]";
} else if(typeof(object) === "object") { } else if(typeof(object) === "object") {
str += "{ "; str += "{ ";
var last = Object.keys(object).sort().pop() var last = Object.keys(object).pop()
for(var k in object) { for(var k in object) {
str += k + ": " + pp(object[k]); str += k + ": " + pp(object[k]);
......
...@@ -52,10 +52,5 @@ func (self *Miner) Stop() { ...@@ -52,10 +52,5 @@ func (self *Miner) Stop() {
} }
func (self *Miner) HashRate() int64 { func (self *Miner) HashRate() int64 {
var tot int64 return self.worker.HashRate()
for _, agent := range self.worker.agents {
tot += agent.Pow().GetHashrate()
}
return tot
} }
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"math/big" "math/big"
"sort" "sort"
"sync" "sync"
"time"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -111,6 +112,8 @@ func (self *worker) register(agent Agent) { ...@@ -111,6 +112,8 @@ func (self *worker) register(agent Agent) {
func (self *worker) update() { func (self *worker) update() {
events := self.mux.Subscribe(core.ChainEvent{}, core.NewMinedBlockEvent{}) events := self.mux.Subscribe(core.ChainEvent{}, core.NewMinedBlockEvent{})
timer := time.NewTicker(2 * time.Second)
out: out:
for { for {
select { select {
...@@ -129,6 +132,8 @@ out: ...@@ -129,6 +132,8 @@ out:
agent.Stop() agent.Stop()
} }
break out break out
case <-timer.C:
minerlogger.Debugln("Hash rate:", self.HashRate(), "Khash")
} }
} }
...@@ -197,7 +202,7 @@ gasLimit: ...@@ -197,7 +202,7 @@ gasLimit:
} }
self.eth.TxPool().RemoveSet(remove) self.eth.TxPool().RemoveSet(remove)
self.current.coinbase.AddAmount(core.BlockReward) self.current.coinbase.AddBalance(core.BlockReward)
self.current.state.Update(ethutil.Big0) self.current.state.Update(ethutil.Big0)
self.push() self.push()
...@@ -225,7 +230,7 @@ func (self *worker) commitUncle(uncle *types.Header) error { ...@@ -225,7 +230,7 @@ func (self *worker) commitUncle(uncle *types.Header) error {
} }
uncleAccount := self.current.state.GetAccount(uncle.Coinbase) uncleAccount := self.current.state.GetAccount(uncle.Coinbase)
uncleAccount.AddAmount(uncleReward) uncleAccount.AddBalance(uncleReward)
self.current.coinbase.AddBalance(uncleReward) self.current.coinbase.AddBalance(uncleReward)
...@@ -244,3 +249,12 @@ func (self *worker) commitTransaction(tx *types.Transaction) error { ...@@ -244,3 +249,12 @@ func (self *worker) commitTransaction(tx *types.Transaction) error {
return nil return nil
} }
func (self *worker) HashRate() int64 {
var tot int64
for _, agent := range self.agents {
tot += agent.Pow().GetHashrate()
}
return tot
}
...@@ -9,6 +9,7 @@ For each request type, define the following: ...@@ -9,6 +9,7 @@ For each request type, define the following:
package rpc package rpc
import ( import (
"fmt"
"math/big" "math/big"
"strings" "strings"
"sync" "sync"
...@@ -19,8 +20,10 @@ import ( ...@@ -19,8 +20,10 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event/filter" "github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/ui"
"github.com/ethereum/go-ethereum/xeth" "github.com/ethereum/go-ethereum/xeth"
) )
...@@ -31,7 +34,10 @@ var ( ...@@ -31,7 +34,10 @@ var (
) )
type EthereumApi struct { type EthereumApi struct {
xeth *xeth.XEth eth *xeth.XEth
xethMu sync.RWMutex
mux *event.TypeMux
quit chan struct{} quit chan struct{}
filterManager *filter.FilterManager filterManager *filter.FilterManager
...@@ -45,17 +51,21 @@ type EthereumApi struct { ...@@ -45,17 +51,21 @@ type EthereumApi struct {
register map[string][]*NewTxArgs register map[string][]*NewTxArgs
db ethutil.Database db ethutil.Database
defaultBlockAge int64
} }
func NewEthereumApi(eth *xeth.XEth) *EthereumApi { func NewEthereumApi(eth *xeth.XEth) *EthereumApi {
db, _ := ethdb.NewLDBDatabase("dapps") db, _ := ethdb.NewLDBDatabase("dapps")
api := &EthereumApi{ api := &EthereumApi{
xeth: eth, eth: eth,
mux: eth.Backend().EventMux(),
quit: make(chan struct{}), quit: make(chan struct{}),
filterManager: filter.NewFilterManager(eth.Backend().EventMux()), filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
logs: make(map[int]*logFilter), logs: make(map[int]*logFilter),
messages: make(map[int]*whisperFilter), messages: make(map[int]*whisperFilter),
db: db, db: db,
defaultBlockAge: -1,
} }
go api.filterManager.Start() go api.filterManager.Start()
go api.start() go api.start()
...@@ -63,11 +73,36 @@ func NewEthereumApi(eth *xeth.XEth) *EthereumApi { ...@@ -63,11 +73,36 @@ func NewEthereumApi(eth *xeth.XEth) *EthereumApi {
return api 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() { func (self *EthereumApi) start() {
timer := time.NewTicker(filterTickerTime) timer := time.NewTicker(filterTickerTime)
events := self.mux.Subscribe(core.ChainEvent{})
done: done:
for { for {
select { select {
case ev := <-events.Chan():
switch ev.(type) {
case core.ChainEvent:
if self.defaultBlockAge < 0 {
self.setStateByBlockNumber(self.defaultBlockAge)
}
}
case <-timer.C: case <-timer.C:
self.logMut.Lock() self.logMut.Lock()
self.messagesMut.Lock() self.messagesMut.Lock()
...@@ -80,7 +115,7 @@ done: ...@@ -80,7 +115,7 @@ done:
for id, filter := range self.messages { for id, filter := range self.messages {
if time.Since(filter.timeout) > 20*time.Second { if time.Since(filter.timeout) > 20*time.Second {
self.xeth.Whisper().Unwatch(id) self.xeth().Whisper().Unwatch(id)
delete(self.messages, id) delete(self.messages, id)
} }
} }
...@@ -128,7 +163,7 @@ func (self *EthereumApi) WatchTx(args string, reply *interface{}) error { ...@@ -128,7 +163,7 @@ func (self *EthereumApi) WatchTx(args string, reply *interface{}) error {
func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error { func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error {
var id int var id int
filter := core.NewFilter(self.xeth.Backend()) filter := core.NewFilter(self.xeth().Backend())
filter.SetOptions(toFilterOptions(args)) filter.SetOptions(toFilterOptions(args))
filter.LogsCallback = func(logs state.Logs) { filter.LogsCallback = func(logs state.Logs) {
self.logMut.Lock() self.logMut.Lock()
...@@ -153,7 +188,7 @@ func (self *EthereumApi) UninstallFilter(id int, reply *interface{}) error { ...@@ -153,7 +188,7 @@ func (self *EthereumApi) UninstallFilter(id int, reply *interface{}) error {
func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error { func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error {
var id int var id int
filter := core.NewFilter(self.xeth.Backend()) filter := core.NewFilter(self.xeth().Backend())
callback := func(block *types.Block) { callback := func(block *types.Block) {
self.logMut.Lock() self.logMut.Lock()
...@@ -198,7 +233,7 @@ func (self *EthereumApi) Logs(id int, reply *interface{}) error { ...@@ -198,7 +233,7 @@ func (self *EthereumApi) Logs(id int, reply *interface{}) error {
} }
func (self *EthereumApi) AllLogs(args *FilterOptions, 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)) filter.SetOptions(toFilterOptions(args))
*reply = toLogs(filter.Find()) *reply = toLogs(filter.Find())
...@@ -209,9 +244,9 @@ func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error ...@@ -209,9 +244,9 @@ func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error
func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *interface{}) error { func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *interface{}) error {
// This seems a bit precarious Maybe worth splitting to discrete functions // This seems a bit precarious Maybe worth splitting to discrete functions
if len(args.Hash) > 0 { if len(args.Hash) > 0 {
*reply = p.xeth.BlockByHash(args.Hash) *reply = p.xeth().BlockByHash(args.Hash)
} else { } else {
*reply = p.xeth.BlockByNumber(args.BlockNumber) *reply = p.xeth().BlockByNumber(args.BlockNumber)
} }
return nil return nil
} }
...@@ -226,18 +261,35 @@ func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error { ...@@ -226,18 +261,35 @@ func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error {
} }
// TODO if no_private_key then // TODO if no_private_key then
if _, exists := p.register[args.From]; exists { //if _, exists := p.register[args.From]; exists {
p.register[args.From] = append(p.register[args.From], args) // p.register[args.From] = append(p.register[args.From], args)
} else { //} else {
result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data) /*
*reply = result 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 return nil
} }
func (p *EthereumApi) Call(args *NewTxArgs, reply *interface{}) error { 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 { if err != nil {
return err return err
} }
...@@ -251,7 +303,7 @@ func (p *EthereumApi) PushTx(args *PushTxArgs, reply *interface{}) error { ...@@ -251,7 +303,7 @@ func (p *EthereumApi) PushTx(args *PushTxArgs, reply *interface{}) error {
if err != nil { if err != nil {
return err return err
} }
result, _ := p.xeth.PushTx(args.Tx) result, _ := p.xeth().PushTx(args.Tx)
*reply = result *reply = result
return nil return nil
} }
...@@ -262,7 +314,7 @@ func (p *EthereumApi) GetStateAt(args *GetStateArgs, reply *interface{}) error { ...@@ -262,7 +314,7 @@ func (p *EthereumApi) GetStateAt(args *GetStateArgs, reply *interface{}) error {
return err return err
} }
state := p.xeth.State().SafeGet(args.Address) state := p.xeth().State().SafeGet(args.Address)
value := state.StorageString(args.Key) value := state.StorageString(args.Key)
var hx string var hx string
...@@ -284,42 +336,55 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) err ...@@ -284,42 +336,55 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) err
return err return err
} }
*reply = p.xeth.State().SafeGet(args.Address).Storage() *reply = p.xeth().State().SafeGet(args.Address).Storage()
return nil return nil
} }
func (p *EthereumApi) GetPeerCount(reply *interface{}) error { func (p *EthereumApi) GetPeerCount(reply *interface{}) error {
*reply = p.xeth.PeerCount() *reply = p.xeth().PeerCount()
return nil return nil
} }
func (p *EthereumApi) GetIsListening(reply *interface{}) error { func (p *EthereumApi) GetIsListening(reply *interface{}) error {
*reply = p.xeth.IsListening() *reply = p.xeth().IsListening()
return nil return nil
} }
func (p *EthereumApi) GetCoinbase(reply *interface{}) error { func (p *EthereumApi) GetCoinbase(reply *interface{}) error {
*reply = p.xeth.Coinbase() *reply = p.xeth().Coinbase()
return nil return nil
} }
func (p *EthereumApi) Accounts(reply *interface{}) error { func (p *EthereumApi) Accounts(reply *interface{}) error {
*reply = p.xeth.Accounts() *reply = p.xeth().Accounts()
return nil return nil
} }
func (p *EthereumApi) GetIsMining(reply *interface{}) error { func (p *EthereumApi) GetIsMining(reply *interface{}) error {
*reply = p.xeth.IsMining() *reply = p.xeth().IsMining()
return nil return nil
} }
func (p *EthereumApi) SetMining(shouldmine bool, reply *interface{}) error { 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 return nil
} }
func (p *EthereumApi) BlockNumber(reply *interface{}) error { func (p *EthereumApi) BlockNumber(reply *interface{}) error {
*reply = p.xeth.Backend().ChainManager().CurrentBlock().Number() *reply = p.xeth().Backend().ChainManager().CurrentBlock().Number()
return nil return nil
} }
...@@ -328,7 +393,7 @@ func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *interface{}) err ...@@ -328,7 +393,7 @@ func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *interface{}) err
if err != nil { if err != nil {
return err return err
} }
*reply = p.xeth.TxCountAt(args.Address) *reply = p.xeth().TxCountAt(args.Address)
return nil return nil
} }
...@@ -337,7 +402,7 @@ func (p *EthereumApi) GetBalanceAt(args *GetBalanceArgs, reply *interface{}) err ...@@ -337,7 +402,7 @@ func (p *EthereumApi) GetBalanceAt(args *GetBalanceArgs, reply *interface{}) err
if err != nil { if err != nil {
return err return err
} }
state := p.xeth.State().SafeGet(args.Address) state := p.xeth().State().SafeGet(args.Address)
*reply = toHex(state.Balance().Bytes()) *reply = toHex(state.Balance().Bytes())
return nil return nil
} }
...@@ -347,7 +412,7 @@ func (p *EthereumApi) GetCodeAt(args *GetCodeAtArgs, reply *interface{}) error { ...@@ -347,7 +412,7 @@ func (p *EthereumApi) GetCodeAt(args *GetCodeAtArgs, reply *interface{}) error {
if err != nil { if err != nil {
return err return err
} }
*reply = p.xeth.CodeAt(args.Address) *reply = p.xeth().CodeAt(args.Address)
return nil return nil
} }
...@@ -394,7 +459,7 @@ func (p *EthereumApi) DbGet(args *DbArgs, reply *interface{}) error { ...@@ -394,7 +459,7 @@ func (p *EthereumApi) DbGet(args *DbArgs, reply *interface{}) error {
} }
func (p *EthereumApi) NewWhisperIdentity(reply *interface{}) error { func (p *EthereumApi) NewWhisperIdentity(reply *interface{}) error {
*reply = p.xeth.Whisper().NewIdentity() *reply = p.xeth().Whisper().NewIdentity()
return nil return nil
} }
...@@ -405,7 +470,7 @@ func (p *EthereumApi) NewWhisperFilter(args *xeth.Options, reply *interface{}) e ...@@ -405,7 +470,7 @@ func (p *EthereumApi) NewWhisperFilter(args *xeth.Options, reply *interface{}) e
defer p.messagesMut.Unlock() defer p.messagesMut.Unlock()
p.messages[id].add(msg) // = append(p.messages[id], msg) 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()} p.messages[id] = &whisperFilter{timeout: time.Now()}
*reply = id *reply = id
return nil return nil
...@@ -423,7 +488,7 @@ func (self *EthereumApi) MessagesChanged(id int, reply *interface{}) error { ...@@ -423,7 +488,7 @@ func (self *EthereumApi) MessagesChanged(id int, reply *interface{}) error {
} }
func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, 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 { if err != nil {
return err return err
} }
...@@ -433,12 +498,12 @@ func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{}) ...@@ -433,12 +498,12 @@ func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{})
} }
func (p *EthereumApi) HasWhisperIdentity(args string, reply *interface{}) error { func (p *EthereumApi) HasWhisperIdentity(args string, reply *interface{}) error {
*reply = p.xeth.Whisper().HasIdentity(args) *reply = p.xeth().Whisper().HasIdentity(args)
return nil return nil
} }
func (p *EthereumApi) WhisperMessages(id int, reply *interface{}) error { func (p *EthereumApi) WhisperMessages(id int, reply *interface{}) error {
*reply = p.xeth.Whisper().Messages(id) *reply = p.xeth().Whisper().Messages(id)
return nil return nil
} }
...@@ -458,6 +523,14 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error ...@@ -458,6 +523,14 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return err return err
} }
return p.SetMining(args, reply) 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": case "eth_peerCount":
return p.GetPeerCount(reply) return p.GetPeerCount(reply)
case "eth_number": case "eth_number":
...@@ -634,3 +707,28 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error ...@@ -634,3 +707,28 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
rpclogger.DebugDetailf("Reply: %T %s", reply, reply) rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
return nil return nil
} }
func (self *EthereumApi) xeth() *xeth.XEth {
self.xethMu.RLock()
defer self.xethMu.RUnlock()
return self.eth
}
func (self *EthereumApi) useState(statedb *state.StateDB) {
self.xethMu.Lock()
defer self.xethMu.Unlock()
self.eth = self.eth.UseState(statedb)
}
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)
}
...@@ -29,8 +29,8 @@ import ( ...@@ -29,8 +29,8 @@ import (
var rpchttplogger = logger.NewLogger("RPC-HTTP") var rpchttplogger = logger.NewLogger("RPC-HTTP")
var JSON rpc.JsonWrapper var JSON rpc.JsonWrapper
func NewRpcHttpServer(pipe *xeth.XEth, port int) (*RpcHttpServer, error) { func NewRpcHttpServer(pipe *xeth.XEth, address string, port int) (*RpcHttpServer, error) {
sport := fmt.Sprintf("127.0.0.1:%d", port) sport := fmt.Sprintf("%s:%d", address, port)
l, err := net.Listen("tcp", sport) l, err := net.Listen("tcp", sport)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -41,6 +41,7 @@ func NewRpcHttpServer(pipe *xeth.XEth, port int) (*RpcHttpServer, error) { ...@@ -41,6 +41,7 @@ func NewRpcHttpServer(pipe *xeth.XEth, port int) (*RpcHttpServer, error) {
quit: make(chan bool), quit: make(chan bool),
pipe: pipe, pipe: pipe,
port: port, port: port,
addr: address,
}, nil }, nil
} }
...@@ -49,6 +50,7 @@ type RpcHttpServer struct { ...@@ -49,6 +50,7 @@ type RpcHttpServer struct {
listener net.Listener listener net.Listener
pipe *xeth.XEth pipe *xeth.XEth
port int port int
addr string
} }
func (s *RpcHttpServer) exitHandler() { func (s *RpcHttpServer) exitHandler() {
...@@ -69,7 +71,7 @@ func (s *RpcHttpServer) Stop() { ...@@ -69,7 +71,7 @@ func (s *RpcHttpServer) Stop() {
} }
func (s *RpcHttpServer) Start() { 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() go s.exitHandler()
api := rpc.NewEthereumApi(s.pipe) api := rpc.NewEthereumApi(s.pipe)
......
...@@ -210,6 +210,19 @@ func (req *RpcRequest) ToBoolArgs() (bool, error) { ...@@ -210,6 +210,19 @@ func (req *RpcRequest) ToBoolArgs() (bool, error) {
return args, nil 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
}
return args, nil
}
func (req *RpcRequest) ToCompileArgs() (string, error) { func (req *RpcRequest) ToCompileArgs() (string, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return "", errArguments return "", errArguments
......
...@@ -20,7 +20,7 @@ type World struct { ...@@ -20,7 +20,7 @@ type World struct {
Accounts map[string]Account `json:"accounts"` Accounts map[string]Account `json:"accounts"`
} }
func (self *StateDB) Dump() []byte { func (self *StateDB) RawDump() World {
world := World{ world := World{
Root: ethutil.Bytes2Hex(self.trie.Root()), Root: ethutil.Bytes2Hex(self.trie.Root()),
Accounts: make(map[string]Account), Accounts: make(map[string]Account),
...@@ -35,12 +35,15 @@ func (self *StateDB) Dump() []byte { ...@@ -35,12 +35,15 @@ func (self *StateDB) Dump() []byte {
storageIt := stateObject.State.trie.Iterator() storageIt := stateObject.State.trie.Iterator()
for storageIt.Next() { 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 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 { if err != nil {
fmt.Println("dump err", err) fmt.Println("dump err", err)
} }
......
...@@ -19,6 +19,14 @@ func (self Code) String() string { ...@@ -19,6 +19,14 @@ func (self Code) String() string {
type Storage map[string]*ethutil.Value 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 { func (self Storage) Copy() Storage {
cpy := make(Storage) cpy := make(Storage)
for key, value := range self { for key, value := range self {
...@@ -119,10 +127,9 @@ func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value { ...@@ -119,10 +127,9 @@ func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value {
} }
func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) { func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) {
self.SetState(key.Bytes(), 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 return self.storage
} }
...@@ -172,20 +179,22 @@ func (c *StateObject) AddBalance(amount *big.Int) { ...@@ -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) 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) { func (c *StateObject) SubBalance(amount *big.Int) {
c.SetBalance(new(big.Int).Sub(c.balance, amount)) c.SetBalance(new(big.Int).Sub(c.balance, amount))
statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.nonce, 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) { func (c *StateObject) SetBalance(amount *big.Int) {
c.balance = amount c.balance = amount
c.dirty = true c.dirty = true
} }
func (c *StateObject) St() Storage {
return c.storage
}
// //
// Gas setters and getters // Gas setters and getters
// //
...@@ -198,7 +207,7 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error { ...@@ -198,7 +207,7 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error {
return fmt.Errorf("insufficient amount: %v, %v", c.balance, total) return fmt.Errorf("insufficient amount: %v, %v", c.balance, total)
} }
c.SubAmount(total) c.SubBalance(total)
c.dirty = true c.dirty = true
...@@ -221,7 +230,7 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error { ...@@ -221,7 +230,7 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error {
rGas := new(big.Int).Set(gas) rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price) rGas.Mul(rGas, price)
self.AddAmount(rGas) self.AddBalance(rGas)
self.dirty = true self.dirty = true
......
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)
}
...@@ -16,6 +16,8 @@ type Vm struct { ...@@ -16,6 +16,8 @@ type Vm struct {
logStr string logStr string
err error err error
// For logging
debug bool
Dbg Debugger Dbg Debugger
...@@ -32,7 +34,7 @@ func New(env Environment) *Vm { ...@@ -32,7 +34,7 @@ func New(env Environment) *Vm {
lt = LogTyDiff 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) { 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 ...@@ -664,6 +666,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
} }
addr = ref.Address() addr = ref.Address()
fmt.Printf("CREATE %X\n", addr)
stack.Push(ethutil.BigD(addr)) stack.Push(ethutil.BigD(addr))
} }
...@@ -727,7 +730,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I ...@@ -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) self.Printf(" => (%x) %v", receiver.Address()[:4], balance)
receiver.AddAmount(balance) receiver.AddBalance(balance)
statedb.Delete(context.Address()) statedb.Delete(context.Address())
fallthrough fallthrough
...@@ -828,7 +831,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo ...@@ -828,7 +831,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
// 0 => non 0 // 0 => non 0
mult = ethutil.Big3 mult = ethutil.Big3
} else if len(val) > 0 && len(y.Bytes()) == 0 { } else if len(val) > 0 && len(y.Bytes()) == 0 {
statedb.Refund(caller.Address(), GasSStoreRefund) statedb.Refund(self.env.Origin(), GasSStoreRefund)
mult = ethutil.Big0 mult = ethutil.Big0
} else { } else {
...@@ -937,18 +940,22 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, callData []byte, context * ...@@ -937,18 +940,22 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, callData []byte, context *
} }
func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine { func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine {
if self.debug {
if self.logTy == LogTyPretty { if self.logTy == LogTyPretty {
self.logStr += fmt.Sprintf(format, v...) self.logStr += fmt.Sprintf(format, v...)
} }
}
return self return self
} }
func (self *Vm) Endl() VirtualMachine { func (self *Vm) Endl() VirtualMachine {
if self.debug {
if self.logTy == LogTyPretty { if self.logTy == LogTyPretty {
vmlogger.Debugln(self.logStr) vmlogger.Debugln(self.logStr)
self.logStr = "" self.logStr = ""
} }
}
return self return self
} }
......
...@@ -4,18 +4,19 @@ import "github.com/ethereum/go-ethereum/state" ...@@ -4,18 +4,19 @@ import "github.com/ethereum/go-ethereum/state"
type State struct { type State struct {
xeth *XEth xeth *XEth
state *state.StateDB
} }
func NewState(xeth *XEth) *State { func NewState(xeth *XEth, statedb *state.StateDB) *State {
return &State{xeth} return &State{xeth, statedb}
} }
func (self *State) State() *state.StateDB { func (self *State) State() *state.StateDB {
return self.xeth.chainManager.TransState() return self.state
} }
func (self *State) Get(addr string) *Object { 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 { func (self *State) SafeGet(addr string) *Object {
...@@ -23,7 +24,7 @@ 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 { func (self *State) safeGet(addr string) *state.StateObject {
object := self.State().GetStateObject(fromHex(addr)) object := self.state.GetStateObject(fromHex(addr))
if object == nil { if object == nil {
object = state.NewStateObject(fromHex(addr), self.xeth.eth.Db()) object = state.NewStateObject(fromHex(addr), self.xeth.eth.Db())
} }
......
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/whisper" "github.com/ethereum/go-ethereum/whisper"
) )
...@@ -54,13 +55,26 @@ func New(eth Backend) *XEth { ...@@ -54,13 +55,26 @@ func New(eth Backend) *XEth {
whisper: NewWhisper(eth.Whisper()), whisper: NewWhisper(eth.Whisper()),
miner: eth.Miner(), miner: eth.Miner(),
} }
xeth.state = NewState(xeth) xeth.state = NewState(xeth, xeth.chainManager.TransState())
return xeth return xeth
} }
func (self *XEth) Backend() Backend { return self.eth } 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) State() *State { return self.state }
func (self *XEth) Whisper() *Whisper { return self.whisper } func (self *XEth) Whisper() *Whisper { return self.whisper }
func (self *XEth) Miner() *miner.Miner { return self.miner } func (self *XEth) Miner() *miner.Miner { return self.miner }
...@@ -229,7 +243,7 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st ...@@ -229,7 +243,7 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st
} }
var ( var (
statedb = self.chainManager.TransState() statedb = self.State().State() //self.chainManager.TransState()
key = self.eth.KeyManager().KeyPair() key = self.eth.KeyManager().KeyPair()
from = statedb.GetOrNewStateObject(key.Address()) from = statedb.GetOrNewStateObject(key.Address())
block = self.chainManager.CurrentBlock() block = self.chainManager.CurrentBlock()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment