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

This commit is contained in:
Paweł Bylica 2015-03-02 18:46:55 +01:00
commit 24003c76d1
47 changed files with 1246 additions and 875 deletions

View File

@ -1,8 +1,8 @@
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:

View File

@ -1,4 +1,4 @@
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
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

11
Godeps/Godeps.json generated
View File

@ -1,15 +1,10 @@
{ {
"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 @@
"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"

View File

@ -1,20 +0,0 @@
Copyright (c) 2012 Daniel Theophanes
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.

View File

@ -0,0 +1,27 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,14 @@
### Extensions to the "os" package.
## Find the current Executable and ExecutableFolder.
There is sometimes utility in finding the current executable file
that is running. This can be used for upgrading the current executable
or finding resources located relative to the executable file.
Multi-platform and supports:
* Linux
* OS X
* Windows
* Plan 9
* BSDs.

View File

@ -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()
}

View File

@ -5,16 +5,16 @@
package osext package osext
import ( import (
"syscall" "os"
"os" "strconv"
"strconv" "syscall"
) )
func executable() (string, error) { func executable() (string, error) {
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text") f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
if err != nil { if err != nil {
return "", err return "", err
} }
defer f.Close() defer f.Close()
return syscall.Fd2path(int(f.Fd())) return syscall.Fd2path(int(f.Fd()))
} }

View File

@ -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) {
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)
} }

View File

@ -34,33 +34,62 @@ 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
} }
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
} }
func (am *AccountManager) Sign(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) { func (am AccountManager) DeleteAccount(address []byte, auth string) error {
return am.keyStore.DeleteKey(address, auth)
}
func (am *AccountManager) Sign(fromAccount *Account, toSign []byte) (signature []byte, err error) {
am.mutex.RLock()
unlockedKey := am.unlockedKeys[string(fromAccount.Address)]
am.mutex.RUnlock()
if unlockedKey.Address == nil {
return nil, ErrLocked
}
signature, err = crypto.Sign(toSign, unlockedKey.PrivateKey)
return signature, err
}
func (am *AccountManager) SignLocked(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) {
key, err := am.keyStore.GetKey(fromAccount.Address, keyAuth) 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
} }
@ -76,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 {
@ -93,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()
}

View File

@ -5,16 +5,78 @@ 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"
"time"
) )
func TestAccountManager(t *testing.T) { func TestAccountManager(t *testing.T) {
ks := crypto.NewKeyStorePlain(crypto.DefaultDataDir()) 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
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)
}
}
} }

View File

@ -26,50 +26,53 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"os/user"
"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/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/vm" "github.com/ethereum/go-ethereum/vm"
) )
var ( var (
Identifier string Identifier string
KeyRing string KeyRing string
DiffTool bool DiffTool bool
DiffType string DiffType string
KeyStore string KeyStore string
StartRpc bool StartRpc bool
StartWebSockets bool StartWebSockets bool
RpcPort int RpcListenAddress string
WsPort int RpcPort int
OutboundPort string WsPort int
ShowGenesis bool OutboundPort string
AddPeer string ShowGenesis bool
MaxPeer int AddPeer string
GenAddr bool MaxPeer int
BootNodes string GenAddr bool
NodeKey *ecdsa.PrivateKey BootNodes string
NAT nat.Interface NodeKey *ecdsa.PrivateKey
SecretFile string NAT nat.Interface
ExportDir string SecretFile string
NonInteractive bool ExportDir string
Datadir string NonInteractive bool
LogFile string Datadir string
ConfigFile string LogFile string
DebugFile string ConfigFile string
LogLevel int DebugFile string
LogFormat string LogLevel int
Dump bool LogFormat string
DumpHash string Dump bool
DumpNumber int DumpHash string
VmType int DumpNumber int
ImportChain string VmType int
SHH bool ImportChain string
Dial bool SHH bool
PrintVersion bool Dial bool
PrintVersion bool
MinerThreads int
) )
// flags specific to cli client // flags specific to cli client
@ -79,12 +82,7 @@ var (
InputFile string InputFile string
) )
func defaultDataDir() string { var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
usr, _ := user.Current()
return path.Join(usr.HomeDir, ".ethereum")
}
var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
func Init() { func Init() {
// TODO: move common flag processing to cmd/util // TODO: move common flag processing to cmd/util
@ -98,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")
@ -107,7 +106,7 @@ func Init() {
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given") flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use") flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
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)")
@ -124,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 (
@ -140,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)

View File

@ -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")
@ -62,20 +62,21 @@ func main() {
utils.InitConfig(VmType, ConfigFile, Datadir, "ETH") utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
ethereum, err := eth.New(&eth.Config{ ethereum, err := eth.New(&eth.Config{
Name: p2p.MakeName(ClientIdentifier, Version), Name: p2p.MakeName(ClientIdentifier, Version),
KeyStore: KeyStore, KeyStore: KeyStore,
DataDir: Datadir, DataDir: Datadir,
LogFile: LogFile, LogFile: LogFile,
LogLevel: LogLevel, LogLevel: LogLevel,
LogFormat: LogFormat, LogFormat: LogFormat,
MaxPeers: MaxPeer, MaxPeers: MaxPeer,
Port: OutboundPort, Port: OutboundPort,
NAT: NAT, NAT: NAT,
KeyRing: KeyRing, KeyRing: KeyRing,
Shh: true, Shh: true,
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() {
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() {
} }
if StartRpc { if StartRpc {
utils.StartRpc(ethereum, RpcPort) utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
} }
if StartWebSockets { if StartWebSockets {
@ -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 {

View File

@ -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')

View File

@ -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;
@ -72,8 +74,9 @@
document.querySelector("#mining").innerHTML = eth.mining; document.querySelector("#mining").innerHTML = eth.mining;
document.querySelector("#listening").innerHTML = eth.listening; document.querySelector("#listening").innerHTML = eth.listening;
eth.watch('chain').changed(function() { eth.watch('chain').changed(function() {
document.querySelector("#number").innerHTML = eth.number; document.querySelector("#number").innerHTML = eth.number;
}); });
</script> </script>

File diff suppressed because it is too large Load Diff

View File

@ -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"
} }
} }

View File

@ -26,80 +26,48 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"os/user"
"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/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/vm" "github.com/ethereum/go-ethereum/vm"
) )
var ( var (
Identifier string Identifier string
KeyRing string KeyRing string
KeyStore string KeyStore string
StartRpc bool StartRpc bool
StartWebSockets bool StartWebSockets bool
RpcPort int RpcListenAddress string
WsPort int RpcPort int
OutboundPort string WsPort int
ShowGenesis bool OutboundPort string
AddPeer string ShowGenesis bool
MaxPeer int AddPeer string
GenAddr bool MaxPeer int
BootNodes string GenAddr bool
NodeKey *ecdsa.PrivateKey BootNodes string
NAT nat.Interface NodeKey *ecdsa.PrivateKey
SecretFile string NAT nat.Interface
ExportDir string SecretFile string
NonInteractive bool ExportDir string
Datadir string NonInteractive bool
LogFile string Datadir string
ConfigFile string LogFile string
DebugFile string ConfigFile string
LogLevel int DebugFile string
VmType int LogLevel int
MinerThreads int VmType int
MinerThreads int
) )
// flags specific to gui client // flags specific to gui client
var AssetPath string var AssetPath string
var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
//TODO: If we re-use the one defined in cmd.go the binary osx image crashes. If somebody finds out why we can dry this up.
func defaultAssetPath() string {
var assetPath string
// If the current working directory is the go-ethereum dir
// assume a debug build and use the source directory as
// asset directory.
pwd, _ := os.Getwd()
if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") {
assetPath = path.Join(pwd, "assets")
} else {
switch runtime.GOOS {
case "darwin":
// Get Binary Directory
exedir, _ := osext.ExecutableFolder()
assetPath = filepath.Join(exedir, "../Resources")
case "linux":
assetPath = "/usr/share/mist"
case "windows":
assetPath = "./assets"
default:
assetPath = "."
}
}
return assetPath
}
func defaultDataDir() string {
usr, _ := user.Current()
return path.Join(usr.HomeDir, ".ethereum")
}
var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
func Init() { func Init() {
// TODO: move common flag processing to cmd/utils // TODO: move common flag processing to cmd/utils
@ -112,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")
@ -121,12 +90,12 @@ func Init() {
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given") flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use") flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
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 (

View File

@ -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 {
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 {

View File

@ -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) {
}) })
} }
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
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 {

View File

@ -48,9 +48,8 @@ type BlockProcessor struct {
func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor { func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
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
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
// 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 {
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)
} }

View File

@ -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
} }

View File

@ -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() {
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() {

View File

@ -30,7 +30,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"os/user"
"path" "path"
) )
@ -48,12 +47,6 @@ type keyStorePlain struct {
keysDirPath string keysDirPath string
} }
// TODO: copied from cmd/ethereum/flags.go
func DefaultDataDir() string {
usr, _ := user.Current()
return path.Join(usr.HomeDir, ".ethereum")
}
func NewKeyStorePlain(path string) KeyStore2 { func NewKeyStorePlain(path string) KeyStore2 {
return &keyStorePlain{path} return &keyStorePlain{path}
} }
@ -126,8 +119,11 @@ func GetKeyAddresses(keysDirPath string) (addresses [][]byte, err error) {
} }
addresses = make([][]byte, len(fileInfos)) addresses = make([][]byte, len(fileInfos))
for i, fileInfo := range fileInfos { for i, fileInfo := range fileInfos {
addresses[i] = make([]byte, 40) address, err := hex.DecodeString(fileInfo.Name())
addresses[i] = []byte(fileInfo.Name()) if err != nil {
continue
}
addresses[i] = address
} }
return addresses, err return addresses, err
} }

View File

@ -2,12 +2,13 @@ package crypto
import ( import (
"github.com/ethereum/go-ethereum/crypto/randentropy" "github.com/ethereum/go-ethereum/crypto/randentropy"
"github.com/ethereum/go-ethereum/ethutil"
"reflect" "reflect"
"testing" "testing"
) )
func TestKeyStorePlain(t *testing.T) { func TestKeyStorePlain(t *testing.T) {
ks := NewKeyStorePlain(DefaultDataDir()) ks := NewKeyStorePlain(ethutil.DefaultDataDir())
pass := "" // not used but required by API pass := "" // not used but required by API
k1, err := ks.GenerateNewKey(randentropy.Reader, pass) k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
if err != nil { if err != nil {
@ -35,7 +36,7 @@ func TestKeyStorePlain(t *testing.T) {
} }
func TestKeyStorePassphrase(t *testing.T) { func TestKeyStorePassphrase(t *testing.T) {
ks := NewKeyStorePassphrase(DefaultDataDir()) ks := NewKeyStorePassphrase(ethutil.DefaultDataDir())
pass := "foo" pass := "foo"
k1, err := ks.GenerateNewKey(randentropy.Reader, pass) k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
if err != nil { if err != nil {
@ -61,7 +62,7 @@ func TestKeyStorePassphrase(t *testing.T) {
} }
func TestKeyStorePassphraseDecryptionFail(t *testing.T) { func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
ks := NewKeyStorePassphrase(DefaultDataDir()) ks := NewKeyStorePassphrase(ethutil.DefaultDataDir())
pass := "foo" pass := "foo"
k1, err := ks.GenerateNewKey(randentropy.Reader, pass) k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
if err != nil { if err != nil {
@ -89,7 +90,7 @@ func TestImportPreSaleKey(t *testing.T) {
// python pyethsaletool.py genwallet // python pyethsaletool.py genwallet
// with password "foo" // with password "foo"
fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}" fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}"
ks := NewKeyStorePassphrase(DefaultDataDir()) ks := NewKeyStorePassphrase(ethutil.DefaultDataDir())
pass := "foo" pass := "foo"
_, err := ImportPreSaleKey(ks, []byte(fileContent), pass) _, err := ImportPreSaleKey(ks, []byte(fileContent), pass)
if err != nil { if err != nil {

View File

@ -147,7 +147,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

View File

@ -3,10 +3,60 @@ package ethutil
import ( import (
"fmt" "fmt"
"math/big" "math/big"
"os"
"os/user"
"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 {
usr, _ := user.Current()
if runtime.GOOS == "darwin" {
return path.Join(usr.HomeDir, "Library/Ethereum")
} else if runtime.GOOS == "windows" {
return path.Join(usr.HomeDir, "AppData/Roaming/Ethereum")
} else {
return path.Join(usr.HomeDir, ".ethereum")
}
}
func IsWindows() bool { func IsWindows() bool {
return runtime.GOOS == "windows" return runtime.GOOS == "windows"
} }

View File

@ -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 {
// 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() {
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 {
} }
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 {
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 {
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)

View File

@ -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]);

View File

@ -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
} }

View File

@ -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) {
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:
agent.Stop() agent.Stop()
} }
break out break out
case <-timer.C:
minerlogger.Debugln("Hash rate:", self.HashRate(), "Khash")
} }
} }
@ -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 {
} }
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 {
return nil return nil
} }
func (self *worker) HashRate() int64 {
var tot int64
for _, agent := range self.agents {
tot += agent.Pow().GetHashrate()
}
return tot
}

View File

@ -20,18 +20,24 @@ 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"
) )
const ( var (
defaultGasPrice = "10000000000000" defaultGasPrice = big.NewInt(10000000000000)
defaultGas = "10000" defaultGas = big.NewInt(10000)
filterTickerTime = 15 * time.Second
) )
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 {
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,
quit: make(chan struct{}), mux: eth.Backend().EventMux(),
filterManager: filter.NewFilterManager(eth.Backend().EventMux()), quit: make(chan struct{}),
logs: make(map[int]*logFilter), filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
messages: make(map[int]*whisperFilter), logs: make(map[int]*logFilter),
db: db, messages: make(map[int]*whisperFilter),
db: db,
defaultBlockAge: -1,
} }
go api.filterManager.Start() go api.filterManager.Start()
go api.start() go api.start()
@ -63,6 +73,64 @@ 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() {
timer := time.NewTicker(filterTickerTime)
events := self.mux.Subscribe(core.ChainEvent{})
done:
for {
select {
case ev := <-events.Chan():
switch ev.(type) {
case core.ChainEvent:
if self.defaultBlockAge < 0 {
self.setStateByBlockNumber(self.defaultBlockAge)
}
}
case <-timer.C:
self.logMut.Lock()
self.messagesMut.Lock()
for id, filter := range self.logs {
if time.Since(filter.timeout) > 20*time.Second {
self.filterManager.UninstallFilter(id)
delete(self.logs, id)
}
}
for id, filter := range self.messages {
if time.Since(filter.timeout) > 20*time.Second {
self.xeth().Whisper().Unwatch(id)
delete(self.messages, id)
}
}
self.logMut.Unlock()
self.messagesMut.Unlock()
case <-self.quit:
break done
}
}
}
func (self *EthereumApi) stop() {
close(self.quit)
}
func (self *EthereumApi) Register(args string, reply *interface{}) error { func (self *EthereumApi) Register(args string, reply *interface{}) error {
self.regmut.Lock() self.regmut.Lock()
defer self.regmut.Unlock() defer self.regmut.Unlock()
@ -95,7 +163,7 @@ func (self *EthereumApi) WatchTx(args string, reply *interface{}) error {
func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error { 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()
@ -120,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()
@ -165,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())
@ -174,41 +242,54 @@ 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 {
err := args.requirements() // This seems a bit precarious Maybe worth splitting to discrete functions
if err != nil { if len(args.Hash) > 0 {
return err *reply = p.xeth().BlockByHash(args.Hash)
}
if args.BlockNumber > 0 {
*reply = p.xeth.BlockByNumber(args.BlockNumber)
} else { } else {
*reply = p.xeth.BlockByHash(args.Hash) *reply = p.xeth().BlockByNumber(args.BlockNumber)
} }
return nil return nil
} }
func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error { func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error {
if len(args.Gas) == 0 { if len(args.Gas) == 0 {
args.Gas = defaultGas args.Gas = defaultGas.String()
} }
if len(args.GasPrice) == 0 { if len(args.GasPrice) == 0 {
args.GasPrice = defaultGasPrice args.GasPrice = defaultGasPrice.String()
} }
// 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
} }
@ -222,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
} }
@ -233,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
@ -255,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
} }
@ -299,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
} }
@ -308,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
} }
@ -318,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
} }
@ -365,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
} }
@ -376,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
@ -394,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
} }
@ -404,17 +498,17 @@ 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
} }
func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error { func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error {
// Spec at https://github.com/ethereum/wiki/wiki/Generic-ON-RPC // Spec at https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC
rpclogger.DebugDetailf("%T %s", req.Params, req.Params) rpclogger.DebugDetailf("%T %s", req.Params, req.Params)
switch req.Method { switch req.Method {
case "eth_coinbase": case "eth_coinbase":
@ -429,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":
@ -520,7 +622,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
} }
return p.AllLogs(args, reply) return p.AllLogs(args, reply)
case "eth_gasPrice": case "eth_gasPrice":
*reply = defaultGasPrice *reply = toHex(defaultGasPrice.Bytes())
return nil return nil
case "eth_register": case "eth_register":
args, err := req.ToRegisterArgs() args, err := req.ToRegisterArgs()
@ -599,44 +701,34 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
} }
return p.WhisperMessages(args, reply) return p.WhisperMessages(args, reply)
default: default:
return NewErrorResponse(fmt.Sprintf("%v %s", ErrorNotImplemented, req.Method)) return NewErrorWithMessage(errNotImplemented, req.Method)
} }
rpclogger.DebugDetailf("Reply: %T %s", reply, reply) rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
return nil return nil
} }
var filterTickerTime = 15 * time.Second func (self *EthereumApi) xeth() *xeth.XEth {
self.xethMu.RLock()
defer self.xethMu.RUnlock()
func (self *EthereumApi) start() { return self.eth
timer := time.NewTicker(filterTickerTime) }
done:
for {
select {
case <-timer.C:
self.logMut.Lock()
self.messagesMut.Lock()
for id, filter := range self.logs {
if time.Since(filter.timeout) > 20*time.Second {
self.filterManager.UninstallFilter(id)
delete(self.logs, id)
}
}
for id, filter := range self.messages { func (self *EthereumApi) useState(statedb *state.StateDB) {
if time.Since(filter.timeout) > 20*time.Second { self.xethMu.Lock()
self.xeth.Whisper().Unwatch(id) defer self.xethMu.Unlock()
delete(self.messages, id)
} self.eth = self.eth.UseState(statedb)
} }
self.logMut.Unlock()
self.messagesMut.Unlock() func t(f ui.Frontend) {
case <-self.quit: // Call the password dialog
break done ret, err := f.Call("PasswordDialog")
} if err != nil {
fmt.Println(err)
} }
} // Get the first argument
t, _ := ret.Get(0)
func (self *EthereumApi) stop() { fmt.Println("return:", t)
close(self.quit)
} }

View File

@ -19,14 +19,7 @@ func (obj *GetBlockArgs) UnmarshalJSON(b []byte) (err error) {
obj.Hash = argstr obj.Hash = argstr
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
}
func (obj *GetBlockArgs) requirements() error {
if obj.BlockNumber == 0 && obj.Hash == "" {
return NewErrorResponse("GetBlock requires either a block 'number' or a block 'hash' as argument")
}
return nil
} }
type NewTxArgs struct { type NewTxArgs struct {
@ -64,7 +57,7 @@ func (obj *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
type PushTxArgs struct { type PushTxArgs struct {
@ -77,12 +70,12 @@ func (obj *PushTxArgs) UnmarshalJSON(b []byte) (err error) {
obj.Tx = arg0 obj.Tx = arg0
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
func (a *PushTxArgs) requirementsPushTx() error { func (a *PushTxArgs) requirementsPushTx() error {
if a.Tx == "" { if a.Tx == "" {
return NewErrorResponse("PushTx requires a 'tx' as argument") return NewErrorWithMessage(errArguments, "PushTx requires a 'tx' as argument")
} }
return nil return nil
} }
@ -93,14 +86,14 @@ type GetStorageArgs struct {
func (obj *GetStorageArgs) UnmarshalJSON(b []byte) (err error) { func (obj *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
if err = json.Unmarshal(b, &obj.Address); err != nil { if err = json.Unmarshal(b, &obj.Address); err != nil {
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
return return
} }
func (a *GetStorageArgs) requirements() error { func (a *GetStorageArgs) requirements() error {
if len(a.Address) == 0 { if len(a.Address) == 0 {
return NewErrorResponse("GetStorageAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'address' value as argument")
} }
return nil return nil
} }
@ -116,64 +109,39 @@ func (obj *GetStateArgs) UnmarshalJSON(b []byte) (err error) {
obj.Address = arg0 obj.Address = arg0
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
func (a *GetStateArgs) requirements() error { func (a *GetStateArgs) requirements() error {
if a.Address == "" { if a.Address == "" {
return NewErrorResponse("GetStorageAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'address' value as argument")
} }
if a.Key == "" { if a.Key == "" {
return NewErrorResponse("GetStorageAt requires an 'key' value as argument") return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'key' value as argument")
} }
return nil return nil
} }
type GetStorageAtRes struct {
Key string `json:"key"`
Value string `json:"value"`
}
type GetTxCountArgs struct { type GetTxCountArgs struct {
Address string `json:"address"` Address string `json:"address"`
} }
// type GetTxCountRes struct {
// Nonce int `json:"nonce"`
// }
func (obj *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) { func (obj *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
arg0 := "" arg0 := ""
if err = json.Unmarshal(b, &arg0); err == nil { if err = json.Unmarshal(b, &arg0); err == nil {
obj.Address = arg0 obj.Address = arg0
return return
} }
return NewErrorResponse("Could not determine JSON parameters") return errDecodeArgs
} }
func (a *GetTxCountArgs) requirements() error { func (a *GetTxCountArgs) requirements() error {
if a.Address == "" { if a.Address == "" {
return NewErrorResponse("GetTxCountAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetTxCountAt requires an 'address' value as argument")
} }
return nil return nil
} }
// type GetPeerCountRes struct {
// PeerCount int `json:"peerCount"`
// }
// type GetListeningRes struct {
// IsListening bool `json:"isListening"`
// }
// type GetCoinbaseRes struct {
// Coinbase string `json:"coinbase"`
// }
// type GetMiningRes struct {
// IsMining bool `json:"isMining"`
// }
type GetBalanceArgs struct { type GetBalanceArgs struct {
Address string Address string
} }
@ -184,21 +152,16 @@ func (obj *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
obj.Address = arg0 obj.Address = arg0
return return
} }
return NewErrorResponse("Could not determine JSON parameters") return errDecodeArgs
} }
func (a *GetBalanceArgs) requirements() error { func (a *GetBalanceArgs) requirements() error {
if a.Address == "" { if a.Address == "" {
return NewErrorResponse("GetBalanceAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetBalanceAt requires an 'address' value as argument")
} }
return nil return nil
} }
type BalanceRes struct {
Balance string `json:"balance"`
Address string `json:"address"`
}
type GetCodeAtArgs struct { type GetCodeAtArgs struct {
Address string Address string
} }
@ -209,12 +172,12 @@ func (obj *GetCodeAtArgs) UnmarshalJSON(b []byte) (err error) {
obj.Address = arg0 obj.Address = arg0
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
func (a *GetCodeAtArgs) requirements() error { func (a *GetCodeAtArgs) requirements() error {
if a.Address == "" { if a.Address == "" {
return NewErrorResponse("GetCodeAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetCodeAt requires an 'address' value as argument")
} }
return nil return nil
} }
@ -225,7 +188,7 @@ type Sha3Args struct {
func (obj *Sha3Args) UnmarshalJSON(b []byte) (err error) { func (obj *Sha3Args) UnmarshalJSON(b []byte) (err error) {
if err = json.Unmarshal(b, &obj.Data); err != nil { if err = json.Unmarshal(b, &obj.Data); err != nil {
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
return return
} }
@ -277,10 +240,10 @@ type DbArgs struct {
func (a *DbArgs) requirements() error { func (a *DbArgs) requirements() error {
if len(a.Database) == 0 { if len(a.Database) == 0 {
return NewErrorResponse("DbPutArgs requires an 'Database' value as argument") return NewErrorWithMessage(errArguments, "DbPutArgs requires an 'Database' value as argument")
} }
if len(a.Key) == 0 { if len(a.Key) == 0 {
return NewErrorResponse("DbPutArgs requires an 'Key' value as argument") return NewErrorWithMessage(errArguments, "DbPutArgs requires an 'Key' value as argument")
} }
return nil return nil
} }

View File

@ -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) {
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 {
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() {
} }
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)
@ -92,7 +94,7 @@ func (s *RpcHttpServer) apiHandler(api *rpc.EthereumApi) http.Handler {
reqParsed, reqerr := JSON.ParseRequestBody(req) reqParsed, reqerr := JSON.ParseRequestBody(req)
if reqerr != nil { if reqerr != nil {
jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest} jsonerr := &rpc.RpcErrorObject{-32700, "Error: Could not parse request"}
JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr}) JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
return return
} }

View File

@ -25,12 +25,11 @@ import (
"github.com/ethereum/go-ethereum/xeth" "github.com/ethereum/go-ethereum/xeth"
) )
const ( var (
ErrorArguments = "Error: Insufficient arguments" errArguments = errors.New("Error: Insufficient arguments")
ErrorNotImplemented = "Error: Method not implemented" errNotImplemented = errors.New("Error: Method not implemented")
ErrorUnknown = "Error: Unknown error" errUnknown = errors.New("Error: Unknown error")
ErrorParseRequest = "Error: Could not parse request" errDecodeArgs = errors.New("Error: Could not decode arguments")
ErrorDecodeArgs = "Error: Could not decode arguments"
) )
type RpcRequest struct { type RpcRequest struct {
@ -58,76 +57,72 @@ type RpcErrorObject struct {
// Data interface{} `json:"data"` // Data interface{} `json:"data"`
} }
func NewErrorResponse(msg string) error { func NewErrorWithMessage(err error, msg string) error {
return errors.New(msg) return fmt.Errorf("%s: %s", err.Error(), msg)
}
func NewErrorResponseWithError(msg string, err error) error {
return fmt.Errorf("%s: %v", msg, err)
} }
func (req *RpcRequest) ToSha3Args() (*Sha3Args, error) { func (req *RpcRequest) ToSha3Args() (*Sha3Args, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(Sha3Args) args := new(Sha3Args)
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
if err := json.NewDecoder(r).Decode(args); err != nil { if err := json.NewDecoder(r).Decode(args); err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs) return nil, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToGetBlockArgs() (*GetBlockArgs, error) { func (req *RpcRequest) ToGetBlockArgs() (*GetBlockArgs, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(GetBlockArgs) args := new(GetBlockArgs)
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args) err := json.NewDecoder(r).Decode(args)
if err != nil { if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs) return nil, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToNewTxArgs() (*NewTxArgs, error) { func (req *RpcRequest) ToNewTxArgs() (*NewTxArgs, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(NewTxArgs) args := new(NewTxArgs)
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args) err := json.NewDecoder(r).Decode(args)
if err != nil { if err != nil {
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToPushTxArgs() (*PushTxArgs, error) { func (req *RpcRequest) ToPushTxArgs() (*PushTxArgs, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(PushTxArgs) args := new(PushTxArgs)
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args) err := json.NewDecoder(r).Decode(args)
if err != nil { if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs) return nil, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToGetStateArgs() (*GetStateArgs, error) { func (req *RpcRequest) ToGetStateArgs() (*GetStateArgs, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(GetStateArgs) args := new(GetStateArgs)
@ -135,234 +130,241 @@ func (req *RpcRequest) ToGetStateArgs() (*GetStateArgs, error) {
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args) err := json.NewDecoder(r).Decode(args)
if err != nil { if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs) return nil, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToStorageAtArgs() (*GetStorageArgs, error) { func (req *RpcRequest) ToStorageAtArgs() (*GetStorageArgs, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(GetStorageArgs) args := new(GetStorageArgs)
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args) err := json.NewDecoder(r).Decode(args)
if err != nil { if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs) return nil, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToGetTxCountArgs() (*GetTxCountArgs, error) { func (req *RpcRequest) ToGetTxCountArgs() (*GetTxCountArgs, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(GetTxCountArgs) args := new(GetTxCountArgs)
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args) err := json.NewDecoder(r).Decode(args)
if err != nil { if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs) return nil, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToGetBalanceArgs() (*GetBalanceArgs, error) { func (req *RpcRequest) ToGetBalanceArgs() (*GetBalanceArgs, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(GetBalanceArgs) args := new(GetBalanceArgs)
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args) err := json.NewDecoder(r).Decode(args)
if err != nil { if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs) return nil, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToGetCodeAtArgs() (*GetCodeAtArgs, error) { func (req *RpcRequest) ToGetCodeAtArgs() (*GetCodeAtArgs, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(GetCodeAtArgs) args := new(GetCodeAtArgs)
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args) err := json.NewDecoder(r).Decode(args)
if err != nil { if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs) return nil, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToBoolArgs() (bool, error) { func (req *RpcRequest) ToBoolArgs() (bool, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return false, NewErrorResponse(ErrorArguments) return false, errArguments
} }
var args bool var args bool
err := json.Unmarshal(req.Params[0], &args) err := json.Unmarshal(req.Params[0], &args)
if err != nil { if err != nil {
return false, NewErrorResponse(ErrorDecodeArgs) return false, errDecodeArgs
}
return args, nil
}
func (req *RpcRequest) ToIntArgs() (int, error) {
if len(req.Params) < 1 {
return 0, errArguments
}
var args int
if err := json.Unmarshal(req.Params[0], &args); err != nil {
return 0, errArguments
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil 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 "", NewErrorResponse(ErrorArguments) return "", errArguments
} }
var args string var args string
err := json.Unmarshal(req.Params[0], &args) err := json.Unmarshal(req.Params[0], &args)
if err != nil { if err != nil {
return "", NewErrorResponse(ErrorDecodeArgs) return "", errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToFilterArgs() (*FilterOptions, error) { func (req *RpcRequest) ToFilterArgs() (*FilterOptions, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
args := new(FilterOptions) args := new(FilterOptions)
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(args) err := json.NewDecoder(r).Decode(args)
if err != nil { if err != nil {
return nil, NewErrorResponse(ErrorDecodeArgs) return nil, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToFilterStringArgs() (string, error) { func (req *RpcRequest) ToFilterStringArgs() (string, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return "", NewErrorResponse(ErrorArguments) return "", errArguments
} }
var args string var args string
err := json.Unmarshal(req.Params[0], &args) err := json.Unmarshal(req.Params[0], &args)
if err != nil { if err != nil {
return "", NewErrorResponse(ErrorDecodeArgs) return "", errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToUninstallFilterArgs() (int, error) { func (req *RpcRequest) ToUninstallFilterArgs() (int, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return 0, NewErrorResponse(ErrorArguments) return 0, errArguments
} }
var args int var args int
err := json.Unmarshal(req.Params[0], &args) err := json.Unmarshal(req.Params[0], &args)
if err != nil { if err != nil {
return 0, NewErrorResponse(ErrorDecodeArgs) return 0, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToFilterChangedArgs() (int, error) { func (req *RpcRequest) ToFilterChangedArgs() (int, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return 0, NewErrorResponse(ErrorArguments) return 0, errArguments
} }
var id int var id int
r := bytes.NewReader(req.Params[0]) r := bytes.NewReader(req.Params[0])
err := json.NewDecoder(r).Decode(&id) err := json.NewDecoder(r).Decode(&id)
if err != nil { if err != nil {
return 0, NewErrorResponse(ErrorDecodeArgs) return 0, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", id, id)
return id, nil return id, nil
} }
func (req *RpcRequest) ToDbPutArgs() (*DbArgs, error) { func (req *RpcRequest) ToDbPutArgs() (*DbArgs, error) {
if len(req.Params) < 3 { if len(req.Params) < 3 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
var args DbArgs var args DbArgs
err := json.Unmarshal(req.Params[0], &args.Database) err := json.Unmarshal(req.Params[0], &args.Database)
if err != nil { if err != nil {
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
} }
err = json.Unmarshal(req.Params[1], &args.Key) err = json.Unmarshal(req.Params[1], &args.Key)
if err != nil { if err != nil {
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
} }
err = json.Unmarshal(req.Params[2], &args.Value) err = json.Unmarshal(req.Params[2], &args.Value)
if err != nil { if err != nil {
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
} }
rpclogger.DebugDetailf("%T %v", args, args)
return &args, nil return &args, nil
} }
func (req *RpcRequest) ToDbGetArgs() (*DbArgs, error) { func (req *RpcRequest) ToDbGetArgs() (*DbArgs, error) {
if len(req.Params) < 2 { if len(req.Params) < 2 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
var args DbArgs var args DbArgs
err := json.Unmarshal(req.Params[0], &args.Database) err := json.Unmarshal(req.Params[0], &args.Database)
if err != nil { if err != nil {
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
} }
err = json.Unmarshal(req.Params[1], &args.Key) err = json.Unmarshal(req.Params[1], &args.Key)
if err != nil { if err != nil {
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
} }
rpclogger.DebugDetailf("%T %v", args, args)
return &args, nil return &args, nil
} }
func (req *RpcRequest) ToWhisperFilterArgs() (*xeth.Options, error) { func (req *RpcRequest) ToWhisperFilterArgs() (*xeth.Options, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
var args xeth.Options var args xeth.Options
err := json.Unmarshal(req.Params[0], &args) err := json.Unmarshal(req.Params[0], &args)
if err != nil { if err != nil {
return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) return nil, NewErrorWithMessage(errDecodeArgs, err.Error())
} }
rpclogger.DebugDetailf("%T %v", args, args)
return &args, nil return &args, nil
} }
func (req *RpcRequest) ToIdArgs() (int, error) { func (req *RpcRequest) ToIdArgs() (int, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return 0, NewErrorResponse(ErrorArguments) return 0, errArguments
} }
var id int var id int
err := json.Unmarshal(req.Params[0], &id) err := json.Unmarshal(req.Params[0], &id)
if err != nil { if err != nil {
return 0, NewErrorResponse(ErrorDecodeArgs) return 0, errDecodeArgs
} }
rpclogger.DebugDetailf("%T %v", id, id)
return id, nil return id, nil
} }
func (req *RpcRequest) ToWhisperPostArgs() (*WhisperMessageArgs, error) { func (req *RpcRequest) ToWhisperPostArgs() (*WhisperMessageArgs, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return nil, NewErrorResponse(ErrorArguments) return nil, errArguments
} }
var args WhisperMessageArgs var args WhisperMessageArgs
@ -370,13 +372,13 @@ func (req *RpcRequest) ToWhisperPostArgs() (*WhisperMessageArgs, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
rpclogger.DebugDetailf("%T %v", args, args)
return &args, nil return &args, nil
} }
func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) { func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return "", NewErrorResponse(ErrorArguments) return "", errArguments
} }
var args string var args string
@ -384,13 +386,13 @@ func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToRegisterArgs() (string, error) { func (req *RpcRequest) ToRegisterArgs() (string, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return "", NewErrorResponse(ErrorArguments) return "", errArguments
} }
var args string var args string
@ -398,13 +400,13 @@ func (req *RpcRequest) ToRegisterArgs() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }
func (req *RpcRequest) ToWatchTxArgs() (string, error) { func (req *RpcRequest) ToWatchTxArgs() (string, error) {
if len(req.Params) < 1 { if len(req.Params) < 1 {
return "", NewErrorResponse(ErrorArguments) return "", errArguments
} }
var args string var args string
@ -412,6 +414,6 @@ func (req *RpcRequest) ToWatchTxArgs() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
rpclogger.DebugDetailf("%T %v", args, args)
return args, nil return args, nil
} }

View File

@ -82,7 +82,7 @@ type RpcServer interface {
type Log struct { type Log struct {
Address string `json:"address"` Address string `json:"address"`
Topic []string `json:"topics"` Topic []string `json:"topic"`
Data string `json:"data"` Data string `json:"data"`
Number uint64 `json:"number"` Number uint64 `json:"number"`
} }

View File

@ -99,7 +99,7 @@ func sockHandler(api *rpc.EthereumApi) websocket.Handler {
// reqParsed, reqerr := JSON.ParseRequestBody(conn.Request()) // reqParsed, reqerr := JSON.ParseRequestBody(conn.Request())
if err := websocket.JSON.Receive(conn, &reqParsed); err != nil { if err := websocket.JSON.Receive(conn, &reqParsed); err != nil {
jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest} jsonerr := &rpc.RpcErrorObject{-32700, "Error: Could not parse request"}
JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr}) JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
continue continue
} }

View File

@ -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 {
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)
} }

View File

@ -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 {
} }
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) {
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 {
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 {
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

18
ui/frontend.go Normal file
View File

@ -0,0 +1,18 @@
package ui
// ReturnInterface is returned by the Intercom interface when a method is called
type ReturnInterface interface {
Get(i int) (interface{}, error)
Size() int
}
// Frontend is the basic interface for calling arbitrary methods on something that
// implements a front end (GUI, CLI, etc)
type Frontend interface {
// Checks whether a specific method is implemented
Supports(method string) bool
// Call calls the given method on interface it implements. This will return
// an error with errNotImplemented if the method hasn't been implemented
// and will return a ReturnInterface if it does.
Call(method string) (ReturnInterface, error)
}

View File

@ -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 {
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
} }
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
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
// 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,17 +940,21 @@ 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.logTy == LogTyPretty { if self.debug {
self.logStr += fmt.Sprintf(format, v...) if self.logTy == LogTyPretty {
self.logStr += fmt.Sprintf(format, v...)
}
} }
return self return self
} }
func (self *Vm) Endl() VirtualMachine { func (self *Vm) Endl() VirtualMachine {
if self.logTy == LogTyPretty { if self.debug {
vmlogger.Debugln(self.logStr) if self.logTy == LogTyPretty {
self.logStr = "" vmlogger.Debugln(self.logStr)
self.logStr = ""
}
} }
return self return self

View File

@ -3,19 +3,20 @@ package xeth
import "github.com/ethereum/go-ethereum/state" 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 {
} }
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())
} }

View File

@ -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 {
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) State() *State { return self.state } func (self *XEth) UseState(statedb *state.StateDB) *XEth {
xeth := &XEth{
eth: self.eth,
blockProcessor: self.blockProcessor,
chainManager: self.chainManager,
whisper: self.whisper,
miner: self.miner,
}
xeth.state = NewState(xeth, statedb)
return xeth
}
func (self *XEth) State() *State { return self.state }
func (self *XEth) Whisper() *Whisper { return self.whisper } func (self *XEth) 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
} }
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()