aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--ethchain/dagger.go11
-rw-r--r--ethchain/state.go11
-rw-r--r--ethchain/state_manager.go58
-rw-r--r--ethchain/state_object.go93
-rw-r--r--ethchain/state_transition.go47
-rw-r--r--ethchain/transaction.go8
-rw-r--r--ethchain/vm.go22
-rw-r--r--ethcrypto/mnemonic.go29
-rw-r--r--ethereum.go26
-rw-r--r--ethlog/loggers.go2
-rw-r--r--ethminer/miner.go34
-rw-r--r--ethpub/pub.go13
-rw-r--r--ethpub/types.go6
-rw-r--r--ethtrie/trie.go35
-rw-r--r--ethtrie/trie_test.go115
-rw-r--r--ethutil/bytes.go16
-rw-r--r--ethutil/config.go1
-rw-r--r--ethutil/value.go21
-rw-r--r--peer.go13
20 files changed, 403 insertions, 160 deletions
diff --git a/README.md b/README.md
index 3ef9bba70..69c6eb0ad 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ Ethereum
Ethereum Go Development package (C) Jeffrey Wilcke
Ethereum is currently in its testing phase. The current state is "Proof
-of Concept 0.5.16". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)).
+of Concept 0.5.20". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)).
Ethereum Go is split up in several sub packages Please refer to each
individual package for more information.
diff --git a/ethchain/dagger.go b/ethchain/dagger.go
index adf1c2f05..917b3d722 100644
--- a/ethchain/dagger.go
+++ b/ethchain/dagger.go
@@ -17,10 +17,16 @@ var powlogger = ethlog.NewLogger("POW")
type PoW interface {
Search(block *Block, reactChan chan ethreact.Event) []byte
Verify(hash []byte, diff *big.Int, nonce []byte) bool
+ GetHashrate() int64
}
type EasyPow struct {
- hash *big.Int
+ hash *big.Int
+ HashRate int64
+}
+
+func (pow *EasyPow) GetHashrate() int64 {
+ return pow.HashRate
}
func (pow *EasyPow) Search(block *Block, reactChan chan ethreact.Event) []byte {
@@ -40,7 +46,8 @@ func (pow *EasyPow) Search(block *Block, reactChan chan ethreact.Event) []byte {
if i%1234567 == 0 {
elapsed := time.Now().UnixNano() - start
hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000
- powlogger.Infoln("Hashing @", int64(hashes), "khash")
+ pow.HashRate = int64(hashes)
+ powlogger.Infoln("Hashing @", int64(pow.HashRate), "khash")
}
sha := ethcrypto.Sha3Bin(big.NewInt(r.Int63()).Bytes())
diff --git a/ethchain/state.go b/ethchain/state.go
index 8df79dcef..684b81102 100644
--- a/ethchain/state.go
+++ b/ethchain/state.go
@@ -76,6 +76,8 @@ func (self *State) DeleteStateObject(stateObject *StateObject) {
// Retrieve a state object given my the address. Nil if not found
func (self *State) GetStateObject(addr []byte) *StateObject {
+ addr = ethutil.Address(addr)
+
stateObject := self.stateObjects[string(addr)]
if stateObject != nil {
return stateObject
@@ -145,7 +147,6 @@ func (self *State) Set(state *State) {
self.trie = state.trie
self.stateObjects = state.stateObjects
- //*self = *state
}
func (s *State) Root() interface{} {
@@ -173,7 +174,7 @@ func (s *State) Reset() {
func (s *State) Sync() {
// Sync all nested states
for _, stateObject := range s.stateObjects {
- s.UpdateStateObject(stateObject)
+ //s.UpdateStateObject(stateObject)
if stateObject.state == nil {
continue
@@ -205,6 +206,8 @@ func (self *State) Update() {
// FIXME trie delete is broken
valid, t2 := ethtrie.ParanoiaCheck(self.trie)
if !valid {
+ statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.trie.Root, t2.Root)
+
self.trie = t2
}
}
@@ -212,9 +215,9 @@ func (self *State) Update() {
// Debug stuff
func (self *State) CreateOutputForDiff() {
for addr, stateObject := range self.stateObjects {
- fmt.Printf("0x%x 0x%x 0x%x 0x%x\n", addr, stateObject.state.Root(), stateObject.Amount.Bytes(), stateObject.Nonce)
+ fmt.Printf("%x %x %x %x\n", addr, stateObject.state.Root(), stateObject.Amount.Bytes(), stateObject.Nonce)
stateObject.state.EachStorage(func(addr string, value *ethutil.Value) {
- fmt.Printf("0x%x 0x%x\n", addr, value.Bytes())
+ fmt.Printf("%x %x\n", addr, value.Bytes())
})
}
}
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 3eafd2d6e..6bd3edd0d 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -7,7 +7,6 @@ import (
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethreact"
- "github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
"math/big"
@@ -121,7 +120,10 @@ func (self *StateManager) ProcessTransactions(coinbase *StateObject, state *Stat
done:
for i, tx := range txs {
txGas := new(big.Int).Set(tx.Gas)
- st := NewStateTransition(coinbase, tx, state, block)
+
+ cb := state.GetStateObject(coinbase.Address())
+ st := NewStateTransition(cb, tx, state, block)
+ //fmt.Printf("#%d\n", i+1)
err = st.TransitionState()
if err != nil {
switch {
@@ -149,10 +151,17 @@ done:
accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas))
receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative}
+ if i < len(block.Receipts()) {
+ original := block.Receipts()[i]
+ if !original.Cmp(receipt) {
+ return nil, nil, nil, fmt.Errorf("err diff #%d (r) %v ~ %x <=> (c) %v ~ %x (%x)\n", i+1, original.CumulativeGasUsed, original.PostState[0:4], receipt.CumulativeGasUsed, receipt.PostState[0:4], receipt.Tx.Hash())
+ }
+ }
+
receipts = append(receipts, receipt)
handled = append(handled, tx)
- if ethutil.Config.Diff {
+ if ethutil.Config.Diff && ethutil.Config.DiffType == "all" {
state.CreateOutputForDiff()
}
}
@@ -188,36 +197,11 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
// before that.
defer state.Reset()
- if ethutil.Config.Diff {
- fmt.Printf("## 0x%x 0x%x ##\n", block.Hash(), block.Number)
+ if ethutil.Config.Diff && ethutil.Config.DiffType == "all" {
+ fmt.Printf("## %x %x ##\n", block.Hash(), block.Number)
}
- receipts, err := sm.ApplyDiff(state, parent, block)
- defer func() {
- if err != nil {
- if len(receipts) == len(block.Receipts()) {
- for i, receipt := range block.Receipts() {
- statelogger.Infof("diff (r) %v ~ %x <=> (c) %v ~ %x (%x)\n", receipt.CumulativeGasUsed, receipt.PostState[0:4], receipts[i].CumulativeGasUsed, receipts[i].PostState[0:4], receipt.Tx.Hash())
- }
- } else {
- statelogger.Warnln("Unable to print receipt diff. Length didn't match", len(receipts), "for", len(block.Receipts()))
- }
- } else {
- /*
- for i, receipt := range receipts {
- gu := new(big.Int)
- if i != 0 {
- gu.Sub(receipt.CumulativeGasUsed, receipts[i-1].CumulativeGasUsed)
- } else {
- gu.Set(receipt.CumulativeGasUsed)
- }
-
- statelogger.Infof("[r] %v ~ %x (%x)\n", gu, receipt.PostState[0:4], receipt.Tx.Hash())
- }
- */
- }
- }()
-
+ _, err = sm.ApplyDiff(state, parent, block)
if err != nil {
return err
}
@@ -235,12 +219,14 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
return err
}
- if ethutil.Config.Paranoia {
- valid, _ := ethtrie.ParanoiaCheck(state.trie)
- if !valid {
- err = fmt.Errorf("PARANOIA: World state trie corruption")
+ /*
+ if ethutil.Config.Paranoia {
+ valid, _ := ethtrie.ParanoiaCheck(state.trie)
+ if !valid {
+ err = fmt.Errorf("PARANOIA: World state trie corruption")
+ }
}
- }
+ */
if !block.State().Cmp(state) {
diff --git a/ethchain/state_object.go b/ethchain/state_object.go
index ebc050863..8e7b5fece 100644
--- a/ethchain/state_object.go
+++ b/ethchain/state_object.go
@@ -15,6 +15,18 @@ func (self Code) String() string {
return strings.Join(Disassemble(self), " ")
}
+type Storage map[string]*ethutil.Value
+
+func (self Storage) Copy() Storage {
+ cpy := make(Storage)
+ for key, value := range self {
+ // XXX Do we need a 'value' copy or is this sufficient?
+ cpy[key] = value
+ }
+
+ return cpy
+}
+
type StateObject struct {
// Address of the object
address []byte
@@ -27,7 +39,7 @@ type StateObject struct {
script Code
initScript Code
- storage map[string]*ethutil.Value
+ storage Storage
// Total gas pool is the total amount of gas currently
// left if this object is the coinbase. Gas is directly
@@ -41,7 +53,8 @@ type StateObject struct {
}
func (self *StateObject) Reset() {
- self.storage = make(map[string]*ethutil.Value)
+ self.storage = make(Storage)
+ self.state.Reset()
}
// Converts an transaction in to a state object
@@ -62,11 +75,12 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
func NewStateObject(addr []byte) *StateObject {
// This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter.
- address := ethutil.LeftPadBytes(addr, 20)
+ address := ethutil.Address(addr)
object := &StateObject{address: address, Amount: new(big.Int), gasPool: new(big.Int)}
object.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, ""))
- object.storage = make(map[string]*ethutil.Value)
+ object.storage = make(Storage)
+ object.gasPool = new(big.Int)
return object
}
@@ -79,13 +93,6 @@ func NewContract(address []byte, Amount *big.Int, root []byte) *StateObject {
return contract
}
-// Returns a newly created account
-func NewAccount(address []byte, amount *big.Int) *StateObject {
- account := &StateObject{address: address, Amount: amount, Nonce: 0}
-
- return account
-}
-
func NewStateObjectFromBytes(address, data []byte) *StateObject {
object := &StateObject{address: address}
object.RlpDecode(data)
@@ -95,7 +102,7 @@ func NewStateObjectFromBytes(address, data []byte) *StateObject {
func (self *StateObject) MarkForDeletion() {
self.remove = true
- statelogger.Infof("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.Amount)
+ statelogger.DebugDetailf("%x: #%d %v (deletion)\n", self.Address(), self.Nonce, self.Amount)
}
func (c *StateObject) GetAddr(addr []byte) *ethutil.Value {
@@ -113,36 +120,73 @@ func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) {
self.setStorage(key.Bytes(), value)
}
-func (self *StateObject) getStorage(key []byte) *ethutil.Value {
- k := ethutil.LeftPadBytes(key, 32)
+func (self *StateObject) getStorage(k []byte) *ethutil.Value {
+ key := ethutil.LeftPadBytes(k, 32)
- value := self.storage[string(k)]
+ value := self.storage[string(key)]
if value == nil {
- value = self.GetAddr(k)
+ value = self.GetAddr(key)
- self.storage[string(k)] = value
+ if !value.IsNil() {
+ self.storage[string(key)] = value
+ }
}
return value
+
+ //return self.GetAddr(key)
}
-func (self *StateObject) setStorage(key []byte, value *ethutil.Value) {
- k := ethutil.LeftPadBytes(key, 32)
+func (self *StateObject) setStorage(k []byte, value *ethutil.Value) {
+ key := ethutil.LeftPadBytes(k, 32)
+ self.storage[string(key)] = value.Copy()
- self.storage[string(k)] = value
+ /*
+ if value.BigInt().Cmp(ethutil.Big0) == 0 {
+ self.state.trie.Delete(string(key))
+ return
+ }
+
+ self.SetAddr(key, value)
+ */
}
func (self *StateObject) Sync() {
+ /*
+ fmt.Println("############# BEFORE ################")
+ self.state.EachStorage(func(key string, value *ethutil.Value) {
+ fmt.Printf("%x %x %x\n", self.Address(), []byte(key), value.Bytes())
+ })
+ fmt.Printf("%x @:%x\n", self.Address(), self.state.Root())
+ fmt.Println("#####################################")
+ */
for key, value := range self.storage {
- if value.BigInt().Cmp(ethutil.Big0) == 0 {
+ if value.Len() == 0 { // value.BigInt().Cmp(ethutil.Big0) == 0 {
+ //data := self.getStorage([]byte(key))
+ //fmt.Printf("deleting %x %x 0x%x\n", self.Address(), []byte(key), data)
self.state.trie.Delete(string(key))
continue
}
self.SetAddr([]byte(key), value)
+ }
+
+ valid, t2 := ethtrie.ParanoiaCheck(self.state.trie)
+ if !valid {
+ statelogger.Infof("Warn: PARANOIA: Different state storage root during copy %x vs %x\n", self.state.trie.Root, t2.Root)
+ self.state.trie = t2
}
+
+ /*
+ fmt.Println("############# AFTER ################")
+ self.state.EachStorage(func(key string, value *ethutil.Value) {
+ fmt.Printf("%x %x %x\n", self.Address(), []byte(key), value.Bytes())
+ })
+ */
+ //fmt.Printf("%x @:%x\n", self.Address(), self.state.Root())
}
+
func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
if int64(len(c.script)-1) < pc.Int64() {
return ethutil.NewValue(0)
@@ -154,13 +198,13 @@ func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
func (c *StateObject) AddAmount(amount *big.Int) {
c.SetAmount(new(big.Int).Add(c.Amount, amount))
- statelogger.Infof("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Amount, amount)
+ statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.Nonce, c.Amount, amount)
}
func (c *StateObject) SubAmount(amount *big.Int) {
c.SetAmount(new(big.Int).Sub(c.Amount, amount))
- statelogger.Infof("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Amount, amount)
+ statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.Nonce, c.Amount, amount)
}
func (c *StateObject) SetAmount(amount *big.Int) {
@@ -222,6 +266,8 @@ func (self *StateObject) Copy() *StateObject {
}
stateObject.script = ethutil.CopyBytes(self.script)
stateObject.initScript = ethutil.CopyBytes(self.initScript)
+ stateObject.storage = self.storage.Copy()
+ stateObject.gasPool.Set(self.gasPool)
return stateObject
}
@@ -280,6 +326,7 @@ func (c *StateObject) RlpDecode(data []byte) {
c.Amount = decoder.Get(1).BigInt()
c.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
c.storage = make(map[string]*ethutil.Value)
+ c.gasPool = new(big.Int)
c.ScriptHash = decoder.Get(3).Bytes()
diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go
index 314d858f2..8ed528c9f 100644
--- a/ethchain/state_transition.go
+++ b/ethchain/state_transition.go
@@ -2,8 +2,6 @@ package ethchain
import (
"fmt"
- "github.com/ethereum/eth-go/ethtrie"
- "github.com/ethereum/eth-go/ethutil"
"math/big"
)
@@ -44,7 +42,7 @@ func (self *StateTransition) Coinbase() *StateObject {
return self.cb
}
- self.cb = self.state.GetAccount(self.coinbase)
+ self.cb = self.state.GetOrNewStateObject(self.coinbase)
return self.cb
}
func (self *StateTransition) Sender() *StateObject {
@@ -52,7 +50,7 @@ func (self *StateTransition) Sender() *StateObject {
return self.sen
}
- self.sen = self.state.GetAccount(self.tx.Sender())
+ self.sen = self.state.GetOrNewStateObject(self.tx.Sender())
return self.sen
}
@@ -65,7 +63,7 @@ func (self *StateTransition) Receiver() *StateObject {
return self.rec
}
- self.rec = self.state.GetAccount(self.tx.Recipient)
+ self.rec = self.state.GetOrNewStateObject(self.tx.Recipient)
return self.rec
}
@@ -176,13 +174,16 @@ func (self *StateTransition) TransitionState() (err error) {
return
}
- /* FIXME
- * If tx goes TO "0", goes OOG during init, reverse changes, but initial endowment should happen. The ether is lost forever
- */
- var snapshot *State
+ if sender.Amount.Cmp(self.value) < 0 {
+ return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Amount)
+ }
+ var snapshot *State
// If the receiver is nil it's a contract (\0*32).
if tx.CreatesContract() {
+ // Subtract the (irreversible) amount from the senders account
+ sender.SubAmount(self.value)
+
snapshot = self.state.Copy()
// Create a new state object for the contract
@@ -191,16 +192,17 @@ func (self *StateTransition) TransitionState() (err error) {
if receiver == nil {
return fmt.Errorf("Unable to create contract")
}
+
+ // Add the amount to receivers account which should conclude this transaction
+ receiver.AddAmount(self.value)
} else {
receiver = self.Receiver()
- }
- // Transfer value from sender to receiver
- if err = self.transferValue(sender, receiver); err != nil {
- return
- }
+ // Subtract the amount from the senders account
+ sender.SubAmount(self.value)
+ // Add the amount to receivers account which should conclude this transaction
+ receiver.AddAmount(self.value)
- if snapshot == nil {
snapshot = self.state.Copy()
}
@@ -275,20 +277,5 @@ func (self *StateTransition) Eval(script []byte, context *StateObject, typ strin
func Call(vm *Vm, closure *Closure, data []byte) (ret []byte, err error) {
ret, _, err = closure.Call(vm, data)
- if ethutil.Config.Paranoia {
- var (
- context = closure.object
- trie = context.state.trie
- )
-
- valid, t2 := ethtrie.ParanoiaCheck(trie)
- if !valid {
- // TODO FIXME ASAP
- context.state.trie = t2
-
- statelogger.Infoln("Warn: PARANOIA: Different state object roots during copy")
- }
- }
-
return
}
diff --git a/ethchain/transaction.go b/ethchain/transaction.go
index da3f9bcf2..5686a7edb 100644
--- a/ethchain/transaction.go
+++ b/ethchain/transaction.go
@@ -227,6 +227,14 @@ func (self *Receipt) String() string {
self.CumulativeGasUsed)
}
+func (self *Receipt) Cmp(other *Receipt) bool {
+ if bytes.Compare(self.PostState, other.PostState) != 0 {
+ return false
+ }
+
+ return true
+}
+
// Transaction slice type for basic sorting
type Transactions []*Transaction
diff --git a/ethchain/vm.go b/ethchain/vm.go
index f1794ff77..4fdf8b31a 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -155,6 +155,15 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
// XXX Leave this Println intact. Don't change this to the log system.
// Used for creating diffs between implementations
if vm.logTy == LogTyDiff {
+ switch op {
+ case STOP, RETURN, SUICIDE:
+ closure.object.Sync()
+ closure.object.state.EachStorage(func(key string, value *ethutil.Value) {
+ value.Decode()
+ fmt.Printf("%x %x\n", new(big.Int).SetBytes([]byte(key)).Bytes(), value.Bytes())
+ })
+ }
+
b := pc.Bytes()
if len(b) == 0 {
b = []byte{0}
@@ -184,9 +193,9 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
var mult *big.Int
y, x := stack.Peekn()
val := closure.GetStorage(x)
- if val.IsEmpty() && len(y.Bytes()) > 0 {
+ if val.BigInt().Cmp(ethutil.Big0) == 0 && len(y.Bytes()) > 0 {
mult = ethutil.Big2
- } else if !val.IsEmpty() && len(y.Bytes()) == 0 {
+ } else if val.BigInt().Cmp(ethutil.Big0) != 0 && len(y.Bytes()) == 0 {
mult = ethutil.Big0
} else {
mult = ethutil.Big1
@@ -447,7 +456,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case BYTE:
require(2)
val, th := stack.Popn()
- if th.Cmp(big.NewInt(32)) < 0 {
+ if th.Cmp(big.NewInt(32)) < 0 && th.Cmp(big.NewInt(int64(len(val.Bytes())))) < 0 {
byt := big.NewInt(int64(val.Bytes()[th.Int64()]))
stack.Push(byt)
@@ -482,7 +491,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case ORIGIN:
stack.Push(ethutil.BigD(vm.vars.Origin))
- vm.Printf(" => %v", vm.vars.Origin)
+ vm.Printf(" => %x", vm.vars.Origin)
case CALLER:
caller := closure.caller.Address()
stack.Push(ethutil.BigD(caller))
@@ -550,10 +559,10 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
}
code := closure.Script[cOff : cOff+l]
- fmt.Println("len:", l, "code off:", cOff, "mem off:", mOff)
+ //fmt.Println("len:", l, "code off:", cOff, "mem off:", mOff)
mem.Set(mOff, l, code)
- fmt.Println(Code(mem.Get(mOff, l)))
+ //fmt.Println(Code(mem.Get(mOff, l)))
case GASPRICE:
stack.Push(closure.Price)
@@ -743,6 +752,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
if closure.object.Amount.Cmp(value) < 0 {
vmlogger.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Amount)
+
closure.ReturnGas(gas, nil, nil)
stack.Push(ethutil.BigFalse)
diff --git a/ethcrypto/mnemonic.go b/ethcrypto/mnemonic.go
index 725846792..b8df2ad6f 100644
--- a/ethcrypto/mnemonic.go
+++ b/ethcrypto/mnemonic.go
@@ -6,30 +6,35 @@ import (
"os"
"path"
"path/filepath"
- "runtime"
"strconv"
"strings"
)
-func InitWords() []string {
- _, thisfile, _, _ := runtime.Caller(1)
- filename := path.Join(path.Dir(thisfile), "mnemonic.words.lst")
+func InitWords(wordsPath string) {
+ filename := path.Join(wordsPath, "mnemonic.words.lst")
if _, err := os.Stat(filename); os.IsNotExist(err) {
- fmt.Printf("reading mnemonic word list file 'mnemonic.words.lst' from source folder failed, looking in current folder.")
- dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
- if err != nil {
- panic(fmt.Errorf("problem getting current folder: ", err))
- }
+ fmt.Printf("reading mnemonic word list file from supplied path not found. Looked in %s. Trying next option.\n", filename)
+
+ dir := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "eth-go", "ethcrypto")
filename = path.Join(dir, "mnemonic.words.lst")
+ if _, err := os.Stat(filename); os.IsNotExist(err) {
+ fmt.Printf("reading mnemonic word list file 'mnemonic.words.lst' from source folder failed: %s.\n", filename)
+ dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
+ if err != nil {
+ panic(fmt.Errorf("problem getting current folder: ", err))
+ }
+ filename = path.Join(dir, "mnemonic.words.lst")
+ }
}
+
content, err := ioutil.ReadFile(filename)
if err != nil {
- panic(fmt.Errorf("reading mnemonic word list file 'mnemonic.words.lst' failed: ", err))
+ panic(fmt.Errorf("All options for finding the mnemonic word list file 'mnemonic.words.lst' failed: ", err))
}
- return strings.Split(string(content), "\n")
+ words = strings.Split(string(content), "\n")
}
-var words = InitWords()
+var words []string
// TODO: See if we can refactor this into a shared util lib if we need it multiple times
func IndexOf(slice []string, value string) int64 {
diff --git a/ethereum.go b/ethereum.go
index c2d2f5241..c48ac00e4 100644
--- a/ethereum.go
+++ b/ethereum.go
@@ -81,6 +81,8 @@ type Ethereum struct {
keyManager *ethcrypto.KeyManager
clientIdentity ethwire.ClientIdentity
+
+ isUpToDate bool
}
func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager *ethcrypto.KeyManager, caps Caps, usePnp bool) (*Ethereum, error) {
@@ -108,6 +110,7 @@ func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager
nat: nat,
keyManager: keyManager,
clientIdentity: clientIdentity,
+ isUpToDate: true,
}
ethereum.reactor = ethreact.New()
@@ -158,7 +161,7 @@ func (s *Ethereum) IsUpToDate() bool {
upToDate := true
eachPeer(s.peers, func(peer *Peer, e *list.Element) {
if atomic.LoadInt32(&peer.connected) == 1 {
- if peer.catchingUp == true {
+ if peer.catchingUp == true && peer.versionKnown {
upToDate = false
}
}
@@ -373,6 +376,7 @@ func (s *Ethereum) Start(seed bool) {
// Start the reaping processes
go s.ReapDeadPeerHandler()
+ go s.update()
if seed {
s.Seed()
@@ -514,3 +518,23 @@ out:
ethlogger.Debugln("succesfully disestablished UPnP port mapping")
}
}
+
+func (self *Ethereum) update() {
+ upToDateTimer := time.NewTicker(1 * time.Second)
+
+out:
+ for {
+ select {
+ case <-upToDateTimer.C:
+ if self.IsUpToDate() && !self.isUpToDate {
+ self.reactor.Post("chainSync", false)
+ self.isUpToDate = true
+ } else if !self.IsUpToDate() && self.isUpToDate {
+ self.reactor.Post("chainSync", true)
+ self.isUpToDate = false
+ }
+ case <-self.quit:
+ break out
+ }
+ }
+}
diff --git a/ethlog/loggers.go b/ethlog/loggers.go
index 59021d169..b2760534b 100644
--- a/ethlog/loggers.go
+++ b/ethlog/loggers.go
@@ -119,7 +119,7 @@ func AddLogSystem(logSystem LogSystem) {
mutex.Lock()
defer mutex.Unlock()
if logSystems == nil {
- logMessages = make(chan *logMessage, 5)
+ logMessages = make(chan *logMessage, 10)
quit = make(chan chan error, 1)
drained = make(chan bool, 1)
go start()
diff --git a/ethminer/miner.go b/ethminer/miner.go
index 5151ee885..602ab0f35 100644
--- a/ethminer/miner.go
+++ b/ethminer/miner.go
@@ -21,28 +21,32 @@ type Miner struct {
block *ethchain.Block
powChan chan []byte
powQuitChan chan ethreact.Event
- quitChan chan bool
+ quitChan chan chan error
}
-func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner {
+func (self *Miner) GetPow() ethchain.PoW {
+ return self.pow
+}
+
+func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) *Miner {
miner := Miner{
pow: &ethchain.EasyPow{},
ethereum: ethereum,
coinbase: coinbase,
}
- // Insert initial TXs in our little miner 'pool'
- miner.txs = ethereum.TxPool().Flush()
- miner.block = ethereum.BlockChain().NewBlock(miner.coinbase)
-
- return miner
+ return &miner
}
func (miner *Miner) Start() {
miner.reactChan = make(chan ethreact.Event, 1) // This is the channel that receives 'updates' when ever a new transaction or block comes in
miner.powChan = make(chan []byte, 1) // This is the channel that receives valid sha hashes for a given block
miner.powQuitChan = make(chan ethreact.Event, 1) // This is the channel that can exit the miner thread
- miner.quitChan = make(chan bool, 1)
+ miner.quitChan = make(chan chan error, 1)
+
+ // Insert initial TXs in our little miner 'pool'
+ miner.txs = miner.ethereum.TxPool().Flush()
+ miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase)
// Prepare inital block
//miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State())
@@ -61,15 +65,17 @@ func (miner *Miner) Start() {
reactor.Subscribe("newTx:pre", miner.powQuitChan)
logger.Infoln("Started")
+
+ reactor.Post("miner:start", miner)
}
func (miner *Miner) listener() {
-out:
for {
select {
- case <-miner.quitChan:
+ case status := <-miner.quitChan:
logger.Infoln("Stopped")
- break out
+ status <- nil
+ return
case chanMessage := <-miner.reactChan:
if block, ok := chanMessage.Resource.(*ethchain.Block); ok {
@@ -127,7 +133,9 @@ out:
func (miner *Miner) Stop() {
logger.Infoln("Stopping...")
- miner.quitChan <- true
+ status := make(chan error)
+ miner.quitChan <- status
+ <-status
reactor := miner.ethereum.Reactor()
reactor.Unsubscribe("newBlock", miner.powQuitChan)
@@ -137,6 +145,8 @@ func (miner *Miner) Stop() {
close(miner.powQuitChan)
close(miner.quitChan)
+
+ reactor.Post("miner:stop", miner)
}
func (self *Miner) mineNewBlock() {
diff --git a/ethpub/pub.go b/ethpub/pub.go
index f409d136b..5d01a7a44 100644
--- a/ethpub/pub.go
+++ b/ethpub/pub.go
@@ -179,6 +179,19 @@ func FindAddressInNameReg(stateManager *ethchain.StateManager, name string) []by
return nil
}
+func FindNameInNameReg(stateManager *ethchain.StateManager, addr []byte) string {
+ nameReg := EthereumConfig(stateManager).NameReg()
+ if nameReg != nil {
+ addr = ethutil.LeftPadBytes(addr, 32)
+
+ reg := nameReg.GetStorage(ethutil.BigD(addr))
+
+ return strings.TrimRight(reg.Str(), "\x00")
+ }
+
+ return ""
+}
+
func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, scriptStr string) (*PReceipt, error) {
var hash []byte
var contractCreation bool
diff --git a/ethpub/types.go b/ethpub/types.go
index 5d41269c8..9e5159a4c 100644
--- a/ethpub/types.go
+++ b/ethpub/types.go
@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethcrypto"
+ "github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
"strings"
)
@@ -46,6 +47,7 @@ type PBlock struct {
Transactions string `json:"transactions"`
Time int64 `json:"time"`
Coinbase string `json:"coinbase"`
+ Name string `json:"name"`
GasLimit string `json:"gasLimit"`
GasUsed string `json:"gasUsed"`
}
@@ -212,6 +214,10 @@ func (c *PStateObject) IsContract() bool {
return false
}
+func (self *PStateObject) EachStorage(cb ethtrie.EachCallback) {
+ self.object.State().EachStorage(cb)
+}
+
type KeyVal struct {
Key string
Value string
diff --git a/ethtrie/trie.go b/ethtrie/trie.go
index 38c78e7f4..f0f3fe5a8 100644
--- a/ethtrie/trie.go
+++ b/ethtrie/trie.go
@@ -5,10 +5,12 @@ import (
"fmt"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethutil"
- "reflect"
+ _ "reflect"
"sync"
)
+func __ignore() { fmt.Println("") }
+
func ParanoiaCheck(t1 *Trie) (bool, *Trie) {
t2 := NewTrie(ethutil.Config.Db, "")
@@ -269,8 +271,7 @@ func (t *Trie) getState(node interface{}, key []int) interface{} {
}
// It shouldn't come this far
- fmt.Println("getState unexpected return")
- return ""
+ panic("unexpected return")
}
func (t *Trie) getNode(node interface{}) *ethutil.Value {
@@ -287,7 +288,9 @@ func (t *Trie) getNode(node interface{}) *ethutil.Value {
return ethutil.NewValueFromBytes([]byte(str))
}
- return t.cache.Get(n.Bytes())
+ data := t.cache.Get(n.Bytes())
+
+ return data
}
func (t *Trie) UpdateState(node interface{}, key []int, value string) interface{} {
@@ -323,7 +326,8 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter
// New node
n := ethutil.NewValue(node)
- if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
+ if node == nil || n.Len() == 0 {
+ //if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
newNode := []interface{}{CompactEncode(key), value}
return t.Put(newNode)
@@ -385,17 +389,22 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter
return t.Put(newNode)
}
- return ""
+ panic("unexpected end")
}
func (t *Trie) deleteState(node interface{}, key []int) interface{} {
if len(key) == 0 {
+ println("<empty ret>")
return ""
}
// New node
n := ethutil.NewValue(node)
- if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
+ //if node == nil || (n.Type() == reflect.String && (n.Str() == "" || n.Get(0).IsNil())) || n.Len() == 0 {
+ if node == nil || n.Len() == 0 {
+ //return nil
+ //fmt.Printf("<empty ret> %x %d\n", n, len(n.Bytes()))
+
return ""
}
@@ -408,10 +417,17 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
// Matching key pair (ie. there's already an object with this key)
if CompareIntSlice(k, key) {
+ //fmt.Printf("<delete ret> %x\n", v)
+
return ""
} else if CompareIntSlice(key[:len(k)], k) {
hash := t.deleteState(v, key[len(k):])
child := t.getNode(hash)
+ /*
+ if child.IsNil() {
+ return node
+ }
+ */
var newNode []interface{}
if child.Len() == 2 {
@@ -421,6 +437,8 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
newNode = []interface{}{currentNode.Get(0).Str(), hash}
}
+ //fmt.Printf("%x\n", newNode)
+
return t.Put(newNode)
} else {
return node
@@ -463,10 +481,11 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
newNode = n
}
+ //fmt.Printf("%x\n", newNode)
return t.Put(newNode)
}
- return ""
+ panic("unexpected return")
}
type TrieIterator struct {
diff --git a/ethtrie/trie_test.go b/ethtrie/trie_test.go
index a3d4547d7..3989a8f45 100644
--- a/ethtrie/trie_test.go
+++ b/ethtrie/trie_test.go
@@ -1,16 +1,17 @@
package ethtrie
import (
- "bytes"
- "encoding/hex"
- "encoding/json"
+ _ "bytes"
+ _ "encoding/hex"
+ _ "encoding/json"
"fmt"
- "io/ioutil"
- "math/rand"
- "net/http"
- "reflect"
+ "github.com/ethereum/eth-go/ethutil"
+ _ "io/ioutil"
+ _ "math/rand"
+ _ "net/http"
+ _ "reflect"
"testing"
- "time"
+ _ "time"
)
const LONG_WORD = "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ"
@@ -42,6 +43,7 @@ func New() (*MemDatabase, *Trie) {
return db, NewTrie(db, "")
}
+/*
func TestTrieSync(t *testing.T) {
db, trie := New()
@@ -251,8 +253,8 @@ func TestRemote(t *testing.T) {
trie.Update(get(key), get(value))
}
- a := NewValue(h(test.Root)).Bytes()
- b := NewValue(trie.Root).Bytes()
+ a := ethutil.NewValue(h(test.Root)).Bytes()
+ b := ethutil.NewValue(trie.Root).Bytes()
if bytes.Compare(a, b) != 0 {
t.Errorf("%-10s: %x %x", test.Name, a, b)
}
@@ -267,12 +269,12 @@ func TestTrieReplay(t *testing.T) {
}
_, trie2 := New()
- trie.NewIterator().Each(func(key string, v *Value) {
+ trie.NewIterator().Each(func(key string, v *ethutil.Value) {
trie2.Update(key, v.Str())
})
- a := NewValue(trie.Root).Bytes()
- b := NewValue(trie2.Root).Bytes()
+ a := ethutil.NewValue(trie.Root).Bytes()
+ b := ethutil.NewValue(trie2.Root).Bytes()
if bytes.Compare(a, b) != 0 {
t.Errorf("%s %x %x\n", test.Name, trie.Root, trie2.Root)
}
@@ -329,3 +331,90 @@ func TestRegression(t *testing.T) {
}
}
}
+
+func TestDelete(t *testing.T) {
+ _, trie := New()
+
+ trie.Update("a", "jeffreytestlongstring")
+ trie.Update("aa", "otherstring")
+ trie.Update("aaa", "othermorestring")
+ trie.Update("aabbbbccc", "hithere")
+ trie.Update("abbcccdd", "hstanoehutnaheoustnh")
+ trie.Update("rnthaoeuabbcccdd", "hstanoehutnaheoustnh")
+ trie.Update("rneuabbcccdd", "hstanoehutnaheoustnh")
+ trie.Update("rneuabboeusntahoeucccdd", "hstanoehutnaheoustnh")
+ trie.Update("rnxabboeusntahoeucccdd", "hstanoehutnaheoustnh")
+ trie.Delete("aaboaestnuhbccc")
+ trie.Delete("a")
+ trie.Update("a", "nthaonethaosentuh")
+ trie.Update("c", "shtaosntehua")
+ trie.Delete("a")
+ trie.Update("aaaa", "testmegood")
+
+ fmt.Println("aa =>", trie.Get("aa"))
+ _, t2 := New()
+ trie.NewIterator().Each(func(key string, v *ethutil.Value) {
+ if key == "aaaa" {
+ t2.Update(key, v.Str())
+ } else {
+ t2.Update(key, v.Str())
+ }
+ })
+
+ a := ethutil.NewValue(trie.Root).Bytes()
+ b := ethutil.NewValue(t2.Root).Bytes()
+
+ fmt.Printf("o: %x\nc: %x\n", a, b)
+}
+*/
+
+func TestRndCase(t *testing.T) {
+ _, trie := New()
+
+ data := []struct{ k, v string }{
+ {"0000000000000000000000000000000000000000000000000000000000000001", "a07573657264617461000000000000000000000000000000000000000000000000"},
+ {"0000000000000000000000000000000000000000000000000000000000000003", "8453bb5b31"},
+ {"0000000000000000000000000000000000000000000000000000000000000004", "850218711a00"},
+ {"0000000000000000000000000000000000000000000000000000000000000005", "9462d7705bd0b3ecbc51a8026a25597cb28a650c79"},
+ {"0000000000000000000000000000000000000000000000000000000000000010", "947e70f9460402290a3e487dae01f610a1a8218fda"},
+ {"0000000000000000000000000000000000000000000000000000000000000111", "01"},
+ {"0000000000000000000000000000000000000000000000000000000000000112", "a053656e6174650000000000000000000000000000000000000000000000000000"},
+ {"0000000000000000000000000000000000000000000000000000000000000113", "a053656e6174650000000000000000000000000000000000000000000000000000"},
+ {"53656e6174650000000000000000000000000000000000000000000000000000", "94977e3f62f5e1ed7953697430303a3cfa2b5b736e"},
+ }
+ for _, e := range data {
+ trie.Update(string(ethutil.Hex2Bytes(e.k)), string(ethutil.Hex2Bytes(e.v)))
+ }
+
+ fmt.Printf("root after update %x\n", trie.Root)
+ trie.NewIterator().Each(func(k string, v *ethutil.Value) {
+ fmt.Printf("%x %x\n", k, v.Bytes())
+ })
+
+ data = []struct{ k, v string }{
+ {"0000000000000000000000000000000000000000000000000000000000000112", ""},
+ {"436974697a656e73000000000000000000000000000000000000000000000001", ""},
+ {"436f757274000000000000000000000000000000000000000000000000000002", ""},
+ {"53656e6174650000000000000000000000000000000000000000000000000000", ""},
+ {"436f757274000000000000000000000000000000000000000000000000000000", ""},
+ {"53656e6174650000000000000000000000000000000000000000000000000001", ""},
+ {"0000000000000000000000000000000000000000000000000000000000000113", ""},
+ {"436974697a656e73000000000000000000000000000000000000000000000000", ""},
+ {"436974697a656e73000000000000000000000000000000000000000000000002", ""},
+ {"436f757274000000000000000000000000000000000000000000000000000001", ""},
+ {"0000000000000000000000000000000000000000000000000000000000000111", ""},
+ {"53656e6174650000000000000000000000000000000000000000000000000002", ""},
+ }
+
+ for _, e := range data {
+ trie.Delete(string(ethutil.Hex2Bytes(e.k)))
+ }
+
+ fmt.Printf("root after delete %x\n", trie.Root)
+
+ trie.NewIterator().Each(func(k string, v *ethutil.Value) {
+ fmt.Printf("%x %x\n", k, v.Bytes())
+ })
+
+ fmt.Printf("%x\n", trie.Get(string(ethutil.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"))))
+}
diff --git a/ethutil/bytes.go b/ethutil/bytes.go
index d68a69433..34fff7d42 100644
--- a/ethutil/bytes.go
+++ b/ethutil/bytes.go
@@ -118,7 +118,7 @@ func FormatData(data string) []byte {
// Simple stupid
d := new(big.Int)
if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
- return RightPadBytes([]byte(data), 32)
+ return RightPadBytes([]byte(data[1:len(data)-1]), 32)
} else if len(data) > 1 && data[:2] == "0x" {
d.SetBytes(Hex2Bytes(data[2:]))
} else {
@@ -149,3 +149,17 @@ func LeftPadBytes(slice []byte, l int) []byte {
return padded
}
+
+func Address(slice []byte) (addr []byte) {
+ if len(slice) < 20 {
+ addr = LeftPadBytes(slice, 20)
+ } else if len(slice) > 20 {
+ addr = slice[len(slice)-20:]
+ } else {
+ addr = slice
+ }
+
+ addr = CopyBytes(addr)
+
+ return
+}
diff --git a/ethutil/config.go b/ethutil/config.go
index 2f3d706fe..41bece21d 100644
--- a/ethutil/config.go
+++ b/ethutil/config.go
@@ -14,6 +14,7 @@ type ConfigManager struct {
ExecPath string
Debug bool
Diff bool
+ DiffType string
Paranoia bool
conf *globalconf.GlobalConf
diff --git a/ethutil/value.go b/ethutil/value.go
index b37b33c28..fba7426d1 100644
--- a/ethutil/value.go
+++ b/ethutil/value.go
@@ -40,13 +40,9 @@ func (val *Value) Len() int {
//return val.kind.Len()
if data, ok := val.Val.([]interface{}); ok {
return len(data)
- } else if data, ok := val.Val.([]byte); ok {
- return len(data)
- } else if data, ok := val.Val.(string); ok {
- return len(data)
}
- return 0
+ return len(val.Bytes())
}
func (val *Value) Raw() interface{} {
@@ -118,6 +114,8 @@ func (val *Value) Bytes() []byte {
return []byte{s}
} else if s, ok := val.Val.(string); ok {
return []byte(s)
+ } else if s, ok := val.Val.(*big.Int); ok {
+ return s.Bytes()
}
return []byte{}
@@ -190,6 +188,19 @@ func (val *Value) Get(idx int) *Value {
return NewValue(nil)
}
+func (self *Value) Copy() *Value {
+ switch val := self.Val.(type) {
+ case *big.Int:
+ return NewValue(new(big.Int).Set(val))
+ case []byte:
+ return NewValue(CopyBytes(val))
+ default:
+ return NewValue(self.Val)
+ }
+
+ return nil
+}
+
func (val *Value) Cmp(o *Value) bool {
return reflect.DeepEqual(val.Val, o.Val)
}
diff --git a/peer.go b/peer.go
index 0a4f08af5..89032364e 100644
--- a/peer.go
+++ b/peer.go
@@ -319,7 +319,7 @@ func (p *Peer) HandleInbound() {
for atomic.LoadInt32(&p.disconnect) == 0 {
// HMM?
- time.Sleep(500 * time.Millisecond)
+ time.Sleep(50 * time.Millisecond)
// Wait for a message from the peer
msgs, err := ethwire.ReadMessages(p.conn)
if err != nil {
@@ -328,6 +328,7 @@ func (p *Peer) HandleInbound() {
for _, msg := range msgs {
peerlogger.DebugDetailf("(%v) => %v %v\n", p.conn.RemoteAddr(), msg.Type, msg.Data)
+ nextMsg:
switch msg.Type {
case ethwire.MsgHandshakeTy:
// Version message
@@ -373,6 +374,7 @@ func (p *Peer) HandleInbound() {
p.diverted = false
if !p.ethereum.StateManager().BlockChain().FindCanonicalChainFromMsg(msg, block.PrevHash) {
p.SyncWithPeerToLastKnown()
+ break nextMsg
}
break
}
@@ -385,10 +387,11 @@ func (p *Peer) HandleInbound() {
p.blocksRequested = p.blocksRequested * 2
peerlogger.Infof("No common ancestor found, requesting %d more blocks.\n", p.blocksRequested)
- p.catchingUp = false
p.FindCommonParentBlock()
- break
+ break nextMsg
}
+
+ p.catchingUp = false
}
for i := msg.Data.Len() - 1; i >= 0; i-- {
@@ -410,7 +413,7 @@ func (p *Peer) HandleInbound() {
}
}
- if msg.Data.Len() == 0 {
+ if msg.Data.Len() <= 1 {
// Set catching up to false if
// the peer has nothing left to give
p.catchingUp = false
@@ -754,7 +757,7 @@ func (p *Peer) CatchupWithPeer(blockHash []byte) {
if !p.catchingUp {
// Make sure nobody else is catching up when you want to do this
p.catchingUp = true
- msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(10)})
+ msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(30)})
p.QueueMessage(msg)
peerlogger.DebugDetailf("Requesting blockchain %x... from peer %s\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4], p.conn.RemoteAddr())