Commit 3820a652 authored by Matthew Wampler-Doty's avatar Matthew Wampler-Doty

Merge branch 'publictests' of github.com:ebuchman/go-ethereum into ethash_pow

parents 8653db6d 0efd6a88
language: go language: go
go: go:
- 1.4.1 - 1.4.2
before_install: before_install:
- sudo add-apt-repository ppa:beineri/opt-qt54 -y - sudo add-apt-repository ppa:beineri/opt-qt541 -y
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine - sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine
install: install:
# - go get code.google.com/p/go.tools/cmd/goimports
# - go get github.com/golang/lint/golint
# - go get golang.org/x/tools/cmd/vet # - go get golang.org/x/tools/cmd/vet
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
- go get github.com/mattn/goveralls - go get github.com/mattn/goveralls
before_script: before_script:
# - gofmt -l -w .
# - goimports -l -w .
# - golint .
# - go vet ./... # - go vet ./...
# - go test -race ./... # - go test -race ./...
script: script:
......
{ {
"ImportPath": "github.com/ethereum/go-ethereum", "ImportPath": "github.com/ethereum/go-ethereum",
"GoVersion": "go1.4.1", "GoVersion": "go1.4.2",
"Packages": [ "Packages": [
"./..." "./..."
], ],
"Deps": [ "Deps": [
{
"ImportPath": "bitbucket.org/kardianos/osext",
"Comment": "null-13",
"Rev": "5d3ddcf53a508cc2f7404eaebf546ef2cb5cdb6e"
},
{ {
"ImportPath": "code.google.com/p/go-uuid/uuid", "ImportPath": "code.google.com/p/go-uuid/uuid",
"Comment": "null-12", "Comment": "null-12",
...@@ -37,6 +32,10 @@ ...@@ -37,6 +32,10 @@
"ImportPath": "github.com/jackpal/go-nat-pmp", "ImportPath": "github.com/jackpal/go-nat-pmp",
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1" "Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
}, },
{
"ImportPath": "github.com/kardianos/osext",
"Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
},
{ {
"ImportPath": "github.com/obscuren/otto", "ImportPath": "github.com/obscuren/otto",
"Rev": "cf13cc4228c5e5ce0fe27a7aea90bc10091c4f19" "Rev": "cf13cc4228c5e5ce0fe27a7aea90bc10091c4f19"
......
Copyright (c) 2012 Daniel Theophanes
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
### Extensions to the "os" package.
## Find the current Executable and ExecutableFolder.
There is sometimes utility in finding the current executable file
that is running. This can be used for upgrading the current executable
or finding resources located relative to the executable file.
Multi-platform and supports:
* Linux
* OS X
* Windows
* Plan 9
* BSDs.
...@@ -25,8 +25,3 @@ func ExecutableFolder() (string, error) { ...@@ -25,8 +25,3 @@ func ExecutableFolder() (string, error) {
folder, _ := filepath.Split(p) folder, _ := filepath.Split(p)
return folder, nil return folder, nil
} }
// Depricated. Same as Executable().
func GetExePath() (exePath string, err error) {
return Executable()
}
...@@ -5,16 +5,16 @@ ...@@ -5,16 +5,16 @@
package osext package osext
import ( import (
"syscall" "os"
"os" "strconv"
"strconv" "syscall"
) )
func executable() (string, error) { func executable() (string, error) {
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text") f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
if err != nil { if err != nil {
return "", err return "", err
} }
defer f.Close() defer f.Close()
return syscall.Fd2path(int(f.Fd())) return syscall.Fd2path(int(f.Fd()))
} }
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux netbsd openbsd // +build linux netbsd openbsd solaris dragonfly
package osext package osext
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"runtime" "runtime"
) )
...@@ -18,8 +19,10 @@ func executable() (string, error) { ...@@ -18,8 +19,10 @@ func executable() (string, error) {
return os.Readlink("/proc/self/exe") return os.Readlink("/proc/self/exe")
case "netbsd": case "netbsd":
return os.Readlink("/proc/curproc/exe") return os.Readlink("/proc/curproc/exe")
case "openbsd": case "openbsd", "dragonfly":
return os.Readlink("/proc/curproc/file") return os.Readlink("/proc/curproc/file")
case "solaris":
return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))
} }
return "", errors.New("ExecPath not implemented for " + runtime.GOOS) return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
} }
...@@ -34,33 +34,62 @@ package accounts ...@@ -34,33 +34,62 @@ package accounts
import ( import (
crand "crypto/rand" crand "crypto/rand"
"errors"
"sync"
"time"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
var ErrLocked = errors.New("account is locked; please request passphrase")
// TODO: better name for this struct? // TODO: better name for this struct?
type Account struct { type Account struct {
Address []byte Address []byte
} }
type AccountManager struct { type AccountManager struct {
keyStore crypto.KeyStore2 keyStore crypto.KeyStore2
unlockedKeys map[string]crypto.Key
unlockMilliseconds time.Duration
mutex sync.RWMutex
} }
// TODO: get key by addr - modify KeyStore2 GetKey to work with addr func NewAccountManager(keyStore crypto.KeyStore2, unlockMilliseconds time.Duration) AccountManager {
keysMap := make(map[string]crypto.Key)
// TODO: pass through passphrase for APIs which require access to private key?
func NewAccountManager(keyStore crypto.KeyStore2) AccountManager {
am := &AccountManager{ am := &AccountManager{
keyStore: keyStore, keyStore: keyStore,
unlockedKeys: keysMap,
unlockMilliseconds: unlockMilliseconds,
} }
return *am return *am
} }
func (am *AccountManager) Sign(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) { func (am AccountManager) DeleteAccount(address []byte, auth string) error {
return am.keyStore.DeleteKey(address, auth)
}
func (am *AccountManager) Sign(fromAccount *Account, toSign []byte) (signature []byte, err error) {
am.mutex.RLock()
unlockedKey := am.unlockedKeys[string(fromAccount.Address)]
am.mutex.RUnlock()
if unlockedKey.Address == nil {
return nil, ErrLocked
}
signature, err = crypto.Sign(toSign, unlockedKey.PrivateKey)
return signature, err
}
func (am *AccountManager) SignLocked(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) {
key, err := am.keyStore.GetKey(fromAccount.Address, keyAuth) key, err := am.keyStore.GetKey(fromAccount.Address, keyAuth)
if err != nil { if err != nil {
return nil, err return nil, err
} }
am.mutex.RLock()
am.unlockedKeys[string(fromAccount.Address)] = *key
am.mutex.RUnlock()
go unlockLater(am, fromAccount.Address)
signature, err = crypto.Sign(toSign, key.PrivateKey) signature, err = crypto.Sign(toSign, key.PrivateKey)
return signature, err return signature, err
} }
...@@ -76,8 +105,6 @@ func (am AccountManager) NewAccount(auth string) (*Account, error) { ...@@ -76,8 +105,6 @@ func (am AccountManager) NewAccount(auth string) (*Account, error) {
return ua, err return ua, err
} }
// set of accounts == set of keys in given key store
// TODO: do we need persistence of accounts as well?
func (am *AccountManager) Accounts() ([]Account, error) { func (am *AccountManager) Accounts() ([]Account, error) {
addresses, err := am.keyStore.GetKeyAddresses() addresses, err := am.keyStore.GetKeyAddresses()
if err != nil { if err != nil {
...@@ -93,3 +120,13 @@ func (am *AccountManager) Accounts() ([]Account, error) { ...@@ -93,3 +120,13 @@ func (am *AccountManager) Accounts() ([]Account, error) {
} }
return accounts, err return accounts, err
} }
func unlockLater(am *AccountManager, addr []byte) {
select {
case <-time.After(time.Millisecond * am.unlockMilliseconds):
}
am.mutex.RLock()
// TODO: how do we know the key is actually gone from memory?
delete(am.unlockedKeys, string(addr))
am.mutex.RUnlock()
}
...@@ -5,16 +5,78 @@ import ( ...@@ -5,16 +5,78 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/randentropy" "github.com/ethereum/go-ethereum/crypto/randentropy"
"github.com/ethereum/go-ethereum/ethutil"
"time"
) )
func TestAccountManager(t *testing.T) { func TestAccountManager(t *testing.T) {
ks := crypto.NewKeyStorePlain(crypto.DefaultDataDir()) ks := crypto.NewKeyStorePlain(ethutil.DefaultDataDir() + "/testaccounts")
am := NewAccountManager(ks) am := NewAccountManager(ks, 100)
pass := "" // not used but required by API pass := "" // not used but required by API
a1, err := am.NewAccount(pass) a1, err := am.NewAccount(pass)
toSign := randentropy.GetEntropyCSPRNG(32) toSign := randentropy.GetEntropyCSPRNG(32)
_, err = am.Sign(a1, pass, toSign) _, err = am.SignLocked(a1, pass, toSign)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Cleanup
time.Sleep(time.Millisecond * 150) // wait for locking
accounts, err := am.Accounts()
if err != nil {
t.Fatal(err)
}
for _, account := range accounts {
err := am.DeleteAccount(account.Address, pass)
if err != nil {
t.Fatal(err)
}
}
}
func TestAccountManagerLocking(t *testing.T) {
ks := crypto.NewKeyStorePassphrase(ethutil.DefaultDataDir() + "/testaccounts")
am := NewAccountManager(ks, 200)
pass := "foo"
a1, err := am.NewAccount(pass)
toSign := randentropy.GetEntropyCSPRNG(32)
// Signing without passphrase fails because account is locked
_, err = am.Sign(a1, toSign)
if err != ErrLocked {
t.Fatal(err)
}
// Signing with passphrase works
_, err = am.SignLocked(a1, pass, toSign)
if err != nil {
t.Fatal(err)
}
// Signing without passphrase works because account is temp unlocked
_, err = am.Sign(a1, toSign)
if err != nil {
t.Fatal(err)
}
// Signing without passphrase fails after automatic locking
time.Sleep(time.Millisecond * time.Duration(250))
_, err = am.Sign(a1, toSign)
if err != ErrLocked {
t.Fatal(err)
}
// Cleanup
accounts, err := am.Accounts()
if err != nil {
t.Fatal(err)
}
for _, account := range accounts {
err := am.DeleteAccount(account.Address, pass)
if err != nil {
t.Fatal(err)
}
}
} }
...@@ -26,10 +26,10 @@ import ( ...@@ -26,10 +26,10 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"os/user"
"path" "path"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/vm" "github.com/ethereum/go-ethereum/vm"
...@@ -79,12 +79,7 @@ var ( ...@@ -79,12 +79,7 @@ var (
InputFile string InputFile string
) )
func defaultDataDir() string { var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
usr, _ := user.Current()
return path.Join(usr.HomeDir, ".ethereum")
}
var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
func Init() { func Init() {
// TODO: move common flag processing to cmd/util // TODO: move common flag processing to cmd/util
...@@ -107,7 +102,7 @@ func Init() { ...@@ -107,7 +102,7 @@ func Init() {
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given") flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use") flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)") flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
......
...@@ -37,7 +37,7 @@ import ( ...@@ -37,7 +37,7 @@ import (
const ( const (
ClientIdentifier = "Ethereum(G)" ClientIdentifier = "Ethereum(G)"
Version = "0.8.4" Version = "0.8.6"
) )
var clilogger = logger.NewLogger("CLI") var clilogger = logger.NewLogger("CLI")
......
...@@ -14,10 +14,12 @@ ...@@ -14,10 +14,12 @@
</div> </div>
<div> <div>
<span class="amount">Amount:</span> <span>Address:</span>
<input type="text" id="address" style="width:200px"> <input type="text" id="address" style="width:200px">
<span>Amount:</span>
<input type="text" id="amount" style="width:200px"> <input type="text" id="amount" style="width:200px">
<button onclick="transact()">Send</button> <button onclick="transact()">Send</button>
<span id="message"></span>
</div> </div>
<hr> <hr>
...@@ -58,7 +60,7 @@ ...@@ -58,7 +60,7 @@
}], }],
"outputs": [] "outputs": []
}, { }, {
"name":"received", "name":"Changed",
"type":"event", "type":"event",
"inputs": [ "inputs": [
{"name":"from","type":"address","indexed":true}, {"name":"from","type":"address","indexed":true},
...@@ -69,18 +71,14 @@ ...@@ -69,18 +71,14 @@
var address = localStorage.getItem("address"); var address = localStorage.getItem("address");
// deploy if not exist // deploy if not exist
if (address == null) { if (address == null) {
var code = "0x60056013565b61012b806100346000396000f35b6103e8600033600160a060020a0316600052602052604060002081905550560060e060020a6000350480637bb98a681461002b578063d0679d3414610039578063e3d670d71461004d57005b610033610126565b60006000f35b610047600435602435610062565b60006000f35b610058600435610104565b8060005260206000f35b80600033600160a060020a0316600052602052604060002054101561008657610100565b80600033600160a060020a0316600052602052604060002090815403908190555080600083600160a060020a0316600052602052604060002090815401908190555033600160a060020a0316600052806020527ff11e547d796cc64acdf758e7cee90439494fd886a19159454aa61e473fdbafef60406000a15b5050565b6000600082600160a060020a03166000526020526040600020549050919050565b5b60008156"; var code = "0x60056013565b61014f8061003a6000396000f35b620f42406000600033600160a060020a0316815260200190815260200160002081905550560060e060020a600035048063d0679d3414610020578063e3d670d71461003457005b61002e600435602435610049565b60006000f35b61003f600435610129565b8060005260206000f35b806000600033600160a060020a03168152602001908152602001600020541061007157610076565b610125565b806000600033600160a060020a03168152602001908152602001600020908154039081905550806000600084600160a060020a031681526020019081526020016000209081540190819055508033600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a38082600160a060020a03167fb52dda022b6c1a1f40905a85f257f689aa5d69d850e49cf939d688fbe5af594660006000a35b5050565b60006000600083600160a060020a0316815260200190815260200160002054905091905056";
address = web3.eth.transact({data: code}); address = web3.eth.transact({data: code});
localStorage.setItem("address", address); localStorage.setItem("address", address);
} }
document.querySelector("#contract_addr").innerHTML = address.toUpperCase(); document.querySelector("#contract_addr").innerHTML = address;
var contract = web3.eth.contract(address, desc); var contract = web3.eth.contract(address, desc);
contract.received({from: eth.coinbase}).changed(function() { contract.Changed({from: eth.coinbase}).changed(function() {
refresh();
});
eth.watch('chain').changed(function() {
refresh(); refresh();
}); });
...@@ -93,21 +91,33 @@ ...@@ -93,21 +91,33 @@
var storage = eth.storageAt(address); var storage = eth.storageAt(address);
table.innerHTML = ""; table.innerHTML = "";
for( var item in storage ) { for( var item in storage ) {
table.innerHTML += "<tr><td>"+item.toUpperCase()+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>"; table.innerHTML += "<tr><td>"+item+"</td><td>"+web3.toDecimal(storage[item])+"</td></tr>";
} }
} }
function transact() { function transact() {
var to = document.querySelector("#address").value; var to = document.querySelector("#address");
if( to.length == 0 ) { if( to.value.length == 0 ) {
to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3"; to = "0x4205b06c2cfa0e30359edcab94543266cb6fa1d3";
} else { } else {
to = "0x"+to; if (to.value.substr(0,2) != "0x")
to.value = "0x"+to.value;
} }
var value = parseInt( document.querySelector("#amount").value ); var value = document.querySelector("#amount");
var amount = parseInt( value.value );
console.log("transact: ", to.value, " => ", amount)
contract.send( to.value, amount );
to.value = "";
value.value = "";
contract.send( to, value ); var message = document.querySelector("#message")
message.innerHTML = "Submitted";
setTimeout(function() {
message.innerHTML = "";
}, 1000);
} }
refresh(); refresh();
...@@ -121,7 +131,7 @@ contract JevCoin { ...@@ -121,7 +131,7 @@ contract JevCoin {
balances[msg.sender] = 1000000; balances[msg.sender] = 1000000;
} }
event changed(address indexed from, address indexed to); event Changed(address indexed from, uint indexed amount);
function send(address to, uint value) function send(address to, uint value)
{ {
if( balances[msg.sender] < value ) return; if( balances[msg.sender] < value ) return;
...@@ -129,7 +139,8 @@ contract JevCoin { ...@@ -129,7 +139,8 @@ contract JevCoin {
balances[msg.sender] -= value; balances[msg.sender] -= value;
balances[to] += value; balances[to] += value;
changed(msg.sender, to); Changed(msg.sender, value);
Changed(to, value);
} }
function balance(address who) constant returns(uint t) function balance(address who) constant returns(uint t)
......
...@@ -62,6 +62,8 @@ ...@@ -62,6 +62,8 @@
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545')); web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545'));
eth.defaultBlock = -2
document.querySelector("#number").innerHTML = eth.number; document.querySelector("#number").innerHTML = eth.number;
document.querySelector("#coinbase").innerHTML = eth.coinbase document.querySelector("#coinbase").innerHTML = eth.coinbase
document.querySelector("#peer_count").innerHTML = eth.peerCount; document.querySelector("#peer_count").innerHTML = eth.peerCount;
...@@ -72,8 +74,9 @@ ...@@ -72,8 +74,9 @@
document.querySelector("#mining").innerHTML = eth.mining; document.querySelector("#mining").innerHTML = eth.mining;
document.querySelector("#listening").innerHTML = eth.listening; document.querySelector("#listening").innerHTML = eth.listening;
eth.watch('chain').changed(function() { eth.watch('chain').changed(function() {
document.querySelector("#number").innerHTML = eth.number; document.querySelector("#number").innerHTML = eth.number;
}); });
</script> </script>
......
...@@ -964,7 +964,7 @@ ApplicationWindow { ...@@ -964,7 +964,7 @@ ApplicationWindow {
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 30 anchors.topMargin: 30
font.pointSize: 12 font.pointSize: 12
text: "<h2>Mist (0.8.4)</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 ( ...@@ -26,13 +26,11 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"os/user"
"path" "path"
"path/filepath"
"runtime" "runtime"
"bitbucket.org/kardianos/osext"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/vm" "github.com/ethereum/go-ethereum/vm"
...@@ -68,38 +66,7 @@ var ( ...@@ -68,38 +66,7 @@ var (
// flags specific to gui client // flags specific to gui client
var AssetPath string var AssetPath string
var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
//TODO: If we re-use the one defined in cmd.go the binary osx image crashes. If somebody finds out why we can dry this up.
func defaultAssetPath() string {
var assetPath string
// If the current working directory is the go-ethereum dir
// assume a debug build and use the source directory as
// asset directory.
pwd, _ := os.Getwd()
if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") {
assetPath = path.Join(pwd, "assets")
} else {
switch runtime.GOOS {
case "darwin":
// Get Binary Directory
exedir, _ := osext.ExecutableFolder()
assetPath = filepath.Join(exedir, "../Resources")
case "linux":
assetPath = "/usr/share/mist"
case "windows":
assetPath = "./assets"
default:
assetPath = "."
}
}
return assetPath
}
func defaultDataDir() string {
usr, _ := user.Current()
return path.Join(usr.HomeDir, ".ethereum")
}
var defaultConfigFile = path.Join(defaultDataDir(), "conf.ini")
func Init() { func Init() {
// TODO: move common flag processing to cmd/utils // TODO: move common flag processing to cmd/utils
...@@ -121,12 +88,12 @@ func Init() { ...@@ -121,12 +88,12 @@ func Init() {
flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)") flag.StringVar(&SecretFile, "import", "", "imports the file given (hex or mnemonic formats)")
flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given") flag.StringVar(&ExportDir, "export", "", "exports the session keyring to files in the directory given")
flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)") flag.StringVar(&LogFile, "logfile", "", "log file (defaults to standard output)")
flag.StringVar(&Datadir, "datadir", defaultDataDir(), "specifies the datadir to use") flag.StringVar(&Datadir, "datadir", ethutil.DefaultDataDir(), "specifies the datadir to use")
flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file") flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)") flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)") flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
flag.StringVar(&AssetPath, "asset_path", defaultAssetPath(), "absolute path to GUI assets directory") flag.StringVar(&AssetPath, "asset_path", ethutil.DefaultAssetPath(), "absolute path to GUI assets directory")
// Network stuff // Network stuff
var ( var (
......
...@@ -36,7 +36,7 @@ import ( ...@@ -36,7 +36,7 @@ import (
const ( const (
ClientIdentifier = "Mist" ClientIdentifier = "Mist"
Version = "0.8.4" Version = "0.8.6"
) )
var ethereum *eth.Ethereum var ethereum *eth.Ethereum
......
...@@ -25,12 +25,8 @@ import ( ...@@ -25,12 +25,8 @@ import (
"fmt" "fmt"
"os" "os"
"os/signal" "os/signal"
"path"
"path/filepath"
"regexp" "regexp"
"runtime"
"bitbucket.org/kardianos/osext"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
...@@ -132,31 +128,6 @@ func StartEthereum(ethereum *eth.Ethereum) { ...@@ -132,31 +128,6 @@ func StartEthereum(ethereum *eth.Ethereum) {
}) })
} }
func DefaultAssetPath() string {
var assetPath string
// If the current working directory is the go-ethereum dir
// assume a debug build and use the source directory as
// asset directory.
pwd, _ := os.Getwd()
if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") {
assetPath = path.Join(pwd, "assets")
} else {
switch runtime.GOOS {
case "darwin":
// Get Binary Directory
exedir, _ := osext.ExecutableFolder()
assetPath = filepath.Join(exedir, "../Resources")
case "linux":
assetPath = "/usr/share/mist"
case "windows":
assetPath = "./assets"
default:
assetPath = "."
}
}
return assetPath
}
func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) { func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
var err error var err error
...@@ -272,7 +243,7 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error { ...@@ -272,7 +243,7 @@ func BlockDo(ethereum *eth.Ethereum, hash []byte) error {
parent := ethereum.ChainManager().GetBlock(block.ParentHash()) parent := ethereum.ChainManager().GetBlock(block.ParentHash())
statedb := state.New(parent.Root(), ethereum.Db()) statedb := state.New(parent.Root(), ethereum.Db())
_, err := ethereum.BlockProcessor().TransitionState(statedb, parent, block) _, err := ethereum.BlockProcessor().TransitionState(statedb, parent, block, true)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -48,9 +48,8 @@ type BlockProcessor struct { ...@@ -48,9 +48,8 @@ type BlockProcessor struct {
func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor { func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
sm := &BlockProcessor{ sm := &BlockProcessor{
db: db, db: db,
mem: make(map[string]*big.Int), mem: make(map[string]*big.Int),
//Pow: &ethash.Ethash{},
Pow: ezp.New(), Pow: ezp.New(),
bc: chainManager, bc: chainManager,
eventMux: eventMux, eventMux: eventMux,
...@@ -60,12 +59,12 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM ...@@ -60,12 +59,12 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM
return sm return sm
} }
func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block) (receipts types.Receipts, err error) { func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) {
coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase) coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase)
coinbase.SetGasPool(CalcGasLimit(parent, block)) coinbase.SetGasPool(block.Header().GasLimit)
// Process the transactions on to parent state // Process the transactions on to parent state
receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), false) receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -100,10 +99,10 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated ...@@ -100,10 +99,10 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
// Notify all subscribers // Notify all subscribers
if !transientProcess { if !transientProcess {
go self.eventMux.Post(TxPostEvent{tx}) go self.eventMux.Post(TxPostEvent{tx})
logs := statedb.Logs()
go self.eventMux.Post(logs)
} }
go self.eventMux.Post(statedb.Logs())
return receipt, txGas, err return receipt, txGas, err
} }
...@@ -179,7 +178,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big ...@@ -179,7 +178,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
return return
} }
receipts, err := sm.TransitionState(state, parent, block) receipts, err := sm.TransitionState(state, parent, block, false)
if err != nil { if err != nil {
return return
} }
...@@ -248,6 +247,11 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { ...@@ -248,6 +247,11 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd) return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd)
} }
expl := CalcGasLimit(parent, block)
if expl.Cmp(block.Header().GasLimit) != 0 {
return fmt.Errorf("GasLimit check failed for block %v, %v", block.Header().GasLimit, expl)
}
if block.Time() < parent.Time() { if block.Time() < parent.Time() {
return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time) return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time)
} }
...@@ -316,13 +320,10 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro ...@@ -316,13 +320,10 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
var ( var (
parent = sm.bc.GetBlock(block.Header().ParentHash) parent = sm.bc.GetBlock(block.Header().ParentHash)
//state = state.New(parent.Trie().Copy()) state = state.New(parent.Root(), sm.db)
state = state.New(parent.Root(), sm.db)
) )
defer state.Reset() sm.TransitionState(state, parent, block, true)
sm.TransitionState(state, parent, block)
sm.AccumulateRewards(state, block, parent) sm.AccumulateRewards(state, block, parent)
return state.Logs(), nil return state.Logs(), nil
......
package core
import (
"fmt"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/state"
"math/big"
)
// So we can generate blocks easily
type FakePow struct{}
func (f FakePow) Search(block pow.Block, stop <-chan struct{}) []byte { return nil }
func (f FakePow) Verify(block pow.Block) bool { return true }
func (f FakePow) GetHashrate() int64 { return 0 }
func (f FakePow) Turbo(bool) {}
func NewBlockFromParent(addr []byte, parent *types.Block) *types.Block {
return newBlockFromParent(addr, parent)
}
func MakeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database) *types.Block {
return makeBlock(bman, parent, i, db)
}
func MakeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database) types.Blocks {
return makeChain(bman, parent, max, db)
}
func NewChainMan(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager {
return newChainManager(block, eventMux, db)
}
func NewBlockProc(db ethutil.Database, txpool *TxPool, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
return newBlockProcessor(db, txpool, cman, eventMux)
}
func NewCanonical(n int, db ethutil.Database) (*BlockProcessor, error) {
return newCanonical(n, db)
}
func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
block := types.NewBlock(parent.Hash(), addr, parent.Root(), ethutil.BigPow(2, 32), nil, "")
block.SetUncles(nil)
block.SetTransactions(nil)
block.SetReceipts(nil)
header := block.Header()
header.Difficulty = CalcDifficulty(block, parent)
header.Number = new(big.Int).Add(parent.Header().Number, ethutil.Big1)
header.GasLimit = CalcGasLimit(parent, block)
block.Td = parent.Td
return block
}
// Actually make a block by simulating what miner would do
func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database) *types.Block {
addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20)
block := newBlockFromParent(addr, parent)
state := state.New(block.Root(), db)
cbase := state.GetOrNewStateObject(addr)
cbase.SetGasPool(CalcGasLimit(parent, block))
cbase.AddBalance(BlockReward)
state.Update(ethutil.Big0)
block.SetRoot(state.Root())
return block
}
// Make a chain with real blocks
// Runs ProcessWithParent to get proper state roots
func makeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database) types.Blocks {
bman.bc.currentBlock = parent
blocks := make(types.Blocks, max)
for i := 0; i < max; i++ {
block := makeBlock(bman, parent, i, db)
td, err := bman.processWithParent(block, parent)
if err != nil {
fmt.Println("process with parent failed", err)
panic(err)
}
block.Td = td
blocks[i] = block
parent = block
fmt.Printf("New Block: %x\n", block.Hash())
}
fmt.Println("Done making chain")
return blocks
}
// Create a new chain manager starting from given block
// Effectively a fork factory
func newChainManager(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager {
bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: eventMux}
if block == nil {
bc.Reset()
} else {
bc.currentBlock = block
bc.td = block.Td
}
return bc
}
// block processor with fake pow
func newBlockProcessor(db ethutil.Database, txpool *TxPool, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
bman := NewBlockProcessor(db, txpool, newChainManager(nil, eventMux, db), eventMux)
bman.Pow = FakePow{}
return bman
}
// Make a new canonical chain by running InsertChain
// on result of makeChain
func newCanonical(n int, db ethutil.Database) (*BlockProcessor, error) {
eventMux := &event.TypeMux{}
txpool := NewTxPool(eventMux)
bman := newBlockProcessor(db, txpool, newChainManager(nil, eventMux, db), eventMux)
bman.bc.SetProcessor(bman)
parent := bman.bc.CurrentBlock()
if n == 0 {
return bman, nil
}
lchain := makeChain(bman, parent, n, db)
bman.bc.InsertChain(lchain)
return bman, nil
}
...@@ -85,12 +85,14 @@ type ChainManager struct { ...@@ -85,12 +85,14 @@ type ChainManager struct {
lastBlockHash []byte lastBlockHash []byte
transState *state.StateDB transState *state.StateDB
txState *state.StateDB
} }
func NewChainManager(db ethutil.Database, mux *event.TypeMux) *ChainManager { func NewChainManager(db ethutil.Database, mux *event.TypeMux) *ChainManager {
bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: mux} bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: mux}
bc.setLastBlock() bc.setLastBlock()
bc.transState = bc.State().Copy() bc.transState = bc.State().Copy()
bc.txState = bc.State().Copy()
return bc return bc
} }
...@@ -138,6 +140,19 @@ func (self *ChainManager) TransState() *state.StateDB { ...@@ -138,6 +140,19 @@ func (self *ChainManager) TransState() *state.StateDB {
return self.transState return self.transState
} }
func (self *ChainManager) TxState() *state.StateDB {
self.tsmu.RLock()
defer self.tsmu.RUnlock()
return self.txState
}
func (self *ChainManager) setTxState(state *state.StateDB) {
self.tsmu.Lock()
defer self.tsmu.Unlock()
self.txState = state
}
func (self *ChainManager) setTransState(statedb *state.StateDB) { func (self *ChainManager) setTransState(statedb *state.StateDB) {
self.transState = statedb self.transState = statedb
} }
...@@ -268,7 +283,6 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain ...@@ -268,7 +283,6 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain
break break
} }
} }
fmt.Printf("get hash %x (%d)\n", hash, len(chain))
return return
} }
...@@ -363,6 +377,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { ...@@ -363,6 +377,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
defer self.tsmu.Unlock() defer self.tsmu.Unlock()
for _, block := range chain { for _, block := range chain {
// Call in to the block processor and check for errors. It's likely that if one block fails
// all others will fail too (unless a known block is returned).
td, err := self.processor.Process(block) td, err := self.processor.Process(block)
if err != nil { if err != nil {
if IsKnownBlockErr(err) { if IsKnownBlockErr(err) {
...@@ -377,11 +393,15 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { ...@@ -377,11 +393,15 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
} }
block.Td = td block.Td = td
var chain, split bool var canonical, split bool
self.mu.Lock() self.mu.Lock()
{ {
// Write block to database. Eventually we'll have to improve on this and throw away blocks that are
// not in the canonical chain.
self.write(block) self.write(block)
cblock := self.currentBlock cblock := self.currentBlock
// Compare the TD of the last known block in the canonical chain to make sure it's greater.
// At this point it's possible that a different chain (fork) becomes the new canonical chain.
if td.Cmp(self.td) > 0 { if td.Cmp(self.td) > 0 {
if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 { if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, ethutil.Big1)) < 0 {
chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td) chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td)
...@@ -391,17 +411,18 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { ...@@ -391,17 +411,18 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
self.setTotalDifficulty(td) self.setTotalDifficulty(td)
self.insert(block) self.insert(block)
chain = true canonical = true
} }
} }
self.mu.Unlock() self.mu.Unlock()
if chain { if canonical {
self.setTransState(state.New(block.Root(), self.db))
self.eventMux.Post(ChainEvent{block, td}) self.eventMux.Post(ChainEvent{block, td})
} }
if split { if split {
self.setTransState(state.New(block.Root(), self.db)) self.setTxState(state.New(block.Root(), self.db))
self.eventMux.Post(ChainSplitEvent{block}) self.eventMux.Post(ChainSplitEvent{block})
} }
} }
......
...@@ -3,6 +3,7 @@ package core ...@@ -3,6 +3,7 @@ package core
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"math/big"
"os" "os"
"path" "path"
"runtime" "runtime"
...@@ -13,7 +14,9 @@ import ( ...@@ -13,7 +14,9 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/state"
) )
func init() { func init() {
...@@ -21,6 +24,61 @@ func init() { ...@@ -21,6 +24,61 @@ func init() {
ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH") ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH")
} }
// Test fork of length N starting from block i
func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big.Int)) {
fmt.Println("Testing Fork!")
var b *types.Block = nil
if i > 0 {
b = bman.bc.GetBlockByNumber(uint64(i))
}
_ = b
// switch databases to process the new chain
db, err := ethdb.NewMemDatabase()
if err != nil {
t.Fatal("Failed to create db:", err)
}
// copy old chain up to i into new db with deterministic canonical
bman2, err := newCanonical(i, db)
if err != nil {
t.Fatal("could not make new canonical in testFork", err)
}
bman2.bc.SetProcessor(bman2)
parent := bman2.bc.CurrentBlock()
chainB := makeChain(bman2, parent, N, db)
bman2.bc.InsertChain(chainB)
tdpre := bman.bc.Td()
td, err := testChain(chainB, bman)
if err != nil {
t.Fatal("expected chainB not to give errors:", err)
}
// Compare difficulties
f(tdpre, td)
}
func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) {
td := new(big.Int)
for _, block := range chainB {
td2, err := bman.bc.processor.Process(block)
if err != nil {
if IsKnownBlockErr(err) {
continue
}
return nil, err
}
block.Td = td2
td = td2
bman.bc.mu.Lock()
{
bman.bc.write(block)
}
bman.bc.mu.Unlock()
}
return td, nil
}
func loadChain(fn string, t *testing.T) (types.Blocks, error) { func loadChain(fn string, t *testing.T) (types.Blocks, error) {
fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm) fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm)
if err != nil { if err != nil {
...@@ -45,6 +103,128 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t * ...@@ -45,6 +103,128 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *
done <- true done <- true
} }
func TestExtendCanonical(t *testing.T) {
db, err := ethdb.NewMemDatabase()
if err != nil {
t.Fatal("Failed to create db:", err)
}
// make first chain starting from genesis
bman, err := newCanonical(5, db)
if err != nil {
t.Fatal("Could not make new canonical chain:", err)
}
f := func(td1, td2 *big.Int) {
if td2.Cmp(td1) <= 0 {
t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
}
}
// Start fork from current height (5)
testFork(t, bman, 5, 1, f)
testFork(t, bman, 5, 2, f)
testFork(t, bman, 5, 5, f)
testFork(t, bman, 5, 10, f)
}
func TestShorterFork(t *testing.T) {
db, err := ethdb.NewMemDatabase()
if err != nil {
t.Fatal("Failed to create db:", err)
}
// make first chain starting from genesis
bman, err := newCanonical(10, db)
if err != nil {
t.Fatal("Could not make new canonical chain:", err)
}
f := func(td1, td2 *big.Int) {
if td2.Cmp(td1) >= 0 {
t.Error("expected chainB to have lower difficulty. Got", td2, "expected less than", td1)
}
}
// Sum of numbers must be less than 10
// for this to be a shorter fork
testFork(t, bman, 0, 3, f)
testFork(t, bman, 0, 7, f)
testFork(t, bman, 1, 1, f)
testFork(t, bman, 1, 7, f)
testFork(t, bman, 5, 3, f)
testFork(t, bman, 5, 4, f)
}
func TestLongerFork(t *testing.T) {
db, err := ethdb.NewMemDatabase()
if err != nil {
t.Fatal("Failed to create db:", err)
}
// make first chain starting from genesis
bman, err := newCanonical(10, db)
if err != nil {
t.Fatal("Could not make new canonical chain:", err)
}
f := func(td1, td2 *big.Int) {
if td2.Cmp(td1) <= 0 {
t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
}
}
// Sum of numbers must be greater than 10
// for this to be a longer fork
testFork(t, bman, 0, 11, f)
testFork(t, bman, 0, 15, f)
testFork(t, bman, 1, 10, f)
testFork(t, bman, 1, 12, f)
testFork(t, bman, 5, 6, f)
testFork(t, bman, 5, 8, f)
}
func TestEqualFork(t *testing.T) {
db, err := ethdb.NewMemDatabase()
if err != nil {
t.Fatal("Failed to create db:", err)
}
bman, err := newCanonical(10, db)
if err != nil {
t.Fatal("Could not make new canonical chain:", err)
}
f := func(td1, td2 *big.Int) {
if td2.Cmp(td1) != 0 {
t.Error("expected chainB to have equal difficulty. Got", td2, "expected ", td1)
}
}
// Sum of numbers must be equal to 10
// for this to be an equal fork
testFork(t, bman, 1, 9, f)
testFork(t, bman, 2, 8, f)
testFork(t, bman, 5, 5, f)
testFork(t, bman, 6, 4, f)
testFork(t, bman, 9, 1, f)
}
func TestBrokenChain(t *testing.T) {
db, err := ethdb.NewMemDatabase()
if err != nil {
t.Fatal("Failed to create db:", err)
}
bman, err := newCanonical(10, db)
if err != nil {
t.Fatal("Could not make new canonical chain:", err)
}
db2, err := ethdb.NewMemDatabase()
if err != nil {
t.Fatal("Failed to create db:", err)
}
bman2, err := newCanonical(10, db2)
if err != nil {
t.Fatal("Could not make new canonical chain:", err)
}
bman2.bc.SetProcessor(bman2)
parent := bman2.bc.CurrentBlock()
chainB := makeChain(bman2, parent, 5, db2)
chainB = chainB[1:]
_, err = testChain(chainB, bman)
if err == nil {
t.Error("expected broken chain to return error")
}
}
func TestChainInsertions(t *testing.T) { func TestChainInsertions(t *testing.T) {
t.Skip() // travil fails. t.Skip() // travil fails.
......
...@@ -111,14 +111,14 @@ func (self *Filter) Find() state.Logs { ...@@ -111,14 +111,14 @@ func (self *Filter) Find() state.Logs {
// current parameters // current parameters
if self.bloomFilter(block) { if self.bloomFilter(block) {
// Get the logs of the block // Get the logs of the block
logs, err := self.eth.BlockProcessor().GetLogs(block) unfiltered, err := self.eth.BlockProcessor().GetLogs(block)
if err != nil { if err != nil {
chainlogger.Warnln("err: filter get logs ", err) chainlogger.Warnln("err: filter get logs ", err)
break break
} }
logs = append(logs, self.FilterLogs(logs)...) logs = append(logs, self.FilterLogs(unfiltered)...)
} }
block = self.eth.ChainManager().GetBlock(block.ParentHash()) block = self.eth.ChainManager().GetBlock(block.ParentHash())
...@@ -146,7 +146,6 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs { ...@@ -146,7 +146,6 @@ func (self *Filter) FilterLogs(logs state.Logs) state.Logs {
Logs: Logs:
for _, log := range logs { for _, log := range logs {
if !includes(self.address, log.Address()) { if !includes(self.address, log.Address()) {
//if !bytes.Equal(self.address, log.Address()) {
continue continue
} }
......
...@@ -126,7 +126,7 @@ func (self *StateTransition) BuyGas() error { ...@@ -126,7 +126,7 @@ func (self *StateTransition) BuyGas() error {
self.AddGas(self.msg.Gas()) self.AddGas(self.msg.Gas())
self.initialGas.Set(self.msg.Gas()) self.initialGas.Set(self.msg.Gas())
sender.SubAmount(MessageGasValue(self.msg)) sender.SubBalance(MessageGasValue(self.msg))
return nil return nil
} }
...@@ -251,7 +251,7 @@ func (self *StateTransition) RefundGas() { ...@@ -251,7 +251,7 @@ func (self *StateTransition) RefundGas() {
coinbase, sender := self.Coinbase(), self.From() coinbase, sender := self.Coinbase(), self.From()
// Return remaining gas // Return remaining gas
remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice()) remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice())
sender.AddAmount(remaining) sender.AddBalance(remaining)
uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2) uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2)
for addr, ref := range self.state.Refunds() { for addr, ref := range self.state.Refunds() {
......
...@@ -117,8 +117,13 @@ func (self *TxPool) add(tx *types.Transaction) error { ...@@ -117,8 +117,13 @@ func (self *TxPool) add(tx *types.Transaction) error {
} else { } else {
to = "[NEW_CONTRACT]" to = "[NEW_CONTRACT]"
} }
var from string
txplogger.Debugf("(t) %x => %s (%v) %x\n", tx.From()[:4], to, tx.Value, tx.Hash()) if len(tx.From()) > 0 {
from = ethutil.Bytes2Hex(tx.From()[:4])
} else {
from = "INVALID"
}
txplogger.Debugf("(t) %x => %s (%v) %x\n", from, to, tx.Value, tx.Hash())
// Notify the subscribers // Notify the subscribers
go self.eventMux.Post(TxPreEvent{tx}) go self.eventMux.Post(TxPreEvent{tx})
......
...@@ -30,7 +30,6 @@ import ( ...@@ -30,7 +30,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"os/user"
"path" "path"
) )
...@@ -48,12 +47,6 @@ type keyStorePlain struct { ...@@ -48,12 +47,6 @@ type keyStorePlain struct {
keysDirPath string keysDirPath string
} }
// TODO: copied from cmd/ethereum/flags.go
func DefaultDataDir() string {
usr, _ := user.Current()
return path.Join(usr.HomeDir, ".ethereum")
}
func NewKeyStorePlain(path string) KeyStore2 { func NewKeyStorePlain(path string) KeyStore2 {
return &keyStorePlain{path} return &keyStorePlain{path}
} }
...@@ -126,8 +119,11 @@ func GetKeyAddresses(keysDirPath string) (addresses [][]byte, err error) { ...@@ -126,8 +119,11 @@ func GetKeyAddresses(keysDirPath string) (addresses [][]byte, err error) {
} }
addresses = make([][]byte, len(fileInfos)) addresses = make([][]byte, len(fileInfos))
for i, fileInfo := range fileInfos { for i, fileInfo := range fileInfos {
addresses[i] = make([]byte, 40) address, err := hex.DecodeString(fileInfo.Name())
addresses[i] = []byte(fileInfo.Name()) if err != nil {
continue
}
addresses[i] = address
} }
return addresses, err return addresses, err
} }
...@@ -2,12 +2,13 @@ package crypto ...@@ -2,12 +2,13 @@ package crypto
import ( import (
"github.com/ethereum/go-ethereum/crypto/randentropy" "github.com/ethereum/go-ethereum/crypto/randentropy"
"github.com/ethereum/go-ethereum/ethutil"
"reflect" "reflect"
"testing" "testing"
) )
func TestKeyStorePlain(t *testing.T) { func TestKeyStorePlain(t *testing.T) {
ks := NewKeyStorePlain(DefaultDataDir()) ks := NewKeyStorePlain(ethutil.DefaultDataDir())
pass := "" // not used but required by API pass := "" // not used but required by API
k1, err := ks.GenerateNewKey(randentropy.Reader, pass) k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
if err != nil { if err != nil {
...@@ -35,7 +36,7 @@ func TestKeyStorePlain(t *testing.T) { ...@@ -35,7 +36,7 @@ func TestKeyStorePlain(t *testing.T) {
} }
func TestKeyStorePassphrase(t *testing.T) { func TestKeyStorePassphrase(t *testing.T) {
ks := NewKeyStorePassphrase(DefaultDataDir()) ks := NewKeyStorePassphrase(ethutil.DefaultDataDir())
pass := "foo" pass := "foo"
k1, err := ks.GenerateNewKey(randentropy.Reader, pass) k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
if err != nil { if err != nil {
...@@ -61,7 +62,7 @@ func TestKeyStorePassphrase(t *testing.T) { ...@@ -61,7 +62,7 @@ func TestKeyStorePassphrase(t *testing.T) {
} }
func TestKeyStorePassphraseDecryptionFail(t *testing.T) { func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
ks := NewKeyStorePassphrase(DefaultDataDir()) ks := NewKeyStorePassphrase(ethutil.DefaultDataDir())
pass := "foo" pass := "foo"
k1, err := ks.GenerateNewKey(randentropy.Reader, pass) k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
if err != nil { if err != nil {
...@@ -89,7 +90,7 @@ func TestImportPreSaleKey(t *testing.T) { ...@@ -89,7 +90,7 @@ func TestImportPreSaleKey(t *testing.T) {
// python pyethsaletool.py genwallet // python pyethsaletool.py genwallet
// with password "foo" // with password "foo"
fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}" fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}"
ks := NewKeyStorePassphrase(DefaultDataDir()) ks := NewKeyStorePassphrase(ethutil.DefaultDataDir())
pass := "foo" pass := "foo"
_, err := ImportPreSaleKey(ks, []byte(fileContent), pass) _, err := ImportPreSaleKey(ks, []byte(fileContent), pass)
if err != nil { if err != nil {
......
...@@ -3,6 +3,8 @@ package eth ...@@ -3,6 +3,8 @@ package eth
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"fmt" "fmt"
"io/ioutil"
"path"
"strings" "strings"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
...@@ -25,7 +27,10 @@ var ( ...@@ -25,7 +27,10 @@ var (
jsonlogger = ethlogger.NewJsonLogger() jsonlogger = ethlogger.NewJsonLogger()
defaultBootNodes = []*discover.Node{ defaultBootNodes = []*discover.Node{
// ETH/DEV cmd/bootnode
discover.MustParseNode("enode://6cdd090303f394a1cac34ecc9f7cda18127eafa2a3a06de39f6d920b0e583e062a7362097c7c65ee490a758b442acd5c80c6fce4b148c6a391e946b45131365b@54.169.166.226:30303"), discover.MustParseNode("enode://6cdd090303f394a1cac34ecc9f7cda18127eafa2a3a06de39f6d920b0e583e062a7362097c7c65ee490a758b442acd5c80c6fce4b148c6a391e946b45131365b@54.169.166.226:30303"),
// ETH/DEV cpp-ethereum (poc-8.ethdev.com)
discover.MustParseNode("enode://4a44599974518ea5b0f14c31c4463692ac0329cb84851f3435e6d1b18ee4eae4aa495f846a0fa1219bd58035671881d44423876e57db2abd57254d0197da0ebe@5.1.83.226:30303"),
} }
) )
...@@ -77,6 +82,27 @@ func (cfg *Config) parseBootNodes() []*discover.Node { ...@@ -77,6 +82,27 @@ func (cfg *Config) parseBootNodes() []*discover.Node {
return ns return ns
} }
func (cfg *Config) nodeKey() (*ecdsa.PrivateKey, error) {
// use explicit key from command line args if set
if cfg.NodeKey != nil {
return cfg.NodeKey, nil
}
// use persistent key if present
keyfile := path.Join(cfg.DataDir, "nodekey")
key, err := crypto.LoadECDSA(keyfile)
if err == nil {
return key, nil
}
// no persistent key, generate and store a new one
if key, err = crypto.GenerateKey(); err != nil {
return nil, fmt.Errorf("could not generate server key: %v", err)
}
if err := ioutil.WriteFile(keyfile, crypto.FromECDSA(key), 0600); err != nil {
logger.Errorln("could not persist nodekey: ", err)
}
return key, nil
}
type Ethereum struct { type Ethereum struct {
// Channel for shutting down the ethereum // Channel for shutting down the ethereum
shutdownChan chan bool shutdownChan chan bool
...@@ -121,7 +147,8 @@ func New(config *Config) (*Ethereum, error) { ...@@ -121,7 +147,8 @@ func New(config *Config) (*Ethereum, error) {
d, _ := db.Get([]byte("ProtocolVersion")) d, _ := db.Get([]byte("ProtocolVersion"))
protov := ethutil.NewValue(d).Uint() protov := ethutil.NewValue(d).Uint()
if protov != ProtocolVersion && protov != 0 { if protov != ProtocolVersion && protov != 0 {
return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, ethutil.Config.ExecPath+"/database") path := path.Join(config.DataDir, "database")
return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, path)
} }
// Create new keymanager // Create new keymanager
...@@ -161,18 +188,16 @@ func New(config *Config) (*Ethereum, error) { ...@@ -161,18 +188,16 @@ func New(config *Config) (*Ethereum, error) {
insertChain := eth.chainManager.InsertChain insertChain := eth.chainManager.InsertChain
eth.blockPool = NewBlockPool(hasBlock, insertChain, ezp.Verify) eth.blockPool = NewBlockPool(hasBlock, insertChain, ezp.Verify)
netprv, err := config.nodeKey()
if err != nil {
return nil, err
}
ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool) ethProto := EthProtocol(eth.txPool, eth.chainManager, eth.blockPool)
protocols := []p2p.Protocol{ethProto} protocols := []p2p.Protocol{ethProto}
if config.Shh { if config.Shh {
protocols = append(protocols, eth.whisper.Protocol()) protocols = append(protocols, eth.whisper.Protocol())
} }
netprv := config.NodeKey
if netprv == nil {
if netprv, err = crypto.GenerateKey(); err != nil {
return nil, fmt.Errorf("could not generate server key: %v", err)
}
}
eth.net = &p2p.Server{ eth.net = &p2p.Server{
PrivateKey: netprv, PrivateKey: netprv,
Name: config.Name, Name: config.Name,
......
...@@ -3,10 +3,51 @@ package ethutil ...@@ -3,10 +3,51 @@ package ethutil
import ( import (
"fmt" "fmt"
"math/big" "math/big"
"os"
"os/user"
"path"
"path/filepath"
"runtime" "runtime"
"time" "time"
"github.com/kardianos/osext"
) )
func DefaultAssetPath() string {
var assetPath string
// 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()
if runtime.GOOS == "darwin" {
return path.Join(usr.HomeDir, "Library/Ethereum")
} else if runtime.GOOS == "windows" {
return path.Join(usr.HomeDir, "AppData/Roaming/Ethereum")
} else {
return path.Join(usr.HomeDir, ".ethereum")
}
}
func IsWindows() bool { func IsWindows() bool {
return runtime.GOOS == "windows" return runtime.GOOS == "windows"
} }
......
...@@ -3,7 +3,6 @@ package filter ...@@ -3,7 +3,6 @@ package filter
// TODO make use of the generic filtering system // TODO make use of the generic filtering system
import ( import (
"fmt"
"sync" "sync"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
...@@ -75,7 +74,6 @@ out: ...@@ -75,7 +74,6 @@ out:
case event := <-events.Chan(): case event := <-events.Chan():
switch event := event.(type) { switch event := event.(type) {
case core.ChainEvent: case core.ChainEvent:
fmt.Println("filter start")
self.filterMu.RLock() self.filterMu.RLock()
for _, filter := range self.filters { for _, filter := range self.filters {
if filter.BlockCallback != nil { if filter.BlockCallback != nil {
...@@ -83,7 +81,6 @@ out: ...@@ -83,7 +81,6 @@ out:
} }
} }
self.filterMu.RUnlock() self.filterMu.RUnlock()
fmt.Println("filter stop")
case core.PendingBlockEvent: case core.PendingBlockEvent:
self.filterMu.RLock() self.filterMu.RLock()
......
...@@ -29,6 +29,3 @@ if ls $dir/*.go &> /dev/null; then ...@@ -29,6 +29,3 @@ if ls $dir/*.go &> /dev/null; then
fi fi
fi fi
done done
go tool cover -func profile.cov
...@@ -197,7 +197,7 @@ gasLimit: ...@@ -197,7 +197,7 @@ gasLimit:
} }
self.eth.TxPool().RemoveSet(remove) self.eth.TxPool().RemoveSet(remove)
self.current.coinbase.AddAmount(core.BlockReward) self.current.coinbase.AddBalance(core.BlockReward)
self.current.state.Update(ethutil.Big0) self.current.state.Update(ethutil.Big0)
self.push() self.push()
...@@ -225,7 +225,7 @@ func (self *worker) commitUncle(uncle *types.Header) error { ...@@ -225,7 +225,7 @@ func (self *worker) commitUncle(uncle *types.Header) error {
} }
uncleAccount := self.current.state.GetAccount(uncle.Coinbase) uncleAccount := self.current.state.GetAccount(uncle.Coinbase)
uncleAccount.AddAmount(uncleReward) uncleAccount.AddBalance(uncleReward)
self.current.coinbase.AddBalance(uncleReward) self.current.coinbase.AddBalance(uncleReward)
......
This diff is collapsed.
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
) )
func TestFilterClose(t *testing.T) { func TestFilterClose(t *testing.T) {
t.Skip()
api := &EthereumApi{ api := &EthereumApi{
logs: make(map[int]*logFilter), logs: make(map[int]*logFilter),
messages: make(map[int]*whisperFilter), messages: make(map[int]*whisperFilter),
......
...@@ -19,14 +19,7 @@ func (obj *GetBlockArgs) UnmarshalJSON(b []byte) (err error) { ...@@ -19,14 +19,7 @@ func (obj *GetBlockArgs) UnmarshalJSON(b []byte) (err error) {
obj.Hash = argstr obj.Hash = argstr
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
}
func (obj *GetBlockArgs) requirements() error {
if obj.BlockNumber == 0 && obj.Hash == "" {
return NewErrorResponse("GetBlock requires either a block 'number' or a block 'hash' as argument")
}
return nil
} }
type NewTxArgs struct { type NewTxArgs struct {
...@@ -64,7 +57,7 @@ func (obj *NewTxArgs) UnmarshalJSON(b []byte) (err error) { ...@@ -64,7 +57,7 @@ func (obj *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
type PushTxArgs struct { type PushTxArgs struct {
...@@ -77,12 +70,12 @@ func (obj *PushTxArgs) UnmarshalJSON(b []byte) (err error) { ...@@ -77,12 +70,12 @@ func (obj *PushTxArgs) UnmarshalJSON(b []byte) (err error) {
obj.Tx = arg0 obj.Tx = arg0
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
func (a *PushTxArgs) requirementsPushTx() error { func (a *PushTxArgs) requirementsPushTx() error {
if a.Tx == "" { if a.Tx == "" {
return NewErrorResponse("PushTx requires a 'tx' as argument") return NewErrorWithMessage(errArguments, "PushTx requires a 'tx' as argument")
} }
return nil return nil
} }
...@@ -93,14 +86,14 @@ type GetStorageArgs struct { ...@@ -93,14 +86,14 @@ type GetStorageArgs struct {
func (obj *GetStorageArgs) UnmarshalJSON(b []byte) (err error) { func (obj *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
if err = json.Unmarshal(b, &obj.Address); err != nil { if err = json.Unmarshal(b, &obj.Address); err != nil {
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
return return
} }
func (a *GetStorageArgs) requirements() error { func (a *GetStorageArgs) requirements() error {
if len(a.Address) == 0 { if len(a.Address) == 0 {
return NewErrorResponse("GetStorageAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'address' value as argument")
} }
return nil return nil
} }
...@@ -116,64 +109,39 @@ func (obj *GetStateArgs) UnmarshalJSON(b []byte) (err error) { ...@@ -116,64 +109,39 @@ func (obj *GetStateArgs) UnmarshalJSON(b []byte) (err error) {
obj.Address = arg0 obj.Address = arg0
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
func (a *GetStateArgs) requirements() error { func (a *GetStateArgs) requirements() error {
if a.Address == "" { if a.Address == "" {
return NewErrorResponse("GetStorageAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'address' value as argument")
} }
if a.Key == "" { if a.Key == "" {
return NewErrorResponse("GetStorageAt requires an 'key' value as argument") return NewErrorWithMessage(errArguments, "GetStorageAt requires an 'key' value as argument")
} }
return nil return nil
} }
type GetStorageAtRes struct {
Key string `json:"key"`
Value string `json:"value"`
}
type GetTxCountArgs struct { type GetTxCountArgs struct {
Address string `json:"address"` Address string `json:"address"`
} }
// type GetTxCountRes struct {
// Nonce int `json:"nonce"`
// }
func (obj *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) { func (obj *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
arg0 := "" arg0 := ""
if err = json.Unmarshal(b, &arg0); err == nil { if err = json.Unmarshal(b, &arg0); err == nil {
obj.Address = arg0 obj.Address = arg0
return return
} }
return NewErrorResponse("Could not determine JSON parameters") return errDecodeArgs
} }
func (a *GetTxCountArgs) requirements() error { func (a *GetTxCountArgs) requirements() error {
if a.Address == "" { if a.Address == "" {
return NewErrorResponse("GetTxCountAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetTxCountAt requires an 'address' value as argument")
} }
return nil return nil
} }
// type GetPeerCountRes struct {
// PeerCount int `json:"peerCount"`
// }
// type GetListeningRes struct {
// IsListening bool `json:"isListening"`
// }
// type GetCoinbaseRes struct {
// Coinbase string `json:"coinbase"`
// }
// type GetMiningRes struct {
// IsMining bool `json:"isMining"`
// }
type GetBalanceArgs struct { type GetBalanceArgs struct {
Address string Address string
} }
...@@ -184,21 +152,16 @@ func (obj *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) { ...@@ -184,21 +152,16 @@ func (obj *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
obj.Address = arg0 obj.Address = arg0
return return
} }
return NewErrorResponse("Could not determine JSON parameters") return errDecodeArgs
} }
func (a *GetBalanceArgs) requirements() error { func (a *GetBalanceArgs) requirements() error {
if a.Address == "" { if a.Address == "" {
return NewErrorResponse("GetBalanceAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetBalanceAt requires an 'address' value as argument")
} }
return nil return nil
} }
type BalanceRes struct {
Balance string `json:"balance"`
Address string `json:"address"`
}
type GetCodeAtArgs struct { type GetCodeAtArgs struct {
Address string Address string
} }
...@@ -209,12 +172,12 @@ func (obj *GetCodeAtArgs) UnmarshalJSON(b []byte) (err error) { ...@@ -209,12 +172,12 @@ func (obj *GetCodeAtArgs) UnmarshalJSON(b []byte) (err error) {
obj.Address = arg0 obj.Address = arg0
return return
} }
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
func (a *GetCodeAtArgs) requirements() error { func (a *GetCodeAtArgs) requirements() error {
if a.Address == "" { if a.Address == "" {
return NewErrorResponse("GetCodeAt requires an 'address' value as argument") return NewErrorWithMessage(errArguments, "GetCodeAt requires an 'address' value as argument")
} }
return nil return nil
} }
...@@ -225,7 +188,7 @@ type Sha3Args struct { ...@@ -225,7 +188,7 @@ type Sha3Args struct {
func (obj *Sha3Args) UnmarshalJSON(b []byte) (err error) { func (obj *Sha3Args) UnmarshalJSON(b []byte) (err error) {
if err = json.Unmarshal(b, &obj.Data); err != nil { if err = json.Unmarshal(b, &obj.Data); err != nil {
return NewErrorResponse(ErrorDecodeArgs) return errDecodeArgs
} }
return return
} }
...@@ -277,10 +240,10 @@ type DbArgs struct { ...@@ -277,10 +240,10 @@ type DbArgs struct {
func (a *DbArgs) requirements() error { func (a *DbArgs) requirements() error {
if len(a.Database) == 0 { if len(a.Database) == 0 {
return NewErrorResponse("DbPutArgs requires an 'Database' value as argument") return NewErrorWithMessage(errArguments, "DbPutArgs requires an 'Database' value as argument")
} }
if len(a.Key) == 0 { if len(a.Key) == 0 {
return NewErrorResponse("DbPutArgs requires an 'Key' value as argument") return NewErrorWithMessage(errArguments, "DbPutArgs requires an 'Key' value as argument")
} }
return nil return nil
} }
......
...@@ -92,7 +92,7 @@ func (s *RpcHttpServer) apiHandler(api *rpc.EthereumApi) http.Handler { ...@@ -92,7 +92,7 @@ func (s *RpcHttpServer) apiHandler(api *rpc.EthereumApi) http.Handler {
reqParsed, reqerr := JSON.ParseRequestBody(req) reqParsed, reqerr := JSON.ParseRequestBody(req)
if reqerr != nil { if reqerr != nil {
jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest} jsonerr := &rpc.RpcErrorObject{-32700, "Error: Could not parse request"}
JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr}) JSON.Send(w, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
return return
} }
......
This diff is collapsed.
...@@ -82,8 +82,9 @@ type RpcServer interface { ...@@ -82,8 +82,9 @@ type RpcServer interface {
type Log struct { type Log struct {
Address string `json:"address"` Address string `json:"address"`
Topic []string `json:"topics"` Topic []string `json:"topic"`
Data string `json:"data"` Data string `json:"data"`
Number uint64 `json:"number"`
} }
func toLogs(logs state.Logs) (ls []Log) { func toLogs(logs state.Logs) (ls []Log) {
...@@ -94,6 +95,7 @@ func toLogs(logs state.Logs) (ls []Log) { ...@@ -94,6 +95,7 @@ func toLogs(logs state.Logs) (ls []Log) {
l.Topic = make([]string, len(log.Topics())) l.Topic = make([]string, len(log.Topics()))
l.Address = toHex(log.Address()) l.Address = toHex(log.Address())
l.Data = toHex(log.Data()) l.Data = toHex(log.Data())
l.Number = log.Number()
for j, topic := range log.Topics() { for j, topic := range log.Topics() {
l.Topic[j] = toHex(topic) l.Topic[j] = toHex(topic)
} }
...@@ -106,6 +108,7 @@ func toLogs(logs state.Logs) (ls []Log) { ...@@ -106,6 +108,7 @@ func toLogs(logs state.Logs) (ls []Log) {
type whisperFilter struct { type whisperFilter struct {
messages []xeth.WhisperMessage messages []xeth.WhisperMessage
timeout time.Time timeout time.Time
id int
} }
func (w *whisperFilter) add(msgs ...xeth.WhisperMessage) { func (w *whisperFilter) add(msgs ...xeth.WhisperMessage) {
...@@ -121,6 +124,7 @@ func (w *whisperFilter) get() []xeth.WhisperMessage { ...@@ -121,6 +124,7 @@ func (w *whisperFilter) get() []xeth.WhisperMessage {
type logFilter struct { type logFilter struct {
logs state.Logs logs state.Logs
timeout time.Time timeout time.Time
id int
} }
func (l *logFilter) add(logs ...state.Log) { func (l *logFilter) add(logs ...state.Log) {
......
...@@ -99,7 +99,7 @@ func sockHandler(api *rpc.EthereumApi) websocket.Handler { ...@@ -99,7 +99,7 @@ func sockHandler(api *rpc.EthereumApi) websocket.Handler {
// reqParsed, reqerr := JSON.ParseRequestBody(conn.Request()) // reqParsed, reqerr := JSON.ParseRequestBody(conn.Request())
if err := websocket.JSON.Receive(conn, &reqParsed); err != nil { if err := websocket.JSON.Receive(conn, &reqParsed); err != nil {
jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest} jsonerr := &rpc.RpcErrorObject{-32700, "Error: Could not parse request"}
JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr}) JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
continue continue
} }
......
...@@ -35,7 +35,7 @@ func (self *StateDB) Dump() []byte { ...@@ -35,7 +35,7 @@ func (self *StateDB) Dump() []byte {
storageIt := stateObject.State.trie.Iterator() storageIt := stateObject.State.trie.Iterator()
for storageIt.Next() { for storageIt.Next() {
account.Storage[ethutil.Bytes2Hex(it.Key)] = ethutil.Bytes2Hex(it.Value) account.Storage[ethutil.Bytes2Hex(storageIt.Key)] = ethutil.Bytes2Hex(storageIt.Value)
} }
world.Accounts[ethutil.Bytes2Hex(it.Key)] = account world.Accounts[ethutil.Bytes2Hex(it.Key)] = account
} }
......
...@@ -12,16 +12,19 @@ type Log interface { ...@@ -12,16 +12,19 @@ type Log interface {
Address() []byte Address() []byte
Topics() [][]byte Topics() [][]byte
Data() []byte Data() []byte
Number() uint64
} }
type StateLog struct { type StateLog struct {
address []byte address []byte
topics [][]byte topics [][]byte
data []byte data []byte
number uint64
} }
func NewLog(address []byte, topics [][]byte, data []byte) *StateLog { func NewLog(address []byte, topics [][]byte, data []byte, number uint64) *StateLog {
return &StateLog{address, topics, data} return &StateLog{address, topics, data, number}
} }
func (self *StateLog) Address() []byte { func (self *StateLog) Address() []byte {
...@@ -36,6 +39,10 @@ func (self *StateLog) Data() []byte { ...@@ -36,6 +39,10 @@ func (self *StateLog) Data() []byte {
return self.data return self.data
} }
func (self *StateLog) Number() uint64 {
return self.number
}
func NewLogFromValue(decoder *ethutil.Value) *StateLog { func NewLogFromValue(decoder *ethutil.Value) *StateLog {
log := &StateLog{ log := &StateLog{
address: decoder.Get(0).Bytes(), address: decoder.Get(0).Bytes(),
......
...@@ -19,6 +19,14 @@ func (self Code) String() string { ...@@ -19,6 +19,14 @@ func (self Code) String() string {
type Storage map[string]*ethutil.Value type Storage map[string]*ethutil.Value
func (self Storage) String() (str string) {
for key, value := range self {
str += fmt.Sprintf("%X : %X\n", key, value.Bytes())
}
return
}
func (self Storage) Copy() Storage { func (self Storage) Copy() Storage {
cpy := make(Storage) cpy := make(Storage)
for key, value := range self { for key, value := range self {
...@@ -119,10 +127,9 @@ func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value { ...@@ -119,10 +127,9 @@ func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value {
} }
func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) { func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) {
self.SetState(key.Bytes(), value) self.SetState(key.Bytes(), value)
self.dirty = true
} }
func (self *StateObject) Storage() map[string]*ethutil.Value { func (self *StateObject) Storage() Storage {
return self.storage return self.storage
} }
...@@ -172,20 +179,22 @@ func (c *StateObject) AddBalance(amount *big.Int) { ...@@ -172,20 +179,22 @@ func (c *StateObject) AddBalance(amount *big.Int) {
statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount) statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount)
} }
func (c *StateObject) AddAmount(amount *big.Int) { c.AddBalance(amount) }
func (c *StateObject) SubBalance(amount *big.Int) { func (c *StateObject) SubBalance(amount *big.Int) {
c.SetBalance(new(big.Int).Sub(c.balance, amount)) c.SetBalance(new(big.Int).Sub(c.balance, amount))
statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount) statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount)
} }
func (c *StateObject) SubAmount(amount *big.Int) { c.SubBalance(amount) }
func (c *StateObject) SetBalance(amount *big.Int) { func (c *StateObject) SetBalance(amount *big.Int) {
c.balance = amount c.balance = amount
c.dirty = true c.dirty = true
} }
func (c *StateObject) St() Storage {
return c.storage
}
// //
// Gas setters and getters // Gas setters and getters
// //
...@@ -198,7 +207,7 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error { ...@@ -198,7 +207,7 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error {
return fmt.Errorf("insufficient amount: %v, %v", c.balance, total) return fmt.Errorf("insufficient amount: %v, %v", c.balance, total)
} }
c.SubAmount(total) c.SubBalance(total)
c.dirty = true c.dirty = true
...@@ -221,7 +230,7 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error { ...@@ -221,7 +230,7 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error {
rGas := new(big.Int).Set(gas) rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price) rGas.Mul(rGas, price)
self.AddAmount(rGas) self.AddBalance(rGas)
self.dirty = true self.dirty = true
......
package ui
// ReturnInterface is returned by the Intercom interface when a method is called
type ReturnInterface interface {
Get(i int) (interface{}, error)
Size() int
}
// Frontend is the basic interface for calling arbitrary methods on something that
// implements a front end (GUI, CLI, etc)
type Frontend interface {
// Checks whether a specific method is implemented
Supports(method string) bool
// Call calls the given method on interface it implements. This will return
// an error with errNotImplemented if the method hasn't been implemented
// and will return a ReturnInterface if it does.
Call(method string) (ReturnInterface, error)
}
...@@ -54,6 +54,7 @@ type Log struct { ...@@ -54,6 +54,7 @@ type Log struct {
address []byte address []byte
topics [][]byte topics [][]byte
data []byte data []byte
log uint64
} }
func (self *Log) Address() []byte { func (self *Log) Address() []byte {
...@@ -68,6 +69,10 @@ func (self *Log) Data() []byte { ...@@ -68,6 +69,10 @@ func (self *Log) Data() []byte {
return self.data return self.data
} }
func (self *Log) Number() uint64 {
return self.log
}
func (self *Log) RlpData() interface{} { func (self *Log) RlpData() interface{} {
return []interface{}{self.address, ethutil.ByteSliceToInterface(self.topics), self.data} return []interface{}{self.address, ethutil.ByteSliceToInterface(self.topics), self.data}
} }
......
...@@ -578,7 +578,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I ...@@ -578,7 +578,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
} }
data := mem.Get(mStart.Int64(), mSize.Int64()) data := mem.Get(mStart.Int64(), mSize.Int64())
log := &Log{context.Address(), topics, data} log := &Log{context.Address(), topics, data, self.env.BlockNumber().Uint64()}
self.env.AddLog(log) self.env.AddLog(log)
self.Printf(" => %v", log) self.Printf(" => %v", log)
...@@ -664,6 +664,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I ...@@ -664,6 +664,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
} }
addr = ref.Address() addr = ref.Address()
fmt.Printf("CREATE %X\n", addr)
stack.Push(ethutil.BigD(addr)) stack.Push(ethutil.BigD(addr))
} }
...@@ -727,7 +728,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I ...@@ -727,7 +728,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self.Printf(" => (%x) %v", receiver.Address()[:4], balance) self.Printf(" => (%x) %v", receiver.Address()[:4], balance)
receiver.AddAmount(balance) receiver.AddBalance(balance)
statedb.Delete(context.Address()) statedb.Delete(context.Address())
fallthrough fallthrough
...@@ -779,9 +780,9 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo ...@@ -779,9 +780,9 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
// Stack Check, memory resize & gas phase // Stack Check, memory resize & gas phase
switch op { switch op {
// Stack checks only // Stack checks only
case ISZERO, CALLDATALOAD, POP, JUMP, NOT: // 1 case ISZERO, CALLDATALOAD, POP, JUMP, NOT, EXTCODESIZE, BLOCKHASH: // 1
stack.require(1) stack.require(1)
case JUMPI, ADD, SUB, DIV, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE, SIGNEXTEND: // 2 case JUMPI, ADD, SUB, DIV, MUL, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE, SIGNEXTEND: // 2
stack.require(2) stack.require(2)
case ADDMOD, MULMOD: // 3 case ADDMOD, MULMOD: // 3
stack.require(3) stack.require(3)
...@@ -828,7 +829,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo ...@@ -828,7 +829,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
// 0 => non 0 // 0 => non 0
mult = ethutil.Big3 mult = ethutil.Big3
} else if len(val) > 0 && len(y.Bytes()) == 0 { } else if len(val) > 0 && len(y.Bytes()) == 0 {
statedb.Refund(caller.Address(), GasSStoreRefund) statedb.Refund(self.env.Origin(), GasSStoreRefund)
mult = ethutil.Big0 mult = ethutil.Big0
} else { } else {
...@@ -859,7 +860,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo ...@@ -859,7 +860,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2]) newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
additionalGas.Set(stack.data[stack.Len()-2]) additionalGas.Set(stack.data[stack.Len()-2])
case CALLDATACOPY: case CALLDATACOPY:
stack.require(2) stack.require(3)
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3]) newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
additionalGas.Set(stack.data[stack.Len()-3]) additionalGas.Set(stack.data[stack.Len()-3])
......
...@@ -127,6 +127,10 @@ func (self *Whisper) Watch(opts Filter) int { ...@@ -127,6 +127,10 @@ func (self *Whisper) Watch(opts Filter) int {
}) })
} }
func (self *Whisper) Unwatch(id int) {
self.filters.Uninstall(id)
}
func (self *Whisper) Messages(id int) (messages []*Message) { func (self *Whisper) Messages(id int) (messages []*Message) {
filter := self.filters.Get(id) filter := self.filters.Get(id)
if filter != nil { if filter != nil {
......
...@@ -3,19 +3,20 @@ package xeth ...@@ -3,19 +3,20 @@ package xeth
import "github.com/ethereum/go-ethereum/state" import "github.com/ethereum/go-ethereum/state"
type State struct { type State struct {
xeth *XEth xeth *XEth
state *state.StateDB
} }
func NewState(xeth *XEth) *State { func NewState(xeth *XEth, statedb *state.StateDB) *State {
return &State{xeth} return &State{xeth, statedb}
} }
func (self *State) State() *state.StateDB { func (self *State) State() *state.StateDB {
return self.xeth.chainManager.TransState() return self.state
} }
func (self *State) Get(addr string) *Object { func (self *State) Get(addr string) *Object {
return &Object{self.State().GetStateObject(fromHex(addr))} return &Object{self.state.GetStateObject(fromHex(addr))}
} }
func (self *State) SafeGet(addr string) *Object { func (self *State) SafeGet(addr string) *Object {
...@@ -23,7 +24,7 @@ func (self *State) SafeGet(addr string) *Object { ...@@ -23,7 +24,7 @@ func (self *State) SafeGet(addr string) *Object {
} }
func (self *State) safeGet(addr string) *state.StateObject { func (self *State) safeGet(addr string) *state.StateObject {
object := self.State().GetStateObject(fromHex(addr)) object := self.state.GetStateObject(fromHex(addr))
if object == nil { if object == nil {
object = state.NewStateObject(fromHex(addr), self.xeth.eth.Db()) object = state.NewStateObject(fromHex(addr), self.xeth.eth.Db())
} }
......
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/whisper" "github.com/ethereum/go-ethereum/whisper"
) )
...@@ -54,13 +55,26 @@ func New(eth Backend) *XEth { ...@@ -54,13 +55,26 @@ func New(eth Backend) *XEth {
whisper: NewWhisper(eth.Whisper()), whisper: NewWhisper(eth.Whisper()),
miner: eth.Miner(), miner: eth.Miner(),
} }
xeth.state = NewState(xeth) xeth.state = NewState(xeth, xeth.chainManager.TransState())
return xeth return xeth
} }
func (self *XEth) Backend() Backend { return self.eth } func (self *XEth) Backend() Backend { return self.eth }
func (self *XEth) State() *State { return self.state } func (self *XEth) UseState(statedb *state.StateDB) *XEth {
xeth := &XEth{
eth: self.eth,
blockProcessor: self.blockProcessor,
chainManager: self.chainManager,
whisper: self.whisper,
miner: self.miner,
}
xeth.state = NewState(xeth, statedb)
return xeth
}
func (self *XEth) State() *State { return self.state }
func (self *XEth) Whisper() *Whisper { return self.whisper } func (self *XEth) Whisper() *Whisper { return self.whisper }
func (self *XEth) Miner() *miner.Miner { return self.miner } func (self *XEth) Miner() *miner.Miner { return self.miner }
...@@ -229,7 +243,7 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st ...@@ -229,7 +243,7 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st
} }
var ( var (
statedb = self.chainManager.TransState() statedb = self.State().State() //self.chainManager.TransState()
key = self.eth.KeyManager().KeyPair() key = self.eth.KeyManager().KeyPair()
from = statedb.GetOrNewStateObject(key.Address()) from = statedb.GetOrNewStateObject(key.Address())
block = self.chainManager.CurrentBlock() block = self.chainManager.CurrentBlock()
...@@ -277,7 +291,7 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string) ...@@ -277,7 +291,7 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string)
} }
var err error var err error
state := self.eth.ChainManager().TransState() state := self.eth.ChainManager().TxState()
if balance := state.GetBalance(key.Address()); balance.Cmp(tx.Value()) < 0 { if balance := state.GetBalance(key.Address()); balance.Cmp(tx.Value()) < 0 {
return "", fmt.Errorf("insufficient balance. balance=%v tx=%v", balance, tx.Value()) return "", fmt.Errorf("insufficient balance. balance=%v tx=%v", balance, tx.Value())
} }
...@@ -288,13 +302,11 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string) ...@@ -288,13 +302,11 @@ func (self *XEth) Transact(toStr, valueStr, gasStr, gasPriceStr, codeStr string)
//fmt.Printf("create tx: %x %v\n", tx.Hash()[:4], tx.Nonce()) //fmt.Printf("create tx: %x %v\n", tx.Hash()[:4], tx.Nonce())
/* // Do some pre processing for our "pre" events and hooks
// Do some pre processing for our "pre" events and hooks //block := self.chainManager.NewBlock(key.Address())
block := self.chainManager.NewBlock(key.Address()) //coinbase := state.GetOrNewStateObject(key.Address())
coinbase := state.GetOrNewStateObject(key.Address()) //coinbase.SetGasPool(block.GasLimit())
coinbase.SetGasPool(block.GasLimit()) //self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true)
self.blockProcessor.ApplyTransactions(coinbase, state, block, types.Transactions{tx}, true)
*/
err = self.eth.TxPool().Add(tx) err = self.eth.TxPool().Add(tx)
if err != nil { if err != nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment