Merge remote-tracking branch 'upstream/develop' into evmjit
This commit is contained in:
		| @@ -1,8 +1,8 @@ | ||||
| language: go | ||||
| go: | ||||
|   - 1.4.1 | ||||
|   - 1.4.2 | ||||
| before_install: | ||||
|   - sudo add-apt-repository ppa:beineri/opt-qt54 -y | ||||
|   - sudo add-apt-repository ppa:beineri/opt-qt541 -y | ||||
|   - sudo apt-get update -qq | ||||
|   - sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine | ||||
| install: | ||||
|   | ||||
							
								
								
									
										12
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| FROM ubuntu:14.04.1 | ||||
| FROM ubuntu:14.04.2 | ||||
|  | ||||
| ## Environment setup | ||||
| ENV HOME /root | ||||
| @@ -12,22 +12,22 @@ ENV DEBIAN_FRONTEND noninteractive | ||||
| RUN apt-get update && apt-get upgrade -y | ||||
| RUN apt-get install -y git mercurial build-essential software-properties-common wget pkg-config libgmp3-dev libreadline6-dev libpcre3-dev libpcre++-dev | ||||
|  | ||||
| ## Install Qt5.4 (not required for CLI) | ||||
| # RUN add-apt-repository ppa:beineri/opt-qt54-trusty -y | ||||
| ## Install Qt5.4.1 (not required for CLI) | ||||
| # RUN add-apt-repository ppa:beineri/opt-qt541-trusty -y | ||||
| # RUN apt-get update -y | ||||
| # RUN apt-get install -y qt54quickcontrols qt54webengine mesa-common-dev libglu1-mesa-dev | ||||
| # ENV PKG_CONFIG_PATH /opt/qt54/lib/pkgconfig | ||||
|  | ||||
| # Install Golang | ||||
| RUN wget https://storage.googleapis.com/golang/go1.4.1.linux-amd64.tar.gz | ||||
| RUN wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz | ||||
| RUN tar -C /usr/local -xzf go*.tar.gz && go version | ||||
|  | ||||
| # this is a workaround, to make sure that docker's cache is invalidated whenever the git repo changes | ||||
| ADD https://api.github.com/repos/ethereum/go-ethereum/git/refs/heads/develop file_does_not_exist | ||||
|  | ||||
| ## Fetch and install go-ethereum | ||||
| RUN go get -v github.com/tools/godep | ||||
| RUN go get -v -d github.com/ethereum/go-ethereum/... | ||||
| RUN go get github.com/tools/godep | ||||
| RUN go get -d github.com/ethereum/go-ethereum/... | ||||
| WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum | ||||
| RUN git checkout develop | ||||
| RUN godep restore | ||||
|   | ||||
							
								
								
									
										11
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										11
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							| @@ -1,15 +1,10 @@ | ||||
| { | ||||
| 	"ImportPath": "github.com/ethereum/go-ethereum", | ||||
| 	"GoVersion": "go1.4.1", | ||||
| 	"GoVersion": "go1.4.2", | ||||
| 	"Packages": [ | ||||
| 		"./..." | ||||
| 	], | ||||
| 	"Deps": [ | ||||
| 		{ | ||||
| 			"ImportPath": "bitbucket.org/kardianos/osext", | ||||
| 			"Comment": "null-13", | ||||
| 			"Rev": "5d3ddcf53a508cc2f7404eaebf546ef2cb5cdb6e" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"ImportPath": "code.google.com/p/go-uuid/uuid", | ||||
| 			"Comment": "null-12", | ||||
| @@ -37,6 +32,10 @@ | ||||
| 			"ImportPath": "github.com/jackpal/go-nat-pmp", | ||||
| 			"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"ImportPath": "github.com/kardianos/osext", | ||||
| 			"Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a" | ||||
| 		}, | ||||
| 		{ | ||||
| 			"ImportPath": "github.com/obscuren/otto", | ||||
| 			"Rev": "cf13cc4228c5e5ce0fe27a7aea90bc10091c4f19" | ||||
|   | ||||
							
								
								
									
										20
									
								
								Godeps/_workspace/src/bitbucket.org/kardianos/osext/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								Godeps/_workspace/src/bitbucket.org/kardianos/osext/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -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. | ||||
							
								
								
									
										27
									
								
								Godeps/_workspace/src/github.com/kardianos/osext/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Godeps/_workspace/src/github.com/kardianos/osext/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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. | ||||
							
								
								
									
										14
									
								
								Godeps/_workspace/src/github.com/kardianos/osext/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Godeps/_workspace/src/github.com/kardianos/osext/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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. | ||||
| @@ -25,8 +25,3 @@ func ExecutableFolder() (string, error) { | ||||
| 	folder, _ := filepath.Split(p) | ||||
| 	return folder, nil | ||||
| } | ||||
| 
 | ||||
| // Depricated. Same as Executable(). | ||||
| func GetExePath() (exePath string, err error) { | ||||
| 	return Executable() | ||||
| } | ||||
| @@ -5,9 +5,9 @@ | ||||
| package osext | ||||
| 
 | ||||
| import ( | ||||
|     "syscall" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"syscall" | ||||
| ) | ||||
| 
 | ||||
| func executable() (string, error) { | ||||
| @@ -2,12 +2,13 @@ | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| // +build linux netbsd openbsd | ||||
| // +build linux netbsd openbsd solaris dragonfly | ||||
| 
 | ||||
| package osext | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| ) | ||||
| @@ -18,8 +19,10 @@ func executable() (string, error) { | ||||
| 		return os.Readlink("/proc/self/exe") | ||||
| 	case "netbsd": | ||||
| 		return os.Readlink("/proc/curproc/exe") | ||||
| 	case "openbsd": | ||||
| 	case "openbsd", "dragonfly": | ||||
| 		return os.Readlink("/proc/curproc/file") | ||||
| 	case "solaris": | ||||
| 		return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid())) | ||||
| 	} | ||||
| 	return "", errors.New("ExecPath not implemented for " + runtime.GOOS) | ||||
| } | ||||
| @@ -34,9 +34,16 @@ package accounts | ||||
|  | ||||
| import ( | ||||
| 	crand "crypto/rand" | ||||
|  | ||||
| 	"errors" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| ) | ||||
|  | ||||
| var ErrLocked = errors.New("account is locked; please request passphrase") | ||||
|  | ||||
| // TODO: better name for this struct? | ||||
| type Account struct { | ||||
| 	Address []byte | ||||
| @@ -44,23 +51,45 @@ type Account struct { | ||||
|  | ||||
| type AccountManager struct { | ||||
| 	keyStore           crypto.KeyStore2 | ||||
| 	unlockedKeys       map[string]crypto.Key | ||||
| 	unlockMilliseconds time.Duration | ||||
| 	mutex              sync.RWMutex | ||||
| } | ||||
|  | ||||
| // TODO: get key by addr - modify KeyStore2 GetKey to work with addr | ||||
|  | ||||
| // TODO: pass through passphrase for APIs which require access to private key? | ||||
| func NewAccountManager(keyStore crypto.KeyStore2) AccountManager { | ||||
| func NewAccountManager(keyStore crypto.KeyStore2, unlockMilliseconds time.Duration) AccountManager { | ||||
| 	keysMap := make(map[string]crypto.Key) | ||||
| 	am := &AccountManager{ | ||||
| 		keyStore:           keyStore, | ||||
| 		unlockedKeys:       keysMap, | ||||
| 		unlockMilliseconds: unlockMilliseconds, | ||||
| 	} | ||||
| 	return *am | ||||
| } | ||||
|  | ||||
| func (am *AccountManager) Sign(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) { | ||||
| func (am AccountManager) DeleteAccount(address []byte, auth string) error { | ||||
| 	return am.keyStore.DeleteKey(address, auth) | ||||
| } | ||||
|  | ||||
| func (am *AccountManager) Sign(fromAccount *Account, toSign []byte) (signature []byte, err error) { | ||||
| 	am.mutex.RLock() | ||||
| 	unlockedKey := am.unlockedKeys[string(fromAccount.Address)] | ||||
| 	am.mutex.RUnlock() | ||||
| 	if unlockedKey.Address == nil { | ||||
| 		return nil, ErrLocked | ||||
| 	} | ||||
| 	signature, err = crypto.Sign(toSign, unlockedKey.PrivateKey) | ||||
| 	return signature, err | ||||
| } | ||||
|  | ||||
| func (am *AccountManager) SignLocked(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) { | ||||
| 	key, err := am.keyStore.GetKey(fromAccount.Address, keyAuth) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	am.mutex.RLock() | ||||
| 	am.unlockedKeys[string(fromAccount.Address)] = *key | ||||
| 	am.mutex.RUnlock() | ||||
| 	go unlockLater(am, fromAccount.Address) | ||||
| 	signature, err = crypto.Sign(toSign, key.PrivateKey) | ||||
| 	return signature, err | ||||
| } | ||||
| @@ -76,8 +105,6 @@ func (am AccountManager) NewAccount(auth string) (*Account, error) { | ||||
| 	return ua, err | ||||
| } | ||||
|  | ||||
| // set of accounts == set of keys in given key store | ||||
| // TODO: do we need persistence of accounts as well? | ||||
| func (am *AccountManager) Accounts() ([]Account, error) { | ||||
| 	addresses, err := am.keyStore.GetKeyAddresses() | ||||
| 	if err != nil { | ||||
| @@ -93,3 +120,13 @@ func (am *AccountManager) Accounts() ([]Account, error) { | ||||
| 	} | ||||
| 	return accounts, err | ||||
| } | ||||
|  | ||||
| func unlockLater(am *AccountManager, addr []byte) { | ||||
| 	select { | ||||
| 	case <-time.After(time.Millisecond * am.unlockMilliseconds): | ||||
| 	} | ||||
| 	am.mutex.RLock() | ||||
| 	// TODO: how do we know the key is actually gone from memory? | ||||
| 	delete(am.unlockedKeys, string(addr)) | ||||
| 	am.mutex.RUnlock() | ||||
| } | ||||
|   | ||||
| @@ -5,16 +5,78 @@ import ( | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/crypto/randentropy" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| func TestAccountManager(t *testing.T) { | ||||
| 	ks := crypto.NewKeyStorePlain(crypto.DefaultDataDir()) | ||||
| 	am := NewAccountManager(ks) | ||||
| 	ks := crypto.NewKeyStorePlain(ethutil.DefaultDataDir() + "/testaccounts") | ||||
| 	am := NewAccountManager(ks, 100) | ||||
| 	pass := "" // not used but required by API | ||||
| 	a1, err := am.NewAccount(pass) | ||||
| 	toSign := randentropy.GetEntropyCSPRNG(32) | ||||
| 	_, err = am.Sign(a1, pass, toSign) | ||||
| 	_, err = am.SignLocked(a1, pass, toSign) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	// Cleanup | ||||
| 	time.Sleep(time.Millisecond * 150) // wait for locking | ||||
|  | ||||
| 	accounts, err := am.Accounts() | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	for _, account := range accounts { | ||||
| 		err := am.DeleteAccount(account.Address, pass) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestAccountManagerLocking(t *testing.T) { | ||||
| 	ks := crypto.NewKeyStorePassphrase(ethutil.DefaultDataDir() + "/testaccounts") | ||||
| 	am := NewAccountManager(ks, 200) | ||||
| 	pass := "foo" | ||||
| 	a1, err := am.NewAccount(pass) | ||||
| 	toSign := randentropy.GetEntropyCSPRNG(32) | ||||
|  | ||||
| 	// Signing without passphrase fails because account is locked | ||||
| 	_, err = am.Sign(a1, toSign) | ||||
| 	if err != ErrLocked { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	// Signing with passphrase works | ||||
| 	_, err = am.SignLocked(a1, pass, toSign) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	// Signing without passphrase works because account is temp unlocked | ||||
| 	_, err = am.Sign(a1, toSign) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	// Signing without passphrase fails after automatic locking | ||||
| 	time.Sleep(time.Millisecond * time.Duration(250)) | ||||
|  | ||||
| 	_, err = am.Sign(a1, toSign) | ||||
| 	if err != ErrLocked { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	// Cleanup | ||||
| 	accounts, err := am.Accounts() | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	for _, account := range accounts { | ||||
| 		err := am.DeleteAccount(account.Address, pass) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -26,10 +26,11 @@ import ( | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"os/user" | ||||
| 	"path" | ||||
| 	"runtime" | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/ethereum/go-ethereum/logger" | ||||
| 	"github.com/ethereum/go-ethereum/p2p/nat" | ||||
| 	"github.com/ethereum/go-ethereum/vm" | ||||
| @@ -43,6 +44,7 @@ var ( | ||||
| 	KeyStore         string | ||||
| 	StartRpc         bool | ||||
| 	StartWebSockets  bool | ||||
| 	RpcListenAddress string | ||||
| 	RpcPort          int | ||||
| 	WsPort           int | ||||
| 	OutboundPort     string | ||||
| @@ -70,6 +72,7 @@ var ( | ||||
| 	SHH              bool | ||||
| 	Dial             bool | ||||
| 	PrintVersion     bool | ||||
| 	MinerThreads     int | ||||
| ) | ||||
|  | ||||
| // flags specific to cli client | ||||
| @@ -79,12 +82,7 @@ var ( | ||||
| 	InputFile      string | ||||
| ) | ||||
|  | ||||
| func defaultDataDir() string { | ||||
| 	usr, _ := user.Current() | ||||
| 	return path.Join(usr.HomeDir, ".ethereum") | ||||
| } | ||||
|  | ||||
| var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini") | ||||
| var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini") | ||||
|  | ||||
| func Init() { | ||||
| 	// TODO: move common flag processing to cmd/util | ||||
| @@ -98,6 +96,7 @@ func Init() { | ||||
| 	flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use") | ||||
| 	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(&WsPort, "wsport", 40404, "port to start websocket rpc server on") | ||||
| 	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(&ExportDir, "export", "", "exports the session keyring to files in the directory given") | ||||
| 	flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") | ||||
| 	flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use") | ||||
| 	flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use") | ||||
| 	flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") | ||||
| 	flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") | ||||
| 	flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)") | ||||
| @@ -124,6 +123,7 @@ func Init() { | ||||
| 	flag.BoolVar(&StartMining, "mine", false, "start dagger mining") | ||||
| 	flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console") | ||||
| 	flag.BoolVar(&PrintVersion, "version", false, "prints version number") | ||||
| 	flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads") | ||||
|  | ||||
| 	// Network stuff | ||||
| 	var ( | ||||
| @@ -140,6 +140,12 @@ func Init() { | ||||
|  | ||||
| 	flag.Parse() | ||||
|  | ||||
| 	// When the javascript console is started log to a file instead | ||||
| 	// of stdout | ||||
| 	if StartJsConsole { | ||||
| 		LogFile = path.Join(Datadir, "ethereum.log") | ||||
| 	} | ||||
|  | ||||
| 	var err error | ||||
| 	if NAT, err = nat.Parse(*natstr); err != nil { | ||||
| 		log.Fatalf("-nat: %v", err) | ||||
|   | ||||
| @@ -37,7 +37,7 @@ import ( | ||||
|  | ||||
| const ( | ||||
| 	ClientIdentifier = "Ethereum(G)" | ||||
| 	Version          = "0.8.5" | ||||
| 	Version          = "0.8.6" | ||||
| ) | ||||
|  | ||||
| var clilogger = logger.NewLogger("CLI") | ||||
| @@ -76,6 +76,7 @@ func main() { | ||||
| 		Dial:         Dial, | ||||
| 		BootNodes:    BootNodes, | ||||
| 		NodeKey:      NodeKey, | ||||
| 		MinerThreads: MinerThreads, | ||||
| 	}) | ||||
|  | ||||
| 	if err != nil { | ||||
| @@ -113,10 +114,6 @@ func main() { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if StartMining { | ||||
| 		utils.StartMining(ethereum) | ||||
| 	} | ||||
|  | ||||
| 	if len(ImportChain) > 0 { | ||||
| 		start := time.Now() | ||||
| 		err := utils.ImportChain(ethereum, ImportChain) | ||||
| @@ -128,7 +125,7 @@ func main() { | ||||
| 	} | ||||
|  | ||||
| 	if StartRpc { | ||||
| 		utils.StartRpc(ethereum, RpcPort) | ||||
| 		utils.StartRpc(ethereum, RpcListenAddress, RpcPort) | ||||
| 	} | ||||
|  | ||||
| 	if StartWebSockets { | ||||
| @@ -137,6 +134,12 @@ func main() { | ||||
|  | ||||
| 	utils.StartEthereum(ethereum) | ||||
|  | ||||
| 	fmt.Printf("Welcome to the FRONTIER\n") | ||||
|  | ||||
| 	if StartMining { | ||||
| 		ethereum.Miner().Start() | ||||
| 	} | ||||
|  | ||||
| 	if StartJsConsole { | ||||
| 		InitJsConsole(ethereum) | ||||
| 	} else if len(InputFile) > 0 { | ||||
|   | ||||
| @@ -60,6 +60,7 @@ func (self *JSRepl) Start() { | ||||
| 	if !self.running { | ||||
| 		self.running = true | ||||
| 		repllogger.Infoln("init JS Console") | ||||
|  | ||||
| 		reader := bufio.NewReader(self.history) | ||||
| 		for { | ||||
| 			line, err := reader.ReadString('\n') | ||||
|   | ||||
| @@ -62,6 +62,8 @@ | ||||
|  | ||||
|     web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545')); | ||||
|  | ||||
|     eth.defaultBlock = -2 | ||||
|  | ||||
|     document.querySelector("#number").innerHTML = eth.number; | ||||
|     document.querySelector("#coinbase").innerHTML = eth.coinbase | ||||
|     document.querySelector("#peer_count").innerHTML = eth.peerCount; | ||||
| @@ -75,6 +77,7 @@ | ||||
|         document.querySelector("#number").innerHTML = eth.number; | ||||
|     }); | ||||
|  | ||||
|  | ||||
| </script> | ||||
|  | ||||
| </html> | ||||
|   | ||||
							
								
								
									
										774
									
								
								cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										774
									
								
								cmd/mist/assets/ext/ethereum.js/dist/ethereum.js
									
									
									
									
										vendored
									
									
								
							| @@ -53,7 +53,6 @@ var inputTypes = types.inputTypes(); | ||||
| /// @returns bytes representation of input params | ||||
| var formatInput = function (inputs, params) { | ||||
|     var bytes = ""; | ||||
|     var padding = c.ETH_PADDING * 2; | ||||
|  | ||||
|     /// first we iterate in search for dynamic  | ||||
|     inputs.forEach(function (input, index) { | ||||
| @@ -110,6 +109,7 @@ var formatOutput = function (outs, output) { | ||||
|     output = output.slice(dynamicPartLength); | ||||
|  | ||||
|     outs.forEach(function (out, i) { | ||||
|         /*jshint maxcomplexity:6 */ | ||||
|         var typeMatch = false; | ||||
|         for (var j = 0; j < outputTypes.length && !typeMatch; j++) { | ||||
|             typeMatch = outputTypes[j].type(outs[i].type); | ||||
| @@ -210,7 +210,7 @@ module.exports = { | ||||
| }; | ||||
|  | ||||
|  | ||||
| },{"./const":2,"./formatters":6,"./types":11,"./utils":12,"./web3":13}],2:[function(require,module,exports){ | ||||
| },{"./const":2,"./formatters":8,"./types":14,"./utils":15,"./web3":17}],2:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -264,7 +264,8 @@ module.exports = { | ||||
|     ETH_PADDING: 32, | ||||
|     ETH_SIGNATURE_LENGTH: 4, | ||||
|     ETH_UNITS: ETH_UNITS, | ||||
|     ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN } | ||||
|     ETH_BIGNUMBER_ROUNDING_MODE: { ROUNDING_MODE: BigNumber.ROUND_DOWN }, | ||||
|     ETH_POLLING_TIMEOUT: 1000 | ||||
| }; | ||||
|  | ||||
|  | ||||
| @@ -340,6 +341,7 @@ var addFunctionsToContract = function (contract, desc, address) { | ||||
|         var typeName = utils.extractTypeName(method.name); | ||||
|  | ||||
|         var impl = function () { | ||||
|             /*jshint maxcomplexity:7 */ | ||||
|             var params = Array.prototype.slice.call(arguments); | ||||
|             var signature = abi.signatureFromAscii(method.name); | ||||
|             var parsed = inputParser[displayName][typeName].apply(null, params); | ||||
| @@ -416,11 +418,11 @@ var addEventsToContract = function (contract, desc, address) { | ||||
|             var signature = abi.eventSignatureFromAscii(e.name); | ||||
|             var event = eventImpl.inputParser(address, signature, e); | ||||
|             var o = event.apply(null, params); | ||||
|             o._onWatchEventResult = function (data) { | ||||
|             var outputFormatter = function (data) { | ||||
|                 var parser = eventImpl.outputParser(e); | ||||
|                 return parser(data); | ||||
|             }; | ||||
|             return web3.eth.watch(o);   | ||||
|             return web3.eth.watch(o, undefined, undefined, outputFormatter); | ||||
|         }; | ||||
|          | ||||
|         // this property should be used by eth.filter to check if object is an event | ||||
| @@ -487,7 +489,131 @@ var contract = function (address, desc) { | ||||
| module.exports = contract; | ||||
|  | ||||
|  | ||||
| },{"./abi":1,"./event":4,"./utils":12,"./web3":13}],4:[function(require,module,exports){ | ||||
| },{"./abi":1,"./event":6,"./utils":15,"./web3":17}],4:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
|     ethereum.js is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU Lesser General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     ethereum.js is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU Lesser General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public License | ||||
|     along with ethereum.js.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
| /** @file db.js | ||||
|  * @authors: | ||||
|  *   Marek Kotewicz <marek@ethdev.com> | ||||
|  * @date 2015 | ||||
|  */ | ||||
|  | ||||
| /// @returns an array of objects describing web3.db api methods | ||||
| var methods = function () { | ||||
|     return [ | ||||
|     { name: 'put', call: 'db_put' }, | ||||
|     { name: 'get', call: 'db_get' }, | ||||
|     { name: 'putString', call: 'db_putString' }, | ||||
|     { name: 'getString', call: 'db_getString' } | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| module.exports = { | ||||
|     methods: methods | ||||
| }; | ||||
|  | ||||
| },{}],5:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
|     ethereum.js is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU Lesser General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     ethereum.js is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU Lesser General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public License | ||||
|     along with ethereum.js.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
| /** @file eth.js | ||||
|  * @authors: | ||||
|  *   Marek Kotewicz <marek@ethdev.com> | ||||
|  * @date 2015 | ||||
|  */ | ||||
|  | ||||
| /// @returns an array of objects describing web3.eth api methods | ||||
| var methods = function () { | ||||
|     var blockCall = function (args) { | ||||
|         return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; | ||||
|     }; | ||||
|  | ||||
|     var transactionCall = function (args) { | ||||
|         return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; | ||||
|     }; | ||||
|  | ||||
|     var uncleCall = function (args) { | ||||
|         return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; | ||||
|     }; | ||||
|  | ||||
|     var transactionCountCall = function (args) { | ||||
|         return typeof args[0] === "string" ? 'eth_transactionCountByHash' : 'eth_transactionCountByNumber'; | ||||
|     }; | ||||
|  | ||||
|     var uncleCountCall = function (args) { | ||||
|         return typeof args[0] === "string" ? 'eth_uncleCountByHash' : 'eth_uncleCountByNumber'; | ||||
|     }; | ||||
|  | ||||
|     return [ | ||||
|     { name: 'balanceAt', call: 'eth_balanceAt' }, | ||||
|     { name: 'stateAt', call: 'eth_stateAt' }, | ||||
|     { name: 'storageAt', call: 'eth_storageAt' }, | ||||
|     { name: 'countAt', call: 'eth_countAt'}, | ||||
|     { name: 'codeAt', call: 'eth_codeAt' }, | ||||
|     { name: 'transact', call: 'eth_transact' }, | ||||
|     { name: 'call', call: 'eth_call' }, | ||||
|     { name: 'block', call: blockCall }, | ||||
|     { name: 'transaction', call: transactionCall }, | ||||
|     { name: 'uncle', call: uncleCall }, | ||||
|     { name: 'compilers', call: 'eth_compilers' }, | ||||
|     { name: 'flush', call: 'eth_flush' }, | ||||
|     { name: 'lll', call: 'eth_lll' }, | ||||
|     { name: 'solidity', call: 'eth_solidity' }, | ||||
|     { name: 'serpent', call: 'eth_serpent' }, | ||||
|     { name: 'logs', call: 'eth_logs' }, | ||||
|     { name: 'transactionCount', call: transactionCountCall }, | ||||
|     { name: 'uncleCount', call: uncleCountCall } | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| /// @returns an array of objects describing web3.eth api properties | ||||
| var properties = function () { | ||||
|     return [ | ||||
|     { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, | ||||
|     { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' }, | ||||
|     { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' }, | ||||
|     { name: 'gasPrice', getter: 'eth_gasPrice' }, | ||||
|     { name: 'accounts', getter: 'eth_accounts' }, | ||||
|     { name: 'peerCount', getter: 'eth_peerCount' }, | ||||
|     { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, | ||||
|     { name: 'number', getter: 'eth_number'} | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| module.exports = { | ||||
|     methods: methods, | ||||
|     properties: properties | ||||
| }; | ||||
|  | ||||
|  | ||||
| },{}],6:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -571,9 +697,9 @@ var getArgumentsObject = function (inputs, indexed, notIndexed) { | ||||
|     return inputs.reduce(function (acc, current) { | ||||
|         var value; | ||||
|         if (current.indexed) | ||||
|             value = indexed.splice(0, 1)[0]; | ||||
|             value = indexedCopy.splice(0, 1)[0]; | ||||
|         else | ||||
|             value = notIndexed.splice(0, 1)[0]; | ||||
|             value = notIndexedCopy.splice(0, 1)[0]; | ||||
|  | ||||
|         acc[current.name] = value; | ||||
|         return acc; | ||||
| @@ -589,6 +715,7 @@ var outputParser = function (event) { | ||||
|             args: {} | ||||
|         }; | ||||
|  | ||||
|         output.topics = output.topic; // fallback for go-ethereum | ||||
|         if (!output.topic) { | ||||
|             return result; | ||||
|         } | ||||
| @@ -624,7 +751,7 @@ module.exports = { | ||||
| }; | ||||
|  | ||||
|  | ||||
| },{"./abi":1,"./utils":12}],5:[function(require,module,exports){ | ||||
| },{"./abi":1,"./utils":15}],7:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -650,24 +777,33 @@ module.exports = { | ||||
|  * @date 2014 | ||||
|  */ | ||||
|  | ||||
| var web3 = require('./web3'); // jshint ignore:line | ||||
| /// Should be called to check if filter implementation is valid | ||||
| /// @returns true if it is, otherwise false | ||||
| var implementationIsValid = function (i) { | ||||
|     return !!i &&  | ||||
|         typeof i.newFilter === 'function' &&  | ||||
|         typeof i.getMessages === 'function' &&  | ||||
|         typeof i.uninstallFilter === 'function' && | ||||
|         typeof i.startPolling === 'function' && | ||||
|         typeof i.stopPolling === 'function'; | ||||
| }; | ||||
|  | ||||
| /// should be used when we want to watch something | ||||
| /// it's using inner polling mechanism and is notified about changes | ||||
| /// TODO: change 'options' name cause it may be not the best matching one, since we have events | ||||
| var Filter = function(options, impl) { | ||||
|  | ||||
|     if (typeof options !== "string") { | ||||
|  | ||||
|         // topics property is deprecated, warn about it! | ||||
|         if (options.topics) { | ||||
|             console.warn('"topics" is deprecated, use "topic" instead'); | ||||
| /// This method should be called on options object, to verify deprecated properties && lazy load dynamic ones | ||||
| /// @param should be string or object | ||||
| /// @returns options string or object | ||||
| var getOptions = function (options) { | ||||
|     if (typeof options === 'string') { | ||||
|         return options; | ||||
|     }  | ||||
|  | ||||
|         this._onWatchResult = options._onWatchEventResult; | ||||
|     options = options || {}; | ||||
|  | ||||
|     if (options.topics) { | ||||
|         console.warn('"topics" is deprecated, is "topic" instead'); | ||||
|     } | ||||
|  | ||||
|     // evaluate lazy properties | ||||
|         options = { | ||||
|     return { | ||||
|         to: options.to, | ||||
|         topic: options.topic, | ||||
|         earliest: options.earliest, | ||||
| @@ -676,58 +812,61 @@ var Filter = function(options, impl) { | ||||
|         skip: options.skip, | ||||
|         address: options.address | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| /// Should be used when we want to watch something | ||||
| /// it's using inner polling mechanism and is notified about changes | ||||
| /// @param options are filter options | ||||
| /// @param implementation, an abstract polling implementation | ||||
| /// @param formatter (optional), callback function which formats output before 'real' callback  | ||||
| var filter = function(options, implementation, formatter) { | ||||
|     if (!implementationIsValid(implementation)) { | ||||
|         console.error('filter implemenation is invalid'); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     this.impl = impl; | ||||
|     this.callbacks = []; | ||||
|  | ||||
|     this.id = impl.newFilter(options); | ||||
|     web3.provider.startPolling({method: impl.changed, params: [this.id]}, this.id, this.trigger.bind(this)); | ||||
|     options = getOptions(options); | ||||
|     var callbacks = []; | ||||
|     var filterId = implementation.newFilter(options); | ||||
|     var onMessages = function (messages) { | ||||
|         messages.forEach(function (message) { | ||||
|             message = formatter ? formatter(message) : message; | ||||
|             callbacks.forEach(function (callback) { | ||||
|                 callback(message); | ||||
|             }); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
| /// alias for changed* | ||||
| Filter.prototype.arrived = function(callback) { | ||||
|     this.changed(callback); | ||||
| }; | ||||
| Filter.prototype.happened = function(callback) { | ||||
|     this.changed(callback); | ||||
|     implementation.startPolling(filterId, onMessages, implementation.uninstallFilter); | ||||
|  | ||||
|     var changed = function (callback) { | ||||
|         callbacks.push(callback); | ||||
|     }; | ||||
|  | ||||
| /// gets called when there is new eth/shh message | ||||
| Filter.prototype.changed = function(callback) { | ||||
|     this.callbacks.push(callback); | ||||
|     var messages = function () { | ||||
|         return implementation.getMessages(filterId); | ||||
|     }; | ||||
|      | ||||
| /// trigger calling new message from people | ||||
| Filter.prototype.trigger = function(messages) { | ||||
|     for (var i = 0; i < this.callbacks.length; i++) { | ||||
|         for (var j = 0; j < messages.length; j++) { | ||||
|             var message = this._onWatchResult ? this._onWatchResult(messages[j]) : messages[j]; | ||||
|             this.callbacks[i].call(this, message); | ||||
|         } | ||||
|     } | ||||
|     var uninstall = function () { | ||||
|         implementation.stopPolling(filterId); | ||||
|         implementation.uninstallFilter(filterId); | ||||
|         callbacks = []; | ||||
|     }; | ||||
|  | ||||
| /// should be called to uninstall current filter | ||||
| Filter.prototype.uninstall = function() { | ||||
|     this.impl.uninstallFilter(this.id); | ||||
|     web3.provider.stopPolling(this.id); | ||||
|     return { | ||||
|         changed: changed, | ||||
|         arrived: changed, | ||||
|         happened: changed, | ||||
|         messages: messages, | ||||
|         logs: messages, | ||||
|         uninstall: uninstall | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| /// should be called to manually trigger getting latest messages from the client | ||||
| Filter.prototype.messages = function() { | ||||
|     return this.impl.getMessages(this.id); | ||||
| }; | ||||
| module.exports = filter; | ||||
|  | ||||
| /// alias for messages | ||||
| Filter.prototype.logs = function () { | ||||
|     return this.messages(); | ||||
| }; | ||||
|  | ||||
| module.exports = Filter; | ||||
|  | ||||
| },{"./web3":13}],6:[function(require,module,exports){ | ||||
| },{}],8:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -770,6 +909,7 @@ var padLeft = function (string, chars, sign) { | ||||
| /// If the value is floating point, round it down | ||||
| /// @returns right-aligned byte representation of int | ||||
| var formatInputInt = function (value) { | ||||
|     /*jshint maxcomplexity:7 */ | ||||
|     var padding = c.ETH_PADDING * 2; | ||||
|     if (value instanceof BigNumber || typeof value === 'number') { | ||||
|         if (typeof value === 'number') | ||||
| @@ -883,7 +1023,7 @@ module.exports = { | ||||
| }; | ||||
|  | ||||
|  | ||||
| },{"./const":2,"./utils":12}],7:[function(require,module,exports){ | ||||
| },{"./const":2,"./utils":15}],9:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -923,15 +1063,17 @@ HttpSyncProvider.prototype.send = function (payload) { | ||||
|     request.open('POST', this.host, false); | ||||
|     request.send(JSON.stringify(payload)); | ||||
|  | ||||
|     // check request.status | ||||
|     var result = request.responseText; | ||||
|     // check request.status | ||||
|     if(request.status !== 200) | ||||
|         return; | ||||
|     return JSON.parse(result); | ||||
| }; | ||||
|  | ||||
| module.exports = HttpSyncProvider; | ||||
|  | ||||
|  | ||||
| },{}],8:[function(require,module,exports){ | ||||
| },{}],10:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -998,111 +1140,7 @@ module.exports = { | ||||
|  | ||||
|  | ||||
|  | ||||
| },{}],9:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
|     ethereum.js is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU Lesser General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     ethereum.js is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU Lesser General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public License | ||||
|     along with ethereum.js.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
| /** @file providermanager.js | ||||
|  * @authors: | ||||
|  *   Jeffrey Wilcke <jeff@ethdev.com> | ||||
|  *   Marek Kotewicz <marek@ethdev.com> | ||||
|  *   Marian Oancea <marian@ethdev.com> | ||||
|  *   Gav Wood <g@ethdev.com> | ||||
|  * @date 2014 | ||||
|  */ | ||||
|  | ||||
| var web3 = require('./web3');  | ||||
| var jsonrpc = require('./jsonrpc'); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Provider manager object prototype | ||||
|  * It's responsible for passing messages to providers | ||||
|  * If no provider is set it's responsible for queuing requests | ||||
|  * It's also responsible for polling the ethereum node for incoming messages | ||||
|  * Default poll timeout is 12 seconds | ||||
|  * If we are running ethereum.js inside ethereum browser, there are backend based tools responsible for polling, | ||||
|  * and provider manager polling mechanism is not used | ||||
|  */ | ||||
| var ProviderManager = function() { | ||||
|     this.polls = []; | ||||
|     this.provider = undefined; | ||||
|  | ||||
|     var self = this; | ||||
|     var poll = function () { | ||||
|         self.polls.forEach(function (data) { | ||||
|             var result = self.send(data.data); | ||||
|  | ||||
|             if (!(result instanceof Array) || result.length === 0) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             data.callback(result); | ||||
|         }); | ||||
|  | ||||
|         setTimeout(poll, 1000); | ||||
|     }; | ||||
|     poll(); | ||||
| }; | ||||
|  | ||||
| /// sends outgoing requests | ||||
| /// @params data - an object with at least 'method' property | ||||
| ProviderManager.prototype.send = function(data) { | ||||
|     var payload = jsonrpc.toPayload(data.method, data.params); | ||||
|  | ||||
|     if (this.provider === undefined) { | ||||
|         console.error('provider is not set'); | ||||
|         return null;  | ||||
|     } | ||||
|  | ||||
|     var result = this.provider.send(payload); | ||||
|  | ||||
|     if (!jsonrpc.isValidResponse(result)) { | ||||
|         console.log(result); | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     return result.result; | ||||
| }; | ||||
|  | ||||
| /// setups provider, which will be used for sending messages | ||||
| ProviderManager.prototype.set = function(provider) { | ||||
|     this.provider = provider; | ||||
| }; | ||||
|  | ||||
| /// this method is only used, when we do not have native qt bindings and have to do polling on our own | ||||
| /// should be callled, on start watching for eth/shh changes | ||||
| ProviderManager.prototype.startPolling = function (data, pollId, callback) { | ||||
|     this.polls.push({data: data, id: pollId, callback: callback}); | ||||
| }; | ||||
|  | ||||
| /// should be called to stop polling for certain watch changes | ||||
| ProviderManager.prototype.stopPolling = function (pollId) { | ||||
|     for (var i = this.polls.length; i--;) { | ||||
|         var poll = this.polls[i]; | ||||
|         if (poll.id === pollId) { | ||||
|             this.polls.splice(i, 1); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| module.exports = ProviderManager; | ||||
|  | ||||
|  | ||||
| },{"./jsonrpc":8,"./web3":13}],10:[function(require,module,exports){ | ||||
| },{}],11:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -1137,7 +1175,160 @@ QtSyncProvider.prototype.send = function (payload) { | ||||
| module.exports = QtSyncProvider; | ||||
|  | ||||
|  | ||||
| },{}],11:[function(require,module,exports){ | ||||
| },{}],12:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
|     ethereum.js is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU Lesser General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     ethereum.js is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU Lesser General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public License | ||||
|     along with ethereum.js.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
| /** @file requestmanager.js | ||||
|  * @authors: | ||||
|  *   Jeffrey Wilcke <jeff@ethdev.com> | ||||
|  *   Marek Kotewicz <marek@ethdev.com> | ||||
|  *   Marian Oancea <marian@ethdev.com> | ||||
|  *   Gav Wood <g@ethdev.com> | ||||
|  * @date 2014 | ||||
|  */ | ||||
|  | ||||
| var jsonrpc = require('./jsonrpc'); | ||||
| var c = require('./const'); | ||||
|  | ||||
| /** | ||||
|  * It's responsible for passing messages to providers | ||||
|  * It's also responsible for polling the ethereum node for incoming messages | ||||
|  * Default poll timeout is 1 second | ||||
|  */ | ||||
| var requestManager = function() { | ||||
|     var polls = []; | ||||
|     var timeout = null; | ||||
|     var provider; | ||||
|  | ||||
|     var send = function (data) { | ||||
|         var payload = jsonrpc.toPayload(data.method, data.params); | ||||
|          | ||||
|         if (!provider) { | ||||
|             console.error('provider is not set'); | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         var result = provider.send(payload); | ||||
|  | ||||
|         if (!jsonrpc.isValidResponse(result)) { | ||||
|             console.log(result); | ||||
|             return null; | ||||
|         } | ||||
|          | ||||
|         return result.result; | ||||
|     }; | ||||
|  | ||||
|     var setProvider = function (p) { | ||||
|         provider = p; | ||||
|     }; | ||||
|  | ||||
|     /*jshint maxparams:4 */ | ||||
|     var startPolling = function (data, pollId, callback, uninstall) { | ||||
|         polls.push({data: data, id: pollId, callback: callback, uninstall: uninstall}); | ||||
|     }; | ||||
|     /*jshint maxparams:3 */ | ||||
|  | ||||
|     var stopPolling = function (pollId) { | ||||
|         for (var i = polls.length; i--;) { | ||||
|             var poll = polls[i]; | ||||
|             if (poll.id === pollId) { | ||||
|                 polls.splice(i, 1); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     var reset = function () { | ||||
|         polls.forEach(function (poll) { | ||||
|             poll.uninstall(poll.id);  | ||||
|         }); | ||||
|         polls = []; | ||||
|  | ||||
|         if (timeout) { | ||||
|             clearTimeout(timeout); | ||||
|             timeout = null; | ||||
|         } | ||||
|         poll(); | ||||
|     }; | ||||
|  | ||||
|     var poll = function () { | ||||
|         polls.forEach(function (data) { | ||||
|             var result = send(data.data); | ||||
|             if (!(result instanceof Array) || result.length === 0) { | ||||
|                 return; | ||||
|             } | ||||
|             data.callback(result); | ||||
|         }); | ||||
|         timeout = setTimeout(poll, c.ETH_POLLING_TIMEOUT); | ||||
|     }; | ||||
|      | ||||
|     poll(); | ||||
|  | ||||
|     return { | ||||
|         send: send, | ||||
|         setProvider: setProvider, | ||||
|         startPolling: startPolling, | ||||
|         stopPolling: stopPolling, | ||||
|         reset: reset | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| module.exports = requestManager; | ||||
|  | ||||
|  | ||||
| },{"./const":2,"./jsonrpc":10}],13:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
|     ethereum.js is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU Lesser General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     ethereum.js is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU Lesser General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public License | ||||
|     along with ethereum.js.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
| /** @file shh.js | ||||
|  * @authors: | ||||
|  *   Marek Kotewicz <marek@ethdev.com> | ||||
|  * @date 2015 | ||||
|  */ | ||||
|  | ||||
| /// @returns an array of objects describing web3.shh api methods | ||||
| var methods = function () { | ||||
|     return [ | ||||
|     { name: 'post', call: 'shh_post' }, | ||||
|     { name: 'newIdentity', call: 'shh_newIdentity' }, | ||||
|     { name: 'haveIdentity', call: 'shh_haveIdentity' }, | ||||
|     { name: 'newGroup', call: 'shh_newGroup' }, | ||||
|     { name: 'addToGroup', call: 'shh_addToGroup' } | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| module.exports = { | ||||
|     methods: methods | ||||
| }; | ||||
|  | ||||
|  | ||||
| },{}],14:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -1218,7 +1409,7 @@ module.exports = { | ||||
| }; | ||||
|  | ||||
|  | ||||
| },{"./formatters":6}],12:[function(require,module,exports){ | ||||
| },{"./formatters":8}],15:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -1328,6 +1519,7 @@ var filterEvents = function (json) { | ||||
| /// TODO: use BigNumber.js to parse int | ||||
| /// TODO: add tests for it! | ||||
| var toEth = function (str) { | ||||
|      /*jshint maxcomplexity:7 */ | ||||
|     var val = typeof str === "string" ? str.indexOf('0x') === 0 ? parseInt(str.substr(2), 16) : parseInt(str) : str; | ||||
|     var unit = 0; | ||||
|     var units = c.ETH_UNITS; | ||||
| @@ -1362,7 +1554,58 @@ module.exports = { | ||||
| }; | ||||
|  | ||||
|  | ||||
| },{"./const":2}],13:[function(require,module,exports){ | ||||
| },{"./const":2}],16:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
|     ethereum.js is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU Lesser General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     ethereum.js is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU Lesser General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public License | ||||
|     along with ethereum.js.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
| /** @file watches.js | ||||
|  * @authors: | ||||
|  *   Marek Kotewicz <marek@ethdev.com> | ||||
|  * @date 2015 | ||||
|  */ | ||||
|  | ||||
| /// @returns an array of objects describing web3.eth.watch api methods | ||||
| var eth = function () { | ||||
|     var newFilter = function (args) { | ||||
|         return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; | ||||
|     }; | ||||
|  | ||||
|     return [ | ||||
|     { name: 'newFilter', call: newFilter }, | ||||
|     { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, | ||||
|     { name: 'getMessages', call: 'eth_filterLogs' } | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| /// @returns an array of objects describing web3.shh.watch api methods | ||||
| var shh = function () { | ||||
|     return [ | ||||
|     { name: 'newFilter', call: 'shh_newFilter' }, | ||||
|     { name: 'uninstallFilter', call: 'shh_uninstallFilter' }, | ||||
|     { name: 'getMessages', call: 'shh_getMessages' } | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| module.exports = { | ||||
|     eth: eth, | ||||
|     shh: shh | ||||
| }; | ||||
|  | ||||
|  | ||||
| },{}],17:[function(require,module,exports){ | ||||
| /* | ||||
|     This file is part of ethereum.js. | ||||
|  | ||||
| @@ -1392,7 +1635,13 @@ if ("build" !== 'build') {/* | ||||
|     var BigNumber = require('bignumber.js'); | ||||
| */} | ||||
|  | ||||
| var eth = require('./eth'); | ||||
| var db = require('./db'); | ||||
| var shh = require('./shh'); | ||||
| var watches = require('./watches'); | ||||
| var filter = require('./filter'); | ||||
| var utils = require('./utils'); | ||||
| var requestManager = require('./requestmanager'); | ||||
|  | ||||
| /// @returns an array of objects describing web3 api methods | ||||
| var web3Methods = function () { | ||||
| @@ -1401,100 +1650,6 @@ var web3Methods = function () { | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| /// @returns an array of objects describing web3.eth api methods | ||||
| var ethMethods = function () { | ||||
|     var blockCall = function (args) { | ||||
|         return typeof args[0] === "string" ? "eth_blockByHash" : "eth_blockByNumber"; | ||||
|     }; | ||||
|  | ||||
|     var transactionCall = function (args) { | ||||
|         return typeof args[0] === "string" ? 'eth_transactionByHash' : 'eth_transactionByNumber'; | ||||
|     }; | ||||
|  | ||||
|     var uncleCall = function (args) { | ||||
|         return typeof args[0] === "string" ? 'eth_uncleByHash' : 'eth_uncleByNumber'; | ||||
|     }; | ||||
|  | ||||
|     var methods = [ | ||||
|     { name: 'balanceAt', call: 'eth_balanceAt' }, | ||||
|     { name: 'register', call: 'eth_register' }, | ||||
|     { name: 'unregister', call: 'eth_unregister' }, | ||||
|     { name: 'stateAt', call: 'eth_stateAt' }, | ||||
|     { name: 'storageAt', call: 'eth_storageAt' }, | ||||
|     { name: 'countAt', call: 'eth_countAt'}, | ||||
|     { name: 'codeAt', call: 'eth_codeAt' }, | ||||
|     { name: 'transact', call: 'eth_transact' }, | ||||
|     { name: 'call', call: 'eth_call' }, | ||||
|     { name: 'block', call: blockCall }, | ||||
|     { name: 'transaction', call: transactionCall }, | ||||
|     { name: 'uncle', call: uncleCall }, | ||||
|     { name: 'compilers', call: 'eth_compilers' }, | ||||
|     { name: 'flush', call: 'eth_flush' }, | ||||
|     { name: 'lll', call: 'eth_lll' }, | ||||
|     { name: 'solidity', call: 'eth_solidity' }, | ||||
|     { name: 'serpent', call: 'eth_serpent' }, | ||||
|     { name: 'logs', call: 'eth_logs' } | ||||
|     ]; | ||||
|     return methods; | ||||
| }; | ||||
|  | ||||
| /// @returns an array of objects describing web3.eth api properties | ||||
| var ethProperties = function () { | ||||
|     return [ | ||||
|     { name: 'coinbase', getter: 'eth_coinbase', setter: 'eth_setCoinbase' }, | ||||
|     { name: 'listening', getter: 'eth_listening', setter: 'eth_setListening' }, | ||||
|     { name: 'mining', getter: 'eth_mining', setter: 'eth_setMining' }, | ||||
|     { name: 'gasPrice', getter: 'eth_gasPrice' }, | ||||
|     { name: 'accounts', getter: 'eth_accounts' }, | ||||
|     { name: 'peerCount', getter: 'eth_peerCount' }, | ||||
|     { name: 'defaultBlock', getter: 'eth_defaultBlock', setter: 'eth_setDefaultBlock' }, | ||||
|     { name: 'number', getter: 'eth_number'} | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| /// @returns an array of objects describing web3.db api methods | ||||
| var dbMethods = function () { | ||||
|     return [ | ||||
|     { name: 'put', call: 'db_put' }, | ||||
|     { name: 'get', call: 'db_get' }, | ||||
|     { name: 'putString', call: 'db_putString' }, | ||||
|     { name: 'getString', call: 'db_getString' } | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| /// @returns an array of objects describing web3.shh api methods | ||||
| var shhMethods = function () { | ||||
|     return [ | ||||
|     { name: 'post', call: 'shh_post' }, | ||||
|     { name: 'newIdentity', call: 'shh_newIdentity' }, | ||||
|     { name: 'haveIdentity', call: 'shh_haveIdentity' }, | ||||
|     { name: 'newGroup', call: 'shh_newGroup' }, | ||||
|     { name: 'addToGroup', call: 'shh_addToGroup' } | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| /// @returns an array of objects describing web3.eth.watch api methods | ||||
| var ethWatchMethods = function () { | ||||
|     var newFilter = function (args) { | ||||
|         return typeof args[0] === 'string' ? 'eth_newFilterString' : 'eth_newFilter'; | ||||
|     }; | ||||
|  | ||||
|     return [ | ||||
|     { name: 'newFilter', call: newFilter }, | ||||
|     { name: 'uninstallFilter', call: 'eth_uninstallFilter' }, | ||||
|     { name: 'getMessages', call: 'eth_filterLogs' } | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| /// @returns an array of objects describing web3.shh.watch api methods | ||||
| var shhWatchMethods = function () { | ||||
|     return [ | ||||
|     { name: 'newFilter', call: 'shh_newFilter' }, | ||||
|     { name: 'uninstallFilter', call: 'shh_uninstallFilter' }, | ||||
|     { name: 'getMessages', call: 'shh_getMessages' } | ||||
|     ]; | ||||
| }; | ||||
|  | ||||
| /// creates methods in a given object based on method description on input | ||||
| /// setups api calls for these methods | ||||
| var setupMethods = function (obj, methods) { | ||||
| @@ -1502,7 +1657,7 @@ var setupMethods = function (obj, methods) { | ||||
|         obj[method.name] = function () { | ||||
|             var args = Array.prototype.slice.call(arguments); | ||||
|             var call = typeof method.call === 'function' ? method.call(args) : method.call; | ||||
|             return web3.provider.send({ | ||||
|             return web3.manager.send({ | ||||
|                 method: call, | ||||
|                 params: args | ||||
|             }); | ||||
| @@ -1516,14 +1671,14 @@ var setupProperties = function (obj, properties) { | ||||
|     properties.forEach(function (property) { | ||||
|         var proto = {}; | ||||
|         proto.get = function () { | ||||
|             return web3.provider.send({ | ||||
|             return web3.manager.send({ | ||||
|                 method: property.getter | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         if (property.setter) { | ||||
|             proto.set = function (val) { | ||||
|                 return web3.provider.send({ | ||||
|                 return web3.manager.send({ | ||||
|                     method: property.setter, | ||||
|                     params: [val] | ||||
|                 }); | ||||
| @@ -1533,10 +1688,32 @@ var setupProperties = function (obj, properties) { | ||||
|     }); | ||||
| }; | ||||
|  | ||||
| /*jshint maxparams:4 */ | ||||
| var startPolling = function (method, id, callback, uninstall) { | ||||
|     web3.manager.startPolling({ | ||||
|         method: method,  | ||||
|         params: [id] | ||||
|     }, id,  callback, uninstall);  | ||||
| }; | ||||
| /*jshint maxparams:3 */ | ||||
|  | ||||
| var stopPolling = function (id) { | ||||
|     web3.manager.stopPolling(id); | ||||
| }; | ||||
|  | ||||
| var ethWatch = { | ||||
|     startPolling: startPolling.bind(null, 'eth_changed'),  | ||||
|     stopPolling: stopPolling | ||||
| }; | ||||
|  | ||||
| var shhWatch = { | ||||
|     startPolling: startPolling.bind(null, 'shh_changed'),  | ||||
|     stopPolling: stopPolling | ||||
| }; | ||||
|  | ||||
| /// setups web3 object, and it's in-browser executed methods | ||||
| var web3 = { | ||||
|     _callbacks: {}, | ||||
|     _events: {}, | ||||
|     manager: requestManager(), | ||||
|     providers: {}, | ||||
|  | ||||
|     /// @returns ascii string representation of hex value prefixed with 0x | ||||
| @@ -1575,12 +1752,15 @@ var web3 = { | ||||
|         /// @param filter may be a string, object or event | ||||
|         /// @param indexed is optional, this is an object with optional event indexed params | ||||
|         /// @param options is optional, this is an object with optional event options ('max'...) | ||||
|         watch: function (filter, indexed, options) { | ||||
|             if (filter._isEvent) { | ||||
|                 return filter(indexed, options); | ||||
|         /// TODO: fix it, 4 params? no way | ||||
|         /*jshint maxparams:4 */ | ||||
|         watch: function (fil, indexed, options, formatter) { | ||||
|             if (fil._isEvent) { | ||||
|                 return fil(indexed, options); | ||||
|             } | ||||
|             return new web3.filter(filter, ethWatch); | ||||
|             return filter(fil, ethWatch, formatter); | ||||
|         } | ||||
|         /*jshint maxparams:3 */ | ||||
|     }, | ||||
|  | ||||
|     /// db object prototype | ||||
| @@ -1588,54 +1768,44 @@ var web3 = { | ||||
|  | ||||
|     /// shh object prototype | ||||
|     shh: { | ||||
|          | ||||
|         /// @param filter may be a string, object or event | ||||
|         watch: function (filter, indexed) { | ||||
|             return new web3.filter(filter, shhWatch); | ||||
|         watch: function (fil) { | ||||
|             return filter(fil, shhWatch); | ||||
|         } | ||||
|     }, | ||||
|     setProvider: function (provider) { | ||||
|         web3.manager.setProvider(provider); | ||||
|     }, | ||||
|      | ||||
|     /// Should be called to reset state of web3 object | ||||
|     /// Resets everything except manager | ||||
|     reset: function () { | ||||
|         web3.manager.reset();  | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /// setups all api methods | ||||
| setupMethods(web3, web3Methods()); | ||||
| setupMethods(web3.eth, ethMethods()); | ||||
| setupProperties(web3.eth, ethProperties()); | ||||
| setupMethods(web3.db, dbMethods()); | ||||
| setupMethods(web3.shh, shhMethods()); | ||||
|  | ||||
| var ethWatch = { | ||||
|     changed: 'eth_changed' | ||||
| }; | ||||
|  | ||||
| setupMethods(ethWatch, ethWatchMethods()); | ||||
|  | ||||
| var shhWatch = { | ||||
|     changed: 'shh_changed' | ||||
| }; | ||||
|  | ||||
| setupMethods(shhWatch, shhWatchMethods()); | ||||
|  | ||||
| web3.setProvider = function(provider) { | ||||
|     web3.provider.set(provider); | ||||
| }; | ||||
| setupMethods(web3.eth, eth.methods()); | ||||
| setupProperties(web3.eth, eth.properties()); | ||||
| setupMethods(web3.db, db.methods()); | ||||
| setupMethods(web3.shh, shh.methods()); | ||||
| setupMethods(ethWatch, watches.eth()); | ||||
| setupMethods(shhWatch, watches.shh()); | ||||
|  | ||||
| module.exports = web3; | ||||
|  | ||||
|  | ||||
| },{"./utils":12}],"web3":[function(require,module,exports){ | ||||
| },{"./db":4,"./eth":5,"./filter":7,"./requestmanager":12,"./shh":13,"./utils":15,"./watches":16}],"web3":[function(require,module,exports){ | ||||
| var web3 = require('./lib/web3'); | ||||
| var ProviderManager = require('./lib/providermanager'); | ||||
| web3.provider = new ProviderManager(); | ||||
| web3.filter = require('./lib/filter'); | ||||
| web3.providers.HttpSyncProvider = require('./lib/httpsync'); | ||||
| web3.providers.QtSyncProvider = require('./lib/qtsync'); | ||||
| web3.eth.contract = require('./lib/contract'); | ||||
| web3.abi = require('./lib/abi'); | ||||
|  | ||||
|  | ||||
| module.exports = web3; | ||||
|  | ||||
| },{"./lib/abi":1,"./lib/contract":3,"./lib/filter":5,"./lib/httpsync":7,"./lib/providermanager":9,"./lib/qtsync":10,"./lib/web3":13}]},{},["web3"]) | ||||
| },{"./lib/abi":1,"./lib/contract":3,"./lib/httpsync":9,"./lib/qtsync":11,"./lib/web3":17}]},{},["web3"]) | ||||
|  | ||||
|  | ||||
| //# sourceMappingURL=ethereum.js.map | ||||
|   | ||||
| @@ -964,7 +964,7 @@ ApplicationWindow { | ||||
|                  anchors.top: parent.top | ||||
|                  anchors.topMargin: 30 | ||||
|                  font.pointSize: 12 | ||||
|                  text: "<h2>Mist (0.8.5)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br>Gustav Simonsson<br><h3>UX/UI</h3>Alex van de Sande<br>Fabian Vogelsteller" | ||||
|                  text: "<h2>Mist (0.8.6)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br>Gustav Simonsson<br><h3>UX/UI</h3>Alex van de Sande<br>Fabian Vogelsteller" | ||||
|              } | ||||
|          } | ||||
|  | ||||
|   | ||||
| @@ -26,13 +26,11 @@ import ( | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"os/user" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
|  | ||||
| 	"bitbucket.org/kardianos/osext" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/ethereum/go-ethereum/logger" | ||||
| 	"github.com/ethereum/go-ethereum/p2p/nat" | ||||
| 	"github.com/ethereum/go-ethereum/vm" | ||||
| @@ -44,6 +42,7 @@ var ( | ||||
| 	KeyStore         string | ||||
| 	StartRpc         bool | ||||
| 	StartWebSockets  bool | ||||
| 	RpcListenAddress string | ||||
| 	RpcPort          int | ||||
| 	WsPort           int | ||||
| 	OutboundPort     string | ||||
| @@ -68,38 +67,7 @@ var ( | ||||
|  | ||||
| // flags specific to gui client | ||||
| var AssetPath string | ||||
|  | ||||
| //TODO: If we re-use the one defined in cmd.go the binary osx image crashes. If somebody finds out why we can dry this up. | ||||
| func defaultAssetPath() string { | ||||
| 	var assetPath string | ||||
| 	// If the current working directory is the go-ethereum dir | ||||
| 	// assume a debug build and use the source directory as | ||||
| 	// asset directory. | ||||
| 	pwd, _ := os.Getwd() | ||||
| 	if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") { | ||||
| 		assetPath = path.Join(pwd, "assets") | ||||
| 	} else { | ||||
| 		switch runtime.GOOS { | ||||
| 		case "darwin": | ||||
| 			// Get Binary Directory | ||||
| 			exedir, _ := osext.ExecutableFolder() | ||||
| 			assetPath = filepath.Join(exedir, "../Resources") | ||||
| 		case "linux": | ||||
| 			assetPath = "/usr/share/mist" | ||||
| 		case "windows": | ||||
| 			assetPath = "./assets" | ||||
| 		default: | ||||
| 			assetPath = "." | ||||
| 		} | ||||
| 	} | ||||
| 	return assetPath | ||||
| } | ||||
| func defaultDataDir() string { | ||||
| 	usr, _ := user.Current() | ||||
| 	return path.Join(usr.HomeDir, ".ethereum") | ||||
| } | ||||
|  | ||||
| var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini") | ||||
| var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini") | ||||
|  | ||||
| func Init() { | ||||
| 	// TODO: move common flag processing to cmd/utils | ||||
| @@ -112,6 +80,7 @@ func Init() { | ||||
| 	flag.StringVar(&Identifier, "id", "", "Custom client identifier") | ||||
| 	flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use") | ||||
| 	flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)") | ||||
| 	flag.StringVar(&RpcListenAddress, "rpcaddr", "127.0.0.1", "address for json-rpc server to listen on") | ||||
| 	flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on") | ||||
| 	flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on") | ||||
| 	flag.BoolVar(&StartRpc, "rpc", true, "start rpc server") | ||||
| @@ -121,12 +90,12 @@ func Init() { | ||||
| 	flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") | ||||
| 	flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given") | ||||
| 	flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") | ||||
| 	flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use") | ||||
| 	flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use") | ||||
| 	flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") | ||||
| 	flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") | ||||
| 	flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)") | ||||
|  | ||||
| 	flag.StringVar(&AssetPath, "asset_path", defaultAssetPath(), "absolute path to GUI assets directory") | ||||
| 	flag.StringVar(&AssetPath, "asset_path", ethutil.DefaultAssetPath(), "absolute path to GUI assets directory") | ||||
|  | ||||
| 	// Network stuff | ||||
| 	var ( | ||||
|   | ||||
| @@ -36,7 +36,7 @@ import ( | ||||
|  | ||||
| const ( | ||||
| 	ClientIdentifier = "Mist" | ||||
| 	Version          = "0.8.5" | ||||
| 	Version          = "0.8.6" | ||||
| ) | ||||
|  | ||||
| var ethereum *eth.Ethereum | ||||
| @@ -73,7 +73,7 @@ func run() error { | ||||
| 	utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive) | ||||
|  | ||||
| 	if StartRpc { | ||||
| 		utils.StartRpc(ethereum, RpcPort) | ||||
| 		utils.StartRpc(ethereum, RpcListenAddress, RpcPort) | ||||
| 	} | ||||
|  | ||||
| 	if StartWebSockets { | ||||
|   | ||||
| @@ -25,12 +25,8 @@ import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/signal" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 	"regexp" | ||||
| 	"runtime" | ||||
|  | ||||
| 	"bitbucket.org/kardianos/osext" | ||||
| 	"github.com/ethereum/go-ethereum/core/types" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/eth" | ||||
| @@ -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) { | ||||
|  | ||||
| 	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()) | ||||
| } | ||||
|  | ||||
| func StartRpc(ethereum *eth.Ethereum, RpcPort int) { | ||||
| func StartRpc(ethereum *eth.Ethereum, RpcListenAddress string, RpcPort int) { | ||||
| 	var err error | ||||
| 	ethereum.RpcServer, err = rpchttp.NewRpcHttpServer(xeth.New(ethereum), RpcPort) | ||||
| 	ethereum.RpcServer, err = rpchttp.NewRpcHttpServer(xeth.New(ethereum), RpcListenAddress, RpcPort) | ||||
| 	if err != nil { | ||||
| 		clilogger.Errorf("Could not start RPC interface (port %v): %v", RpcPort, err) | ||||
| 	} else { | ||||
|   | ||||
| @@ -50,7 +50,6 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM | ||||
| 	sm := &BlockProcessor{ | ||||
| 		db:       db, | ||||
| 		mem:      make(map[string]*big.Int), | ||||
| 		//Pow:      ðash.Ethash{}, | ||||
| 		Pow:      ezp.New(), | ||||
| 		bc:       chainManager, | ||||
| 		eventMux: eventMux, | ||||
| @@ -62,7 +61,7 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM | ||||
|  | ||||
| func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) { | ||||
| 	coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase) | ||||
| 	coinbase.SetGasPool(CalcGasLimit(parent, block)) | ||||
| 	coinbase.SetGasPool(block.Header().GasLimit) | ||||
|  | ||||
| 	// Process the transactions on to parent state | ||||
| 	receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess) | ||||
| @@ -100,7 +99,8 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated | ||||
| 	// Notify all subscribers | ||||
| 	if !transientProcess { | ||||
| 		go self.eventMux.Post(TxPostEvent{tx}) | ||||
| 		go self.eventMux.Post(statedb.Logs()) | ||||
| 		logs := statedb.Logs() | ||||
| 		go self.eventMux.Post(logs) | ||||
| 	} | ||||
|  | ||||
| 	return receipt, txGas, err | ||||
| @@ -247,6 +247,11 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { | ||||
| 		return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd) | ||||
| 	} | ||||
|  | ||||
| 	expl := CalcGasLimit(parent, block) | ||||
| 	if expl.Cmp(block.Header().GasLimit) != 0 { | ||||
| 		return fmt.Errorf("GasLimit check failed for block %v, %v", block.Header().GasLimit, expl) | ||||
| 	} | ||||
|  | ||||
| 	if block.Time() < parent.Time() { | ||||
| 		return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time) | ||||
| 	} | ||||
|   | ||||
| @@ -51,8 +51,6 @@ func GenesisBlock(db ethutil.Database) *types.Block { | ||||
| 	statedb.Sync() | ||||
| 	genesis.Header().Root = statedb.Root() | ||||
|  | ||||
| 	fmt.Printf("+++ genesis +++\nRoot: %x\nHash: %x\n", genesis.Header().Root, genesis.Hash()) | ||||
|  | ||||
| 	return genesis | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -126,7 +126,7 @@ func (self *StateTransition) BuyGas() error { | ||||
|  | ||||
| 	self.AddGas(self.msg.Gas()) | ||||
| 	self.initialGas.Set(self.msg.Gas()) | ||||
| 	sender.SubAmount(MessageGasValue(self.msg)) | ||||
| 	sender.SubBalance(MessageGasValue(self.msg)) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
| @@ -251,7 +251,7 @@ func (self *StateTransition) RefundGas() { | ||||
| 	coinbase, sender := self.Coinbase(), self.From() | ||||
| 	// Return remaining gas | ||||
| 	remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice()) | ||||
| 	sender.AddAmount(remaining) | ||||
| 	sender.AddBalance(remaining) | ||||
|  | ||||
| 	uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2) | ||||
| 	for addr, ref := range self.state.Refunds() { | ||||
|   | ||||
| @@ -30,7 +30,6 @@ import ( | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"os/user" | ||||
| 	"path" | ||||
| ) | ||||
|  | ||||
| @@ -48,12 +47,6 @@ type keyStorePlain struct { | ||||
| 	keysDirPath string | ||||
| } | ||||
|  | ||||
| // TODO: copied from cmd/ethereum/flags.go | ||||
| func DefaultDataDir() string { | ||||
| 	usr, _ := user.Current() | ||||
| 	return path.Join(usr.HomeDir, ".ethereum") | ||||
| } | ||||
|  | ||||
| func NewKeyStorePlain(path string) KeyStore2 { | ||||
| 	return &keyStorePlain{path} | ||||
| } | ||||
| @@ -126,8 +119,11 @@ func GetKeyAddresses(keysDirPath string) (addresses [][]byte, err error) { | ||||
| 	} | ||||
| 	addresses = make([][]byte, len(fileInfos)) | ||||
| 	for i, fileInfo := range fileInfos { | ||||
| 		addresses[i] = make([]byte, 40) | ||||
| 		addresses[i] = []byte(fileInfo.Name()) | ||||
| 		address, err := hex.DecodeString(fileInfo.Name()) | ||||
| 		if err != nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		addresses[i] = address | ||||
| 	} | ||||
| 	return addresses, err | ||||
| } | ||||
|   | ||||
| @@ -2,12 +2,13 @@ package crypto | ||||
|  | ||||
| import ( | ||||
| 	"github.com/ethereum/go-ethereum/crypto/randentropy" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestKeyStorePlain(t *testing.T) { | ||||
| 	ks := NewKeyStorePlain(DefaultDataDir()) | ||||
| 	ks := NewKeyStorePlain(ethutil.DefaultDataDir()) | ||||
| 	pass := "" // not used but required by API | ||||
| 	k1, err := ks.GenerateNewKey(randentropy.Reader, pass) | ||||
| 	if err != nil { | ||||
| @@ -35,7 +36,7 @@ func TestKeyStorePlain(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func TestKeyStorePassphrase(t *testing.T) { | ||||
| 	ks := NewKeyStorePassphrase(DefaultDataDir()) | ||||
| 	ks := NewKeyStorePassphrase(ethutil.DefaultDataDir()) | ||||
| 	pass := "foo" | ||||
| 	k1, err := ks.GenerateNewKey(randentropy.Reader, pass) | ||||
| 	if err != nil { | ||||
| @@ -61,7 +62,7 @@ func TestKeyStorePassphrase(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func TestKeyStorePassphraseDecryptionFail(t *testing.T) { | ||||
| 	ks := NewKeyStorePassphrase(DefaultDataDir()) | ||||
| 	ks := NewKeyStorePassphrase(ethutil.DefaultDataDir()) | ||||
| 	pass := "foo" | ||||
| 	k1, err := ks.GenerateNewKey(randentropy.Reader, pass) | ||||
| 	if err != nil { | ||||
| @@ -89,7 +90,7 @@ func TestImportPreSaleKey(t *testing.T) { | ||||
| 	// python pyethsaletool.py genwallet | ||||
| 	// with password "foo" | ||||
| 	fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}" | ||||
| 	ks := NewKeyStorePassphrase(DefaultDataDir()) | ||||
| 	ks := NewKeyStorePassphrase(ethutil.DefaultDataDir()) | ||||
| 	pass := "foo" | ||||
| 	_, err := ImportPreSaleKey(ks, []byte(fileContent), pass) | ||||
| 	if err != nil { | ||||
|   | ||||
| @@ -147,7 +147,8 @@ func New(config *Config) (*Ethereum, error) { | ||||
| 	d, _ := db.Get([]byte("ProtocolVersion")) | ||||
| 	protov := ethutil.NewValue(d).Uint() | ||||
| 	if protov != ProtocolVersion && protov != 0 { | ||||
| 		return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, ethutil.Config.ExecPath+"/database") | ||||
| 		path := path.Join(config.DataDir, "database") | ||||
| 		return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, path) | ||||
| 	} | ||||
|  | ||||
| 	// Create new keymanager | ||||
|   | ||||
| @@ -3,10 +3,60 @@ package ethutil | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"os" | ||||
| 	"os/user" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/kardianos/osext" | ||||
| ) | ||||
|  | ||||
| func DefaultAssetPath() string { | ||||
| 	var assetPath string | ||||
| 	pwd, _ := os.Getwd() | ||||
| 	srcdir := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") | ||||
|  | ||||
| 	// If the current working directory is the go-ethereum dir | ||||
| 	// assume a debug build and use the source directory as | ||||
| 	// asset directory. | ||||
| 	if pwd == srcdir { | ||||
| 		assetPath = path.Join(pwd, "assets") | ||||
| 	} else { | ||||
| 		switch runtime.GOOS { | ||||
| 		case "darwin": | ||||
| 			// Get Binary Directory | ||||
| 			exedir, _ := osext.ExecutableFolder() | ||||
| 			assetPath = filepath.Join(exedir, "../Resources") | ||||
| 		case "linux": | ||||
| 			assetPath = "/usr/share/mist" | ||||
| 		case "windows": | ||||
| 			assetPath = "./assets" | ||||
| 		default: | ||||
| 			assetPath = "." | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Check if the assetPath exists. If not, try the source directory | ||||
| 	// This happens when binary is run from outside cmd/mist directory | ||||
| 	if _, err := os.Stat(assetPath); os.IsNotExist(err) { | ||||
| 		assetPath = path.Join(srcdir, "assets") | ||||
| 	} | ||||
|  | ||||
| 	return assetPath | ||||
| } | ||||
|  | ||||
| func DefaultDataDir() string { | ||||
| 	usr, _ := user.Current() | ||||
| 	if runtime.GOOS == "darwin" { | ||||
| 		return path.Join(usr.HomeDir, "Library/Ethereum") | ||||
| 	} else if runtime.GOOS == "windows" { | ||||
| 		return path.Join(usr.HomeDir, "AppData/Roaming/Ethereum") | ||||
| 	} else { | ||||
| 		return path.Join(usr.HomeDir, ".ethereum") | ||||
| 	} | ||||
| } | ||||
| func IsWindows() bool { | ||||
| 	return runtime.GOOS == "windows" | ||||
| } | ||||
|   | ||||
| @@ -24,7 +24,7 @@ var jsrelogger = logger.NewLogger("JSRE") | ||||
| type JSRE struct { | ||||
| 	ethereum *eth.Ethereum | ||||
| 	Vm       *otto.Otto | ||||
| 	pipe     *xeth.XEth | ||||
| 	xeth     *xeth.XEth | ||||
|  | ||||
| 	events event.Subscription | ||||
|  | ||||
| @@ -67,7 +67,7 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE { | ||||
| 	// We have to make sure that, whoever calls this, calls "Stop" | ||||
| 	go re.mainLoop() | ||||
|  | ||||
| 	re.Bind("eth", &JSEthereum{re.pipe, re.Vm, ethereum}) | ||||
| 	re.Bind("eth", &JSEthereum{re.xeth, re.Vm, ethereum}) | ||||
|  | ||||
| 	re.initStdFuncs() | ||||
|  | ||||
| @@ -113,12 +113,10 @@ func (self *JSRE) mainLoop() { | ||||
| func (self *JSRE) initStdFuncs() { | ||||
| 	t, _ := self.Vm.Get("eth") | ||||
| 	eth := t.Object() | ||||
| 	eth.Set("watch", self.watch) | ||||
| 	eth.Set("addPeer", self.addPeer) | ||||
| 	eth.Set("connect", self.connect) | ||||
| 	eth.Set("require", self.require) | ||||
| 	eth.Set("stopMining", self.stopMining) | ||||
| 	eth.Set("startMining", self.startMining) | ||||
| 	eth.Set("execBlock", self.execBlock) | ||||
| 	eth.Set("dump", self.dump) | ||||
| 	eth.Set("export", self.export) | ||||
| } | ||||
| @@ -152,7 +150,8 @@ func (self *JSRE) dump(call otto.FunctionCall) otto.Value { | ||||
| 	} | ||||
|  | ||||
| 	statedb := state.New(block.Root(), self.ethereum.Db()) | ||||
| 	v, _ := self.Vm.ToValue(statedb.Dump()) | ||||
|  | ||||
| 	v, _ := self.Vm.ToValue(statedb.RawDump()) | ||||
|  | ||||
| 	return v | ||||
| } | ||||
| @@ -167,36 +166,7 @@ func (self *JSRE) startMining(call otto.FunctionCall) otto.Value { | ||||
| 	return v | ||||
| } | ||||
|  | ||||
| // eth.watch | ||||
| func (self *JSRE) watch(call otto.FunctionCall) otto.Value { | ||||
| 	addr, _ := call.Argument(0).ToString() | ||||
| 	var storageAddr string | ||||
| 	var cb otto.Value | ||||
| 	var storageCallback bool | ||||
| 	if len(call.ArgumentList) > 2 { | ||||
| 		storageCallback = true | ||||
| 		storageAddr, _ = call.Argument(1).ToString() | ||||
| 		cb = call.Argument(2) | ||||
| 	} else { | ||||
| 		cb = call.Argument(1) | ||||
| 	} | ||||
|  | ||||
| 	if storageCallback { | ||||
| 		self.objectCb[addr+storageAddr] = append(self.objectCb[addr+storageAddr], cb) | ||||
|  | ||||
| 		// event := "storage:" + string(ethutil.Hex2Bytes(addr)) + ":" + string(ethutil.Hex2Bytes(storageAddr)) | ||||
| 		// self.ethereum.EventMux().Subscribe(event, self.changeChan) | ||||
| 	} else { | ||||
| 		self.objectCb[addr] = append(self.objectCb[addr], cb) | ||||
|  | ||||
| 		// event := "object:" + string(ethutil.Hex2Bytes(addr)) | ||||
| 		// self.ethereum.EventMux().Subscribe(event, self.changeChan) | ||||
| 	} | ||||
|  | ||||
| 	return otto.UndefinedValue() | ||||
| } | ||||
|  | ||||
| func (self *JSRE) addPeer(call otto.FunctionCall) otto.Value { | ||||
| func (self *JSRE) connect(call otto.FunctionCall) otto.Value { | ||||
| 	nodeURL, err := call.Argument(0).ToString() | ||||
| 	if err != nil { | ||||
| 		return otto.FalseValue() | ||||
| @@ -222,22 +192,12 @@ func (self *JSRE) require(call otto.FunctionCall) otto.Value { | ||||
| 	return t | ||||
| } | ||||
|  | ||||
| func (self *JSRE) execBlock(call otto.FunctionCall) otto.Value { | ||||
| 	hash, err := call.Argument(0).ToString() | ||||
| 	if err != nil { | ||||
| 		return otto.UndefinedValue() | ||||
| 	} | ||||
|  | ||||
| 	err = utils.BlockDo(self.ethereum, ethutil.Hex2Bytes(hash)) | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| func (self *JSRE) export(call otto.FunctionCall) otto.Value { | ||||
| 	if len(call.ArgumentList) == 0 { | ||||
| 		fmt.Println("err: require file name") | ||||
| 		return otto.FalseValue() | ||||
| 	} | ||||
|  | ||||
| 	return otto.TrueValue() | ||||
| } | ||||
|  | ||||
| func (self *JSRE) export(call otto.FunctionCall) otto.Value { | ||||
| 	fn, err := call.Argument(0).ToString() | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
|   | ||||
| @@ -16,7 +16,7 @@ function pp(object) { | ||||
|         str += " ]"; | ||||
|     } else if(typeof(object) === "object") { | ||||
|         str += "{ "; | ||||
|         var last = Object.keys(object).sort().pop() | ||||
|         var last = Object.keys(object).pop() | ||||
|         for(var k in object) { | ||||
|             str += k + ": " + pp(object[k]); | ||||
|  | ||||
|   | ||||
| @@ -52,10 +52,5 @@ func (self *Miner) Stop() { | ||||
| } | ||||
|  | ||||
| func (self *Miner) HashRate() int64 { | ||||
| 	var tot int64 | ||||
| 	for _, agent := range self.worker.agents { | ||||
| 		tot += agent.Pow().GetHashrate() | ||||
| 	} | ||||
|  | ||||
| 	return tot | ||||
| 	return self.worker.HashRate() | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
| 	"math/big" | ||||
| 	"sort" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum/core" | ||||
| 	"github.com/ethereum/go-ethereum/core/types" | ||||
| @@ -111,6 +112,8 @@ func (self *worker) register(agent Agent) { | ||||
| func (self *worker) update() { | ||||
| 	events := self.mux.Subscribe(core.ChainEvent{}, core.NewMinedBlockEvent{}) | ||||
|  | ||||
| 	timer := time.NewTicker(2 * time.Second) | ||||
|  | ||||
| out: | ||||
| 	for { | ||||
| 		select { | ||||
| @@ -129,6 +132,8 @@ out: | ||||
| 				agent.Stop() | ||||
| 			} | ||||
| 			break out | ||||
| 		case <-timer.C: | ||||
| 			minerlogger.Debugln("Hash rate:", self.HashRate(), "Khash") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -197,7 +202,7 @@ gasLimit: | ||||
| 	} | ||||
| 	self.eth.TxPool().RemoveSet(remove) | ||||
|  | ||||
| 	self.current.coinbase.AddAmount(core.BlockReward) | ||||
| 	self.current.coinbase.AddBalance(core.BlockReward) | ||||
|  | ||||
| 	self.current.state.Update(ethutil.Big0) | ||||
| 	self.push() | ||||
| @@ -225,7 +230,7 @@ func (self *worker) commitUncle(uncle *types.Header) error { | ||||
| 	} | ||||
|  | ||||
| 	uncleAccount := self.current.state.GetAccount(uncle.Coinbase) | ||||
| 	uncleAccount.AddAmount(uncleReward) | ||||
| 	uncleAccount.AddBalance(uncleReward) | ||||
|  | ||||
| 	self.current.coinbase.AddBalance(uncleReward) | ||||
|  | ||||
| @@ -244,3 +249,12 @@ func (self *worker) commitTransaction(tx *types.Transaction) error { | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (self *worker) HashRate() int64 { | ||||
| 	var tot int64 | ||||
| 	for _, agent := range self.agents { | ||||
| 		tot += agent.Pow().GetHashrate() | ||||
| 	} | ||||
|  | ||||
| 	return tot | ||||
| } | ||||
|   | ||||
| @@ -20,18 +20,24 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/ethdb" | ||||
| 	"github.com/ethereum/go-ethereum/ethutil" | ||||
| 	"github.com/ethereum/go-ethereum/event" | ||||
| 	"github.com/ethereum/go-ethereum/event/filter" | ||||
| 	"github.com/ethereum/go-ethereum/state" | ||||
| 	"github.com/ethereum/go-ethereum/ui" | ||||
| 	"github.com/ethereum/go-ethereum/xeth" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	defaultGasPrice = "10000000000000" | ||||
| 	defaultGas      = "10000" | ||||
| var ( | ||||
| 	defaultGasPrice  = big.NewInt(10000000000000) | ||||
| 	defaultGas       = big.NewInt(10000) | ||||
| 	filterTickerTime = 15 * time.Second | ||||
| ) | ||||
| 
 | ||||
| type EthereumApi struct { | ||||
| 	xeth          *xeth.XEth | ||||
| 	eth    *xeth.XEth | ||||
| 	xethMu sync.RWMutex | ||||
| 	mux    *event.TypeMux | ||||
| 
 | ||||
| 	quit          chan struct{} | ||||
| 	filterManager *filter.FilterManager | ||||
| 
 | ||||
| @@ -45,17 +51,21 @@ type EthereumApi struct { | ||||
| 	register map[string][]*NewTxArgs | ||||
| 
 | ||||
| 	db ethutil.Database | ||||
| 
 | ||||
| 	defaultBlockAge int64 | ||||
| } | ||||
| 
 | ||||
| func NewEthereumApi(eth *xeth.XEth) *EthereumApi { | ||||
| 	db, _ := ethdb.NewLDBDatabase("dapps") | ||||
| 	api := &EthereumApi{ | ||||
| 		xeth:          eth, | ||||
| 		eth:             eth, | ||||
| 		mux:             eth.Backend().EventMux(), | ||||
| 		quit:            make(chan struct{}), | ||||
| 		filterManager:   filter.NewFilterManager(eth.Backend().EventMux()), | ||||
| 		logs:            make(map[int]*logFilter), | ||||
| 		messages:        make(map[int]*whisperFilter), | ||||
| 		db:              db, | ||||
| 		defaultBlockAge: -1, | ||||
| 	} | ||||
| 	go api.filterManager.Start() | ||||
| 	go api.start() | ||||
| @@ -63,6 +73,64 @@ func NewEthereumApi(eth *xeth.XEth) *EthereumApi { | ||||
| 	return api | ||||
| } | ||||
| 
 | ||||
| func (self *EthereumApi) setStateByBlockNumber(num int64) { | ||||
| 	chain := self.xeth().Backend().ChainManager() | ||||
| 	var block *types.Block | ||||
| 
 | ||||
| 	if self.defaultBlockAge < 0 { | ||||
| 		num = chain.CurrentBlock().Number().Int64() + num + 1 | ||||
| 	} | ||||
| 	block = chain.GetBlockByNumber(uint64(num)) | ||||
| 
 | ||||
| 	if block != nil { | ||||
| 		self.useState(state.New(block.Root(), self.xeth().Backend().Db())) | ||||
| 	} else { | ||||
| 		self.useState(chain.State()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (self *EthereumApi) start() { | ||||
| 	timer := time.NewTicker(filterTickerTime) | ||||
| 	events := self.mux.Subscribe(core.ChainEvent{}) | ||||
| 
 | ||||
| done: | ||||
| 	for { | ||||
| 		select { | ||||
| 		case ev := <-events.Chan(): | ||||
| 			switch ev.(type) { | ||||
| 			case core.ChainEvent: | ||||
| 				if self.defaultBlockAge < 0 { | ||||
| 					self.setStateByBlockNumber(self.defaultBlockAge) | ||||
| 				} | ||||
| 			} | ||||
| 		case <-timer.C: | ||||
| 			self.logMut.Lock() | ||||
| 			self.messagesMut.Lock() | ||||
| 			for id, filter := range self.logs { | ||||
| 				if time.Since(filter.timeout) > 20*time.Second { | ||||
| 					self.filterManager.UninstallFilter(id) | ||||
| 					delete(self.logs, id) | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			for id, filter := range self.messages { | ||||
| 				if time.Since(filter.timeout) > 20*time.Second { | ||||
| 					self.xeth().Whisper().Unwatch(id) | ||||
| 					delete(self.messages, id) | ||||
| 				} | ||||
| 			} | ||||
| 			self.logMut.Unlock() | ||||
| 			self.messagesMut.Unlock() | ||||
| 		case <-self.quit: | ||||
| 			break done | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (self *EthereumApi) stop() { | ||||
| 	close(self.quit) | ||||
| } | ||||
| 
 | ||||
| func (self *EthereumApi) Register(args string, reply *interface{}) error { | ||||
| 	self.regmut.Lock() | ||||
| 	defer self.regmut.Unlock() | ||||
| @@ -95,7 +163,7 @@ func (self *EthereumApi) WatchTx(args string, reply *interface{}) error { | ||||
| 
 | ||||
| func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error { | ||||
| 	var id int | ||||
| 	filter := core.NewFilter(self.xeth.Backend()) | ||||
| 	filter := core.NewFilter(self.xeth().Backend()) | ||||
| 	filter.SetOptions(toFilterOptions(args)) | ||||
| 	filter.LogsCallback = func(logs state.Logs) { | ||||
| 		self.logMut.Lock() | ||||
| @@ -120,7 +188,7 @@ func (self *EthereumApi) UninstallFilter(id int, reply *interface{}) error { | ||||
| 
 | ||||
| func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error { | ||||
| 	var id int | ||||
| 	filter := core.NewFilter(self.xeth.Backend()) | ||||
| 	filter := core.NewFilter(self.xeth().Backend()) | ||||
| 
 | ||||
| 	callback := func(block *types.Block) { | ||||
| 		self.logMut.Lock() | ||||
| @@ -165,7 +233,7 @@ func (self *EthereumApi) Logs(id int, reply *interface{}) error { | ||||
| } | ||||
| 
 | ||||
| func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error { | ||||
| 	filter := core.NewFilter(self.xeth.Backend()) | ||||
| 	filter := core.NewFilter(self.xeth().Backend()) | ||||
| 	filter.SetOptions(toFilterOptions(args)) | ||||
| 
 | ||||
| 	*reply = toLogs(filter.Find()) | ||||
| @@ -174,41 +242,54 @@ func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *interface{}) error { | ||||
| 	err := args.requirements() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if args.BlockNumber > 0 { | ||||
| 		*reply = p.xeth.BlockByNumber(args.BlockNumber) | ||||
| 	// This seems a bit precarious Maybe worth splitting to discrete functions | ||||
| 	if len(args.Hash) > 0 { | ||||
| 		*reply = p.xeth().BlockByHash(args.Hash) | ||||
| 	} else { | ||||
| 		*reply = p.xeth.BlockByHash(args.Hash) | ||||
| 		*reply = p.xeth().BlockByNumber(args.BlockNumber) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error { | ||||
| 	if len(args.Gas) == 0 { | ||||
| 		args.Gas = defaultGas | ||||
| 		args.Gas = defaultGas.String() | ||||
| 	} | ||||
| 
 | ||||
| 	if len(args.GasPrice) == 0 { | ||||
| 		args.GasPrice = defaultGasPrice | ||||
| 		args.GasPrice = defaultGasPrice.String() | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO if no_private_key then | ||||
| 	if _, exists := p.register[args.From]; exists { | ||||
| 		p.register[args.From] = append(p.register[args.From], args) | ||||
| 	} else { | ||||
| 		result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data) | ||||
| 		*reply = result | ||||
| 	//if _, exists := p.register[args.From]; exists { | ||||
| 	//	p.register[args.From] = append(p.register[args.From], args) | ||||
| 	//} else { | ||||
| 	/* | ||||
| 		account := accounts.Get(fromHex(args.From)) | ||||
| 		if account != nil { | ||||
| 			if account.Unlocked() { | ||||
| 				if !unlockAccount(account) { | ||||
| 					return | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			result, _ := account.Transact(fromHex(args.To), fromHex(args.Value), fromHex(args.Gas), fromHex(args.GasPrice), fromHex(args.Data)) | ||||
| 			if len(result) > 0 { | ||||
| 				*reply = toHex(result) | ||||
| 			} | ||||
| 		} else if _, exists := p.register[args.From]; exists { | ||||
| 			p.register[ags.From] = append(p.register[args.From], args) | ||||
| 		} | ||||
| 	*/ | ||||
| 	result, _ := p.xeth().Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data) | ||||
| 	*reply = result | ||||
| 	//} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) Call(args *NewTxArgs, reply *interface{}) error { | ||||
| 	result, err := p.xeth.Call( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data) | ||||
| 	result, err := p.xeth().Call( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -222,7 +303,7 @@ func (p *EthereumApi) PushTx(args *PushTxArgs, reply *interface{}) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	result, _ := p.xeth.PushTx(args.Tx) | ||||
| 	result, _ := p.xeth().PushTx(args.Tx) | ||||
| 	*reply = result | ||||
| 	return nil | ||||
| } | ||||
| @@ -233,7 +314,7 @@ func (p *EthereumApi) GetStateAt(args *GetStateArgs, reply *interface{}) error { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	state := p.xeth.State().SafeGet(args.Address) | ||||
| 	state := p.xeth().State().SafeGet(args.Address) | ||||
| 
 | ||||
| 	value := state.StorageString(args.Key) | ||||
| 	var hx string | ||||
| @@ -255,42 +336,55 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) err | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	*reply = p.xeth.State().SafeGet(args.Address).Storage() | ||||
| 	*reply = p.xeth().State().SafeGet(args.Address).Storage() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) GetPeerCount(reply *interface{}) error { | ||||
| 	*reply = p.xeth.PeerCount() | ||||
| 	*reply = p.xeth().PeerCount() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) GetIsListening(reply *interface{}) error { | ||||
| 	*reply = p.xeth.IsListening() | ||||
| 	*reply = p.xeth().IsListening() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) GetCoinbase(reply *interface{}) error { | ||||
| 	*reply = p.xeth.Coinbase() | ||||
| 	*reply = p.xeth().Coinbase() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) Accounts(reply *interface{}) error { | ||||
| 	*reply = p.xeth.Accounts() | ||||
| 	*reply = p.xeth().Accounts() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) GetIsMining(reply *interface{}) error { | ||||
| 	*reply = p.xeth.IsMining() | ||||
| 	*reply = p.xeth().IsMining() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) SetMining(shouldmine bool, reply *interface{}) error { | ||||
| 	*reply = p.xeth.SetMining(shouldmine) | ||||
| 	*reply = p.xeth().SetMining(shouldmine) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) GetDefaultBlockAge(reply *interface{}) error { | ||||
| 	*reply = p.defaultBlockAge | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) SetDefaultBlockAge(defaultBlockAge int64, reply *interface{}) error { | ||||
| 	p.defaultBlockAge = defaultBlockAge | ||||
| 	p.setStateByBlockNumber(p.defaultBlockAge) | ||||
| 
 | ||||
| 	*reply = true | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) BlockNumber(reply *interface{}) error { | ||||
| 	*reply = p.xeth.Backend().ChainManager().CurrentBlock().Number() | ||||
| 	*reply = p.xeth().Backend().ChainManager().CurrentBlock().Number() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @@ -299,7 +393,7 @@ func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *interface{}) err | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*reply = p.xeth.TxCountAt(args.Address) | ||||
| 	*reply = p.xeth().TxCountAt(args.Address) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @@ -308,7 +402,7 @@ func (p *EthereumApi) GetBalanceAt(args *GetBalanceArgs, reply *interface{}) err | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	state := p.xeth.State().SafeGet(args.Address) | ||||
| 	state := p.xeth().State().SafeGet(args.Address) | ||||
| 	*reply = toHex(state.Balance().Bytes()) | ||||
| 	return nil | ||||
| } | ||||
| @@ -318,7 +412,7 @@ func (p *EthereumApi) GetCodeAt(args *GetCodeAtArgs, reply *interface{}) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*reply = p.xeth.CodeAt(args.Address) | ||||
| 	*reply = p.xeth().CodeAt(args.Address) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @@ -365,7 +459,7 @@ func (p *EthereumApi) DbGet(args *DbArgs, reply *interface{}) error { | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) NewWhisperIdentity(reply *interface{}) error { | ||||
| 	*reply = p.xeth.Whisper().NewIdentity() | ||||
| 	*reply = p.xeth().Whisper().NewIdentity() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @@ -376,7 +470,7 @@ func (p *EthereumApi) NewWhisperFilter(args *xeth.Options, reply *interface{}) e | ||||
| 		defer p.messagesMut.Unlock() | ||||
| 		p.messages[id].add(msg) // = append(p.messages[id], msg) | ||||
| 	} | ||||
| 	id = p.xeth.Whisper().Watch(args) | ||||
| 	id = p.xeth().Whisper().Watch(args) | ||||
| 	p.messages[id] = &whisperFilter{timeout: time.Now()} | ||||
| 	*reply = id | ||||
| 	return nil | ||||
| @@ -394,7 +488,7 @@ func (self *EthereumApi) MessagesChanged(id int, reply *interface{}) error { | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{}) error { | ||||
| 	err := p.xeth.Whisper().Post(args.Payload, args.To, args.From, args.Topic, args.Priority, args.Ttl) | ||||
| 	err := p.xeth().Whisper().Post(args.Payload, args.To, args.From, args.Topic, args.Priority, args.Ttl) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -404,17 +498,17 @@ func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{}) | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) HasWhisperIdentity(args string, reply *interface{}) error { | ||||
| 	*reply = p.xeth.Whisper().HasIdentity(args) | ||||
| 	*reply = p.xeth().Whisper().HasIdentity(args) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) WhisperMessages(id int, reply *interface{}) error { | ||||
| 	*reply = p.xeth.Whisper().Messages(id) | ||||
| 	*reply = p.xeth().Whisper().Messages(id) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error { | ||||
| 	// Spec at https://github.com/ethereum/wiki/wiki/Generic-ON-RPC | ||||
| 	// Spec at https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC | ||||
| 	rpclogger.DebugDetailf("%T %s", req.Params, req.Params) | ||||
| 	switch req.Method { | ||||
| 	case "eth_coinbase": | ||||
| @@ -429,6 +523,14 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error | ||||
| 			return err | ||||
| 		} | ||||
| 		return p.SetMining(args, reply) | ||||
| 	case "eth_defaultBlock": | ||||
| 		return p.GetDefaultBlockAge(reply) | ||||
| 	case "eth_setDefaultBlock": | ||||
| 		args, err := req.ToIntArgs() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		return p.SetDefaultBlockAge(int64(args), reply) | ||||
| 	case "eth_peerCount": | ||||
| 		return p.GetPeerCount(reply) | ||||
| 	case "eth_number": | ||||
| @@ -520,7 +622,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error | ||||
| 		} | ||||
| 		return p.AllLogs(args, reply) | ||||
| 	case "eth_gasPrice": | ||||
| 		*reply = defaultGasPrice | ||||
| 		*reply = toHex(defaultGasPrice.Bytes()) | ||||
| 		return nil | ||||
| 	case "eth_register": | ||||
| 		args, err := req.ToRegisterArgs() | ||||
| @@ -599,44 +701,34 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error | ||||
| 		} | ||||
| 		return p.WhisperMessages(args, reply) | ||||
| 	default: | ||||
| 		return NewErrorResponse(fmt.Sprintf("%v %s", ErrorNotImplemented, req.Method)) | ||||
| 		return NewErrorWithMessage(errNotImplemented, req.Method) | ||||
| 	} | ||||
| 
 | ||||
| 	rpclogger.DebugDetailf("Reply: %T %s", reply, reply) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| var filterTickerTime = 15 * time.Second | ||||
| func (self *EthereumApi) xeth() *xeth.XEth { | ||||
| 	self.xethMu.RLock() | ||||
| 	defer self.xethMu.RUnlock() | ||||
| 
 | ||||
| func (self *EthereumApi) start() { | ||||
| 	timer := time.NewTicker(filterTickerTime) | ||||
| done: | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-timer.C: | ||||
| 			self.logMut.Lock() | ||||
| 			self.messagesMut.Lock() | ||||
| 			for id, filter := range self.logs { | ||||
| 				if time.Since(filter.timeout) > 20*time.Second { | ||||
| 					self.filterManager.UninstallFilter(id) | ||||
| 					delete(self.logs, id) | ||||
| 				} | ||||
| 	return self.eth | ||||
| } | ||||
| 
 | ||||
| 			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) useState(statedb *state.StateDB) { | ||||
| 	self.xethMu.Lock() | ||||
| 	defer self.xethMu.Unlock() | ||||
| 
 | ||||
| 	self.eth = self.eth.UseState(statedb) | ||||
| } | ||||
| 
 | ||||
| func (self *EthereumApi) stop() { | ||||
| 	close(self.quit) | ||||
| func t(f ui.Frontend) { | ||||
| 	// Call the password dialog | ||||
| 	ret, err := f.Call("PasswordDialog") | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 	} | ||||
| 	// Get the first argument | ||||
| 	t, _ := ret.Get(0) | ||||
| 	fmt.Println("return:", t) | ||||
| } | ||||
							
								
								
									
										73
									
								
								rpc/args.go
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								rpc/args.go
									
									
									
									
									
								
							| @@ -19,14 +19,7 @@ func (obj *GetBlockArgs) UnmarshalJSON(b []byte) (err error) { | ||||
| 		obj.Hash = argstr | ||||
| 		return | ||||
| 	} | ||||
| 	return NewErrorResponse(ErrorDecodeArgs) | ||||
| } | ||||
|  | ||||
| func (obj *GetBlockArgs) requirements() error { | ||||
| 	if obj.BlockNumber == 0 && obj.Hash == "" { | ||||
| 		return NewErrorResponse("GetBlock requires either a block 'number' or a block 'hash' as argument") | ||||
| 	} | ||||
| 	return nil | ||||
| 	return errDecodeArgs | ||||
| } | ||||
|  | ||||
| type NewTxArgs struct { | ||||
| @@ -64,7 +57,7 @@ func (obj *NewTxArgs) UnmarshalJSON(b []byte) (err error) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	return NewErrorResponse(ErrorDecodeArgs) | ||||
| 	return errDecodeArgs | ||||
| } | ||||
|  | ||||
| type PushTxArgs struct { | ||||
| @@ -77,12 +70,12 @@ func (obj *PushTxArgs) UnmarshalJSON(b []byte) (err error) { | ||||
| 		obj.Tx = arg0 | ||||
| 		return | ||||
| 	} | ||||
| 	return NewErrorResponse(ErrorDecodeArgs) | ||||
| 	return errDecodeArgs | ||||
| } | ||||
|  | ||||
| func (a *PushTxArgs) requirementsPushTx() error { | ||||
| 	if a.Tx == "" { | ||||
| 		return NewErrorResponse("PushTx requires a 'tx' as argument") | ||||
| 		return NewErrorWithMessage(errArguments, "PushTx requires a 'tx' as argument") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -93,14 +86,14 @@ type GetStorageArgs struct { | ||||
|  | ||||
| func (obj *GetStorageArgs) UnmarshalJSON(b []byte) (err error) { | ||||
| 	if err = json.Unmarshal(b, &obj.Address); err != nil { | ||||
| 		return NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return errDecodeArgs | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (a *GetStorageArgs) requirements() error { | ||||
| 	if len(a.Address) == 0 { | ||||
| 		return NewErrorResponse("GetStorageAt requires an 'address' value as argument") | ||||
| 		return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'address' value as argument") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -116,64 +109,39 @@ func (obj *GetStateArgs) UnmarshalJSON(b []byte) (err error) { | ||||
| 		obj.Address = arg0 | ||||
| 		return | ||||
| 	} | ||||
| 	return NewErrorResponse(ErrorDecodeArgs) | ||||
| 	return errDecodeArgs | ||||
| } | ||||
|  | ||||
| func (a *GetStateArgs) requirements() error { | ||||
| 	if a.Address == "" { | ||||
| 		return NewErrorResponse("GetStorageAt requires an 'address' value as argument") | ||||
| 		return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'address' value as argument") | ||||
| 	} | ||||
| 	if a.Key == "" { | ||||
| 		return NewErrorResponse("GetStorageAt requires an 'key' value as argument") | ||||
| 		return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'key' value as argument") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type GetStorageAtRes struct { | ||||
| 	Key   string `json:"key"` | ||||
| 	Value string `json:"value"` | ||||
| } | ||||
|  | ||||
| type GetTxCountArgs struct { | ||||
| 	Address string `json:"address"` | ||||
| } | ||||
|  | ||||
| // type GetTxCountRes struct { | ||||
| //  Nonce int `json:"nonce"` | ||||
| // } | ||||
|  | ||||
| func (obj *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) { | ||||
| 	arg0 := "" | ||||
| 	if err = json.Unmarshal(b, &arg0); err == nil { | ||||
| 		obj.Address = arg0 | ||||
| 		return | ||||
| 	} | ||||
| 	return NewErrorResponse("Could not determine JSON parameters") | ||||
| 	return errDecodeArgs | ||||
| } | ||||
|  | ||||
| func (a *GetTxCountArgs) requirements() error { | ||||
| 	if a.Address == "" { | ||||
| 		return NewErrorResponse("GetTxCountAt requires an 'address' value as argument") | ||||
| 		return NewErrorWithMessage(errArguments, "GetTxCountAt requires an 'address' value as argument") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // type GetPeerCountRes struct { | ||||
| //  PeerCount int `json:"peerCount"` | ||||
| // } | ||||
|  | ||||
| // type GetListeningRes struct { | ||||
| //  IsListening bool `json:"isListening"` | ||||
| // } | ||||
|  | ||||
| // type GetCoinbaseRes struct { | ||||
| //  Coinbase string `json:"coinbase"` | ||||
| // } | ||||
|  | ||||
| // type GetMiningRes struct { | ||||
| //  IsMining bool `json:"isMining"` | ||||
| // } | ||||
|  | ||||
| type GetBalanceArgs struct { | ||||
| 	Address string | ||||
| } | ||||
| @@ -184,21 +152,16 @@ func (obj *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) { | ||||
| 		obj.Address = arg0 | ||||
| 		return | ||||
| 	} | ||||
| 	return NewErrorResponse("Could not determine JSON parameters") | ||||
| 	return errDecodeArgs | ||||
| } | ||||
|  | ||||
| func (a *GetBalanceArgs) requirements() error { | ||||
| 	if a.Address == "" { | ||||
| 		return NewErrorResponse("GetBalanceAt requires an 'address' value as argument") | ||||
| 		return NewErrorWithMessage(errArguments, "GetBalanceAt requires an 'address' value as argument") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type BalanceRes struct { | ||||
| 	Balance string `json:"balance"` | ||||
| 	Address string `json:"address"` | ||||
| } | ||||
|  | ||||
| type GetCodeAtArgs struct { | ||||
| 	Address string | ||||
| } | ||||
| @@ -209,12 +172,12 @@ func (obj *GetCodeAtArgs) UnmarshalJSON(b []byte) (err error) { | ||||
| 		obj.Address = arg0 | ||||
| 		return | ||||
| 	} | ||||
| 	return NewErrorResponse(ErrorDecodeArgs) | ||||
| 	return errDecodeArgs | ||||
| } | ||||
|  | ||||
| func (a *GetCodeAtArgs) requirements() error { | ||||
| 	if a.Address == "" { | ||||
| 		return NewErrorResponse("GetCodeAt requires an 'address' value as argument") | ||||
| 		return NewErrorWithMessage(errArguments, "GetCodeAt requires an 'address' value as argument") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -225,7 +188,7 @@ type Sha3Args struct { | ||||
|  | ||||
| func (obj *Sha3Args) UnmarshalJSON(b []byte) (err error) { | ||||
| 	if err = json.Unmarshal(b, &obj.Data); err != nil { | ||||
| 		return NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return errDecodeArgs | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| @@ -277,10 +240,10 @@ type DbArgs struct { | ||||
|  | ||||
| func (a *DbArgs) requirements() error { | ||||
| 	if len(a.Database) == 0 { | ||||
| 		return NewErrorResponse("DbPutArgs requires an 'Database' value as argument") | ||||
| 		return NewErrorWithMessage(errArguments, "DbPutArgs requires an 'Database' value as argument") | ||||
| 	} | ||||
| 	if len(a.Key) == 0 { | ||||
| 		return NewErrorResponse("DbPutArgs requires an 'Key' value as argument") | ||||
| 		return NewErrorWithMessage(errArguments, "DbPutArgs requires an 'Key' value as argument") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -29,8 +29,8 @@ import ( | ||||
| var rpchttplogger = logger.NewLogger("RPC-HTTP") | ||||
| var JSON rpc.JsonWrapper | ||||
|  | ||||
| func NewRpcHttpServer(pipe *xeth.XEth, port int) (*RpcHttpServer, error) { | ||||
| 	sport := fmt.Sprintf("127.0.0.1:%d", port) | ||||
| func NewRpcHttpServer(pipe *xeth.XEth, address string, port int) (*RpcHttpServer, error) { | ||||
| 	sport := fmt.Sprintf("%s:%d", address, port) | ||||
| 	l, err := net.Listen("tcp", sport) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -41,6 +41,7 @@ func NewRpcHttpServer(pipe *xeth.XEth, port int) (*RpcHttpServer, error) { | ||||
| 		quit:     make(chan bool), | ||||
| 		pipe:     pipe, | ||||
| 		port:     port, | ||||
| 		addr:     address, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| @@ -49,6 +50,7 @@ type RpcHttpServer struct { | ||||
| 	listener net.Listener | ||||
| 	pipe     *xeth.XEth | ||||
| 	port     int | ||||
| 	addr     string | ||||
| } | ||||
|  | ||||
| func (s *RpcHttpServer) exitHandler() { | ||||
| @@ -69,7 +71,7 @@ func (s *RpcHttpServer) Stop() { | ||||
| } | ||||
|  | ||||
| func (s *RpcHttpServer) Start() { | ||||
| 	rpchttplogger.Infof("Starting RPC-HTTP server on port %d", s.port) | ||||
| 	rpchttplogger.Infof("Starting RPC-HTTP server on %s:%d", s.addr, s.port) | ||||
| 	go s.exitHandler() | ||||
|  | ||||
| 	api := rpc.NewEthereumApi(s.pipe) | ||||
| @@ -92,7 +94,7 @@ func (s *RpcHttpServer) apiHandler(api *rpc.EthereumApi) http.Handler { | ||||
|  | ||||
| 		reqParsed, reqerr := JSON.ParseRequestBody(req) | ||||
| 		if reqerr != nil { | ||||
| 			jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest} | ||||
| 			jsonerr := &rpc.RpcErrorObject{-32700, "Error: Could not parse request"} | ||||
| 			JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr}) | ||||
| 			return | ||||
| 		} | ||||
|   | ||||
| @@ -25,12 +25,11 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/xeth" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	ErrorArguments      = "Error: Insufficient arguments" | ||||
| 	ErrorNotImplemented = "Error: Method not implemented" | ||||
| 	ErrorUnknown        = "Error: Unknown error" | ||||
| 	ErrorParseRequest   = "Error: Could not parse request" | ||||
| 	ErrorDecodeArgs     = "Error: Could not decode arguments" | ||||
| var ( | ||||
| 	errArguments      = errors.New("Error: Insufficient arguments") | ||||
| 	errNotImplemented = errors.New("Error: Method not implemented") | ||||
| 	errUnknown        = errors.New("Error: Unknown error") | ||||
| 	errDecodeArgs     = errors.New("Error: Could not decode arguments") | ||||
| ) | ||||
| 
 | ||||
| type RpcRequest struct { | ||||
| @@ -58,76 +57,72 @@ type RpcErrorObject struct { | ||||
| 	// Data    interface{} `json:"data"` | ||||
| } | ||||
| 
 | ||||
| func NewErrorResponse(msg string) error { | ||||
| 	return errors.New(msg) | ||||
| } | ||||
| 
 | ||||
| func NewErrorResponseWithError(msg string, err error) error { | ||||
| 	return fmt.Errorf("%s: %v", msg, err) | ||||
| func NewErrorWithMessage(err error, msg string) error { | ||||
| 	return fmt.Errorf("%s: %s", err.Error(), msg) | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToSha3Args() (*Sha3Args, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(Sha3Args) | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	if err := json.NewDecoder(r).Decode(args); err != nil { | ||||
| 		return nil, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return nil, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToGetBlockArgs() (*GetBlockArgs, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(GetBlockArgs) | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return nil, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToNewTxArgs() (*NewTxArgs, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(NewTxArgs) | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) | ||||
| 		return nil, NewErrorWithMessage(errDecodeArgs, err.Error()) | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToPushTxArgs() (*PushTxArgs, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(PushTxArgs) | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return nil, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToGetStateArgs() (*GetStateArgs, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(GetStateArgs) | ||||
| @@ -135,234 +130,241 @@ func (req *RpcRequest) ToGetStateArgs() (*GetStateArgs, error) { | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return nil, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToStorageAtArgs() (*GetStorageArgs, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(GetStorageArgs) | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return nil, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToGetTxCountArgs() (*GetTxCountArgs, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(GetTxCountArgs) | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return nil, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToGetBalanceArgs() (*GetBalanceArgs, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(GetBalanceArgs) | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return nil, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToGetCodeAtArgs() (*GetCodeAtArgs, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(GetCodeAtArgs) | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return nil, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToBoolArgs() (bool, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return false, NewErrorResponse(ErrorArguments) | ||||
| 		return false, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args bool | ||||
| 	err := json.Unmarshal(req.Params[0], &args) | ||||
| 	if err != nil { | ||||
| 		return false, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return false, errDecodeArgs | ||||
| 	} | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToIntArgs() (int, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return 0, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args int | ||||
| 	if err := json.Unmarshal(req.Params[0], &args); err != nil { | ||||
| 		return 0, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToCompileArgs() (string, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return "", NewErrorResponse(ErrorArguments) | ||||
| 		return "", errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args string | ||||
| 	err := json.Unmarshal(req.Params[0], &args) | ||||
| 	if err != nil { | ||||
| 		return "", NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return "", errDecodeArgs | ||||
| 	} | ||||
| 
 | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToFilterArgs() (*FilterOptions, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	args := new(FilterOptions) | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return nil, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToFilterStringArgs() (string, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return "", NewErrorResponse(ErrorArguments) | ||||
| 		return "", errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args string | ||||
| 	err := json.Unmarshal(req.Params[0], &args) | ||||
| 	if err != nil { | ||||
| 		return "", NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return "", errDecodeArgs | ||||
| 	} | ||||
| 
 | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToUninstallFilterArgs() (int, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return 0, NewErrorResponse(ErrorArguments) | ||||
| 		return 0, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args int | ||||
| 	err := json.Unmarshal(req.Params[0], &args) | ||||
| 	if err != nil { | ||||
| 		return 0, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return 0, errDecodeArgs | ||||
| 	} | ||||
| 
 | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToFilterChangedArgs() (int, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return 0, NewErrorResponse(ErrorArguments) | ||||
| 		return 0, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var id int | ||||
| 	r := bytes.NewReader(req.Params[0]) | ||||
| 	err := json.NewDecoder(r).Decode(&id) | ||||
| 	if err != nil { | ||||
| 		return 0, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return 0, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", id, id) | ||||
| 	return id, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToDbPutArgs() (*DbArgs, error) { | ||||
| 	if len(req.Params) < 3 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args DbArgs | ||||
| 	err := json.Unmarshal(req.Params[0], &args.Database) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) | ||||
| 		return nil, NewErrorWithMessage(errDecodeArgs, err.Error()) | ||||
| 	} | ||||
| 	err = json.Unmarshal(req.Params[1], &args.Key) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) | ||||
| 		return nil, NewErrorWithMessage(errDecodeArgs, err.Error()) | ||||
| 	} | ||||
| 	err = json.Unmarshal(req.Params[2], &args.Value) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) | ||||
| 		return nil, NewErrorWithMessage(errDecodeArgs, err.Error()) | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return &args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToDbGetArgs() (*DbArgs, error) { | ||||
| 	if len(req.Params) < 2 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args DbArgs | ||||
| 	err := json.Unmarshal(req.Params[0], &args.Database) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) | ||||
| 		return nil, NewErrorWithMessage(errDecodeArgs, err.Error()) | ||||
| 	} | ||||
| 
 | ||||
| 	err = json.Unmarshal(req.Params[1], &args.Key) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) | ||||
| 		return nil, NewErrorWithMessage(errDecodeArgs, err.Error()) | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return &args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToWhisperFilterArgs() (*xeth.Options, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args xeth.Options | ||||
| 	err := json.Unmarshal(req.Params[0], &args) | ||||
| 	if err != nil { | ||||
| 		return nil, NewErrorResponseWithError(ErrorDecodeArgs, err) | ||||
| 		return nil, NewErrorWithMessage(errDecodeArgs, err.Error()) | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return &args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToIdArgs() (int, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return 0, NewErrorResponse(ErrorArguments) | ||||
| 		return 0, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var id int | ||||
| 	err := json.Unmarshal(req.Params[0], &id) | ||||
| 	if err != nil { | ||||
| 		return 0, NewErrorResponse(ErrorDecodeArgs) | ||||
| 		return 0, errDecodeArgs | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", id, id) | ||||
| 
 | ||||
| 	return id, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToWhisperPostArgs() (*WhisperMessageArgs, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return nil, NewErrorResponse(ErrorArguments) | ||||
| 		return nil, errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args WhisperMessageArgs | ||||
| @@ -370,13 +372,13 @@ func (req *RpcRequest) ToWhisperPostArgs() (*WhisperMessageArgs, error) { | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return &args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return "", NewErrorResponse(ErrorArguments) | ||||
| 		return "", errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args string | ||||
| @@ -384,13 +386,13 @@ func (req *RpcRequest) ToWhisperHasIdentityArgs() (string, error) { | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToRegisterArgs() (string, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return "", NewErrorResponse(ErrorArguments) | ||||
| 		return "", errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args string | ||||
| @@ -398,13 +400,13 @@ func (req *RpcRequest) ToRegisterArgs() (string, error) { | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| 
 | ||||
| func (req *RpcRequest) ToWatchTxArgs() (string, error) { | ||||
| 	if len(req.Params) < 1 { | ||||
| 		return "", NewErrorResponse(ErrorArguments) | ||||
| 		return "", errArguments | ||||
| 	} | ||||
| 
 | ||||
| 	var args string | ||||
| @@ -412,6 +414,6 @@ func (req *RpcRequest) ToWatchTxArgs() (string, error) { | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	rpclogger.DebugDetailf("%T %v", args, args) | ||||
| 
 | ||||
| 	return args, nil | ||||
| } | ||||
| @@ -82,7 +82,7 @@ type RpcServer interface { | ||||
|  | ||||
| type Log struct { | ||||
| 	Address string   `json:"address"` | ||||
| 	Topic   []string `json:"topics"` | ||||
| 	Topic   []string `json:"topic"` | ||||
| 	Data    string   `json:"data"` | ||||
| 	Number  uint64   `json:"number"` | ||||
| } | ||||
|   | ||||
| @@ -99,7 +99,7 @@ func sockHandler(api *rpc.EthereumApi) websocket.Handler { | ||||
|  | ||||
| 			// reqParsed, reqerr := JSON.ParseRequestBody(conn.Request()) | ||||
| 			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}) | ||||
| 				continue | ||||
| 			} | ||||
|   | ||||
| @@ -20,7 +20,7 @@ type World struct { | ||||
| 	Accounts map[string]Account `json:"accounts"` | ||||
| } | ||||
|  | ||||
| func (self *StateDB) Dump() []byte { | ||||
| func (self *StateDB) RawDump() World { | ||||
| 	world := World{ | ||||
| 		Root:     ethutil.Bytes2Hex(self.trie.Root()), | ||||
| 		Accounts: make(map[string]Account), | ||||
| @@ -35,12 +35,15 @@ func (self *StateDB) Dump() []byte { | ||||
|  | ||||
| 		storageIt := stateObject.State.trie.Iterator() | ||||
| 		for storageIt.Next() { | ||||
| 			account.Storage[ethutil.Bytes2Hex(it.Key)] = ethutil.Bytes2Hex(it.Value) | ||||
| 			account.Storage[ethutil.Bytes2Hex(storageIt.Key)] = ethutil.Bytes2Hex(storageIt.Value) | ||||
| 		} | ||||
| 		world.Accounts[ethutil.Bytes2Hex(it.Key)] = account | ||||
| 	} | ||||
| 	return world | ||||
| } | ||||
|  | ||||
| 	json, err := json.MarshalIndent(world, "", "    ") | ||||
| func (self *StateDB) Dump() []byte { | ||||
| 	json, err := json.MarshalIndent(self.RawDump(), "", "    ") | ||||
| 	if err != nil { | ||||
| 		fmt.Println("dump err", err) | ||||
| 	} | ||||
|   | ||||
| @@ -19,6 +19,14 @@ func (self Code) String() string { | ||||
|  | ||||
| type Storage map[string]*ethutil.Value | ||||
|  | ||||
| func (self Storage) String() (str string) { | ||||
| 	for key, value := range self { | ||||
| 		str += fmt.Sprintf("%X : %X\n", key, value.Bytes()) | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (self Storage) Copy() Storage { | ||||
| 	cpy := make(Storage) | ||||
| 	for key, value := range self { | ||||
| @@ -119,10 +127,9 @@ func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value { | ||||
| } | ||||
| func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) { | ||||
| 	self.SetState(key.Bytes(), value) | ||||
| 	self.dirty = true | ||||
| } | ||||
|  | ||||
| func (self *StateObject) Storage() map[string]*ethutil.Value { | ||||
| func (self *StateObject) Storage() Storage { | ||||
| 	return self.storage | ||||
| } | ||||
|  | ||||
| @@ -172,20 +179,22 @@ func (c *StateObject) AddBalance(amount *big.Int) { | ||||
|  | ||||
| 	statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount) | ||||
| } | ||||
| func (c *StateObject) AddAmount(amount *big.Int) { c.AddBalance(amount) } | ||||
|  | ||||
| func (c *StateObject) SubBalance(amount *big.Int) { | ||||
| 	c.SetBalance(new(big.Int).Sub(c.balance, amount)) | ||||
|  | ||||
| 	statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount) | ||||
| } | ||||
| func (c *StateObject) SubAmount(amount *big.Int) { c.SubBalance(amount) } | ||||
|  | ||||
| func (c *StateObject) SetBalance(amount *big.Int) { | ||||
| 	c.balance = amount | ||||
| 	c.dirty = true | ||||
| } | ||||
|  | ||||
| func (c *StateObject) St() Storage { | ||||
| 	return c.storage | ||||
| } | ||||
|  | ||||
| // | ||||
| // Gas setters and getters | ||||
| // | ||||
| @@ -198,7 +207,7 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error { | ||||
| 		return fmt.Errorf("insufficient amount: %v, %v", c.balance, total) | ||||
| 	} | ||||
|  | ||||
| 	c.SubAmount(total) | ||||
| 	c.SubBalance(total) | ||||
|  | ||||
| 	c.dirty = true | ||||
|  | ||||
| @@ -221,7 +230,7 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error { | ||||
| 	rGas := new(big.Int).Set(gas) | ||||
| 	rGas.Mul(rGas, price) | ||||
|  | ||||
| 	self.AddAmount(rGas) | ||||
| 	self.AddBalance(rGas) | ||||
|  | ||||
| 	self.dirty = true | ||||
|  | ||||
|   | ||||
							
								
								
									
										18
									
								
								ui/frontend.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								ui/frontend.go
									
									
									
									
									
										Normal 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) | ||||
| } | ||||
							
								
								
									
										13
									
								
								vm/vm.go
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								vm/vm.go
									
									
									
									
									
								
							| @@ -16,6 +16,8 @@ type Vm struct { | ||||
| 	logStr string | ||||
|  | ||||
| 	err error | ||||
| 	// For logging | ||||
| 	debug bool | ||||
|  | ||||
| 	Dbg Debugger | ||||
|  | ||||
| @@ -32,7 +34,7 @@ func New(env Environment) *Vm { | ||||
| 		lt = LogTyDiff | ||||
| 	} | ||||
|  | ||||
| 	return &Vm{env: env, logTy: lt, Recoverable: true} | ||||
| 	return &Vm{debug: false, env: env, logTy: lt, Recoverable: true} | ||||
| } | ||||
|  | ||||
| func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) { | ||||
| @@ -664,6 +666,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I | ||||
| 				} | ||||
| 				addr = ref.Address() | ||||
|  | ||||
| 				fmt.Printf("CREATE %X\n", addr) | ||||
| 				stack.Push(ethutil.BigD(addr)) | ||||
|  | ||||
| 			} | ||||
| @@ -727,7 +730,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I | ||||
|  | ||||
| 			self.Printf(" => (%x) %v", receiver.Address()[:4], balance) | ||||
|  | ||||
| 			receiver.AddAmount(balance) | ||||
| 			receiver.AddBalance(balance) | ||||
| 			statedb.Delete(context.Address()) | ||||
|  | ||||
| 			fallthrough | ||||
| @@ -828,7 +831,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo | ||||
| 			// 0 => non 0 | ||||
| 			mult = ethutil.Big3 | ||||
| 		} else if len(val) > 0 && len(y.Bytes()) == 0 { | ||||
| 			statedb.Refund(caller.Address(), GasSStoreRefund) | ||||
| 			statedb.Refund(self.env.Origin(), GasSStoreRefund) | ||||
|  | ||||
| 			mult = ethutil.Big0 | ||||
| 		} else { | ||||
| @@ -937,18 +940,22 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, callData []byte, context * | ||||
| } | ||||
|  | ||||
| func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine { | ||||
| 	if self.debug { | ||||
| 		if self.logTy == LogTyPretty { | ||||
| 			self.logStr += fmt.Sprintf(format, v...) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return self | ||||
| } | ||||
|  | ||||
| func (self *Vm) Endl() VirtualMachine { | ||||
| 	if self.debug { | ||||
| 		if self.logTy == LogTyPretty { | ||||
| 			vmlogger.Debugln(self.logStr) | ||||
| 			self.logStr = "" | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return self | ||||
| } | ||||
|   | ||||
| @@ -4,18 +4,19 @@ import "github.com/ethereum/go-ethereum/state" | ||||
| 
 | ||||
| type State struct { | ||||
| 	xeth  *XEth | ||||
| 	state *state.StateDB | ||||
| } | ||||
| 
 | ||||
| func NewState(xeth *XEth) *State { | ||||
| 	return &State{xeth} | ||||
| func NewState(xeth *XEth, statedb *state.StateDB) *State { | ||||
| 	return &State{xeth, statedb} | ||||
| } | ||||
| 
 | ||||
| func (self *State) State() *state.StateDB { | ||||
| 	return self.xeth.chainManager.TransState() | ||||
| 	return self.state | ||||
| } | ||||
| 
 | ||||
| func (self *State) Get(addr string) *Object { | ||||
| 	return &Object{self.State().GetStateObject(fromHex(addr))} | ||||
| 	return &Object{self.state.GetStateObject(fromHex(addr))} | ||||
| } | ||||
| 
 | ||||
| func (self *State) SafeGet(addr string) *Object { | ||||
| @@ -23,7 +24,7 @@ func (self *State) SafeGet(addr string) *Object { | ||||
| } | ||||
| 
 | ||||
| func (self *State) safeGet(addr string) *state.StateObject { | ||||
| 	object := self.State().GetStateObject(fromHex(addr)) | ||||
| 	object := self.state.GetStateObject(fromHex(addr)) | ||||
| 	if object == nil { | ||||
| 		object = state.NewStateObject(fromHex(addr), self.xeth.eth.Db()) | ||||
| 	} | ||||
							
								
								
									
										18
									
								
								xeth/xeth.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								xeth/xeth.go
									
									
									
									
									
								
							| @@ -17,6 +17,7 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/logger" | ||||
| 	"github.com/ethereum/go-ethereum/miner" | ||||
| 	"github.com/ethereum/go-ethereum/p2p" | ||||
| 	"github.com/ethereum/go-ethereum/state" | ||||
| 	"github.com/ethereum/go-ethereum/whisper" | ||||
| ) | ||||
|  | ||||
| @@ -54,13 +55,26 @@ func New(eth Backend) *XEth { | ||||
| 		whisper:        NewWhisper(eth.Whisper()), | ||||
| 		miner:          eth.Miner(), | ||||
| 	} | ||||
| 	xeth.state = NewState(xeth) | ||||
| 	xeth.state = NewState(xeth, xeth.chainManager.TransState()) | ||||
|  | ||||
| 	return xeth | ||||
| } | ||||
|  | ||||
| func (self *XEth) Backend() Backend { return self.eth } | ||||
| func (self *XEth) UseState(statedb *state.StateDB) *XEth { | ||||
| 	xeth := &XEth{ | ||||
| 		eth:            self.eth, | ||||
| 		blockProcessor: self.blockProcessor, | ||||
| 		chainManager:   self.chainManager, | ||||
| 		whisper:        self.whisper, | ||||
| 		miner:          self.miner, | ||||
| 	} | ||||
|  | ||||
| 	xeth.state = NewState(xeth, statedb) | ||||
| 	return xeth | ||||
| } | ||||
| func (self *XEth) State() *State { return self.state } | ||||
|  | ||||
| func (self *XEth) Whisper() *Whisper   { return self.whisper } | ||||
| func (self *XEth) Miner() *miner.Miner { return self.miner } | ||||
|  | ||||
| @@ -229,7 +243,7 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		statedb = self.chainManager.TransState() | ||||
| 		statedb = self.State().State() //self.chainManager.TransState() | ||||
| 		key     = self.eth.KeyManager().KeyPair() | ||||
| 		from    = statedb.GetOrNewStateObject(key.Address()) | ||||
| 		block   = self.chainManager.CurrentBlock() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user