merge upstream

This commit is contained in:
zelig 2014-07-21 13:26:29 +01:00
commit 1e4af85a38
20 changed files with 404 additions and 161 deletions

View File

@ -6,7 +6,7 @@ Ethereum
Ethereum Go Development package (C) Jeffrey Wilcke Ethereum Go Development package (C) Jeffrey Wilcke
Ethereum is currently in its testing phase. The current state is "Proof 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 Ethereum Go is split up in several sub packages Please refer to each
individual package for more information. individual package for more information.

View File

@ -17,10 +17,16 @@ var powlogger = ethlog.NewLogger("POW")
type PoW interface { type PoW interface {
Search(block *Block, reactChan chan ethreact.Event) []byte Search(block *Block, reactChan chan ethreact.Event) []byte
Verify(hash []byte, diff *big.Int, nonce []byte) bool Verify(hash []byte, diff *big.Int, nonce []byte) bool
GetHashrate() int64
} }
type EasyPow struct { 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 { 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 { if i%1234567 == 0 {
elapsed := time.Now().UnixNano() - start elapsed := time.Now().UnixNano() - start
hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000 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()) sha := ethcrypto.Sha3Bin(big.NewInt(r.Int63()).Bytes())

View File

@ -76,6 +76,8 @@ func (self *State) DeleteStateObject(stateObject *StateObject) {
// Retrieve a state object given my the address. Nil if not found // Retrieve a state object given my the address. Nil if not found
func (self *State) GetStateObject(addr []byte) *StateObject { func (self *State) GetStateObject(addr []byte) *StateObject {
addr = ethutil.Address(addr)
stateObject := self.stateObjects[string(addr)] stateObject := self.stateObjects[string(addr)]
if stateObject != nil { if stateObject != nil {
return stateObject return stateObject
@ -145,7 +147,6 @@ func (self *State) Set(state *State) {
self.trie = state.trie self.trie = state.trie
self.stateObjects = state.stateObjects self.stateObjects = state.stateObjects
//*self = *state
} }
func (s *State) Root() interface{} { func (s *State) Root() interface{} {
@ -173,7 +174,7 @@ func (s *State) Reset() {
func (s *State) Sync() { func (s *State) Sync() {
// Sync all nested states // Sync all nested states
for _, stateObject := range s.stateObjects { for _, stateObject := range s.stateObjects {
s.UpdateStateObject(stateObject) //s.UpdateStateObject(stateObject)
if stateObject.state == nil { if stateObject.state == nil {
continue continue
@ -205,6 +206,8 @@ func (self *State) Update() {
// FIXME trie delete is broken // FIXME trie delete is broken
valid, t2 := ethtrie.ParanoiaCheck(self.trie) valid, t2 := ethtrie.ParanoiaCheck(self.trie)
if !valid { if !valid {
statelogger.Infof("Warn: PARANOIA: Different state root during copy %x vs %x\n", self.trie.Root, t2.Root)
self.trie = t2 self.trie = t2
} }
} }
@ -212,9 +215,9 @@ func (self *State) Update() {
// Debug stuff // Debug stuff
func (self *State) CreateOutputForDiff() { func (self *State) CreateOutputForDiff() {
for addr, stateObject := range self.stateObjects { 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) { 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())
}) })
} }
} }

View File

@ -7,7 +7,6 @@ import (
"github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog" "github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethreact" "github.com/ethereum/eth-go/ethreact"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire" "github.com/ethereum/eth-go/ethwire"
"math/big" "math/big"
@ -121,7 +120,10 @@ func (self *StateManager) ProcessTransactions(coinbase *StateObject, state *Stat
done: done:
for i, tx := range txs { for i, tx := range txs {
txGas := new(big.Int).Set(tx.Gas) 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() err = st.TransitionState()
if err != nil { if err != nil {
switch { switch {
@ -149,10 +151,17 @@ done:
accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas)) accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas))
receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative} 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) receipts = append(receipts, receipt)
handled = append(handled, tx) handled = append(handled, tx)
if ethutil.Config.Diff { if ethutil.Config.Diff && ethutil.Config.DiffType == "all" {
state.CreateOutputForDiff() state.CreateOutputForDiff()
} }
} }
@ -188,36 +197,11 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
// before that. // before that.
defer state.Reset() defer state.Reset()
if ethutil.Config.Diff { if ethutil.Config.Diff && ethutil.Config.DiffType == "all" {
fmt.Printf("## 0x%x 0x%x ##\n", block.Hash(), block.Number) fmt.Printf("## %x %x ##\n", block.Hash(), block.Number)
} }
receipts, err := sm.ApplyDiff(state, parent, block) _, 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())
}
*/
}
}()
if err != nil { if err != nil {
return err return err
} }
@ -235,12 +219,14 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
return err return err
} }
/*
if ethutil.Config.Paranoia { if ethutil.Config.Paranoia {
valid, _ := ethtrie.ParanoiaCheck(state.trie) valid, _ := ethtrie.ParanoiaCheck(state.trie)
if !valid { if !valid {
err = fmt.Errorf("PARANOIA: World state trie corruption") err = fmt.Errorf("PARANOIA: World state trie corruption")
} }
} }
*/
if !block.State().Cmp(state) { if !block.State().Cmp(state) {

View File

@ -15,6 +15,18 @@ func (self Code) String() string {
return strings.Join(Disassemble(self), " ") 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 { type StateObject struct {
// Address of the object // Address of the object
address []byte address []byte
@ -27,7 +39,7 @@ type StateObject struct {
script Code script Code
initScript Code initScript Code
storage map[string]*ethutil.Value storage Storage
// Total gas pool is the total amount of gas currently // Total gas pool is the total amount of gas currently
// left if this object is the coinbase. Gas is directly // left if this object is the coinbase. Gas is directly
@ -41,7 +53,8 @@ type StateObject struct {
} }
func (self *StateObject) Reset() { 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 // Converts an transaction in to a state object
@ -62,11 +75,12 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
func NewStateObject(addr []byte) *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. // 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 := &StateObject{address: address, Amount: new(big.Int), gasPool: new(big.Int)}
object.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, "")) 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 return object
} }
@ -79,13 +93,6 @@ func NewContract(address []byte, Amount *big.Int, root []byte) *StateObject {
return contract 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 { func NewStateObjectFromBytes(address, data []byte) *StateObject {
object := &StateObject{address: address} object := &StateObject{address: address}
object.RlpDecode(data) object.RlpDecode(data)
@ -95,7 +102,7 @@ func NewStateObjectFromBytes(address, data []byte) *StateObject {
func (self *StateObject) MarkForDeletion() { func (self *StateObject) MarkForDeletion() {
self.remove = true 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 { 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) self.setStorage(key.Bytes(), value)
} }
func (self *StateObject) getStorage(key []byte) *ethutil.Value { func (self *StateObject) getStorage(k []byte) *ethutil.Value {
k := ethutil.LeftPadBytes(key, 32) key := ethutil.LeftPadBytes(k, 32)
value := self.storage[string(k)] value := self.storage[string(key)]
if value == nil { 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 value
//return self.GetAddr(key)
} }
func (self *StateObject) setStorage(key []byte, value *ethutil.Value) { func (self *StateObject) setStorage(k []byte, value *ethutil.Value) {
k := ethutil.LeftPadBytes(key, 32) 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() { 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 { 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)) self.state.trie.Delete(string(key))
continue continue
} }
self.SetAddr([]byte(key), value) 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 { func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
if int64(len(c.script)-1) < pc.Int64() { if int64(len(c.script)-1) < pc.Int64() {
return ethutil.NewValue(0) return ethutil.NewValue(0)
@ -154,13 +198,13 @@ func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
func (c *StateObject) AddAmount(amount *big.Int) { func (c *StateObject) AddAmount(amount *big.Int) {
c.SetAmount(new(big.Int).Add(c.Amount, amount)) 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) { func (c *StateObject) SubAmount(amount *big.Int) {
c.SetAmount(new(big.Int).Sub(c.Amount, amount)) 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) { func (c *StateObject) SetAmount(amount *big.Int) {
@ -222,6 +266,8 @@ func (self *StateObject) Copy() *StateObject {
} }
stateObject.script = ethutil.CopyBytes(self.script) stateObject.script = ethutil.CopyBytes(self.script)
stateObject.initScript = ethutil.CopyBytes(self.initScript) stateObject.initScript = ethutil.CopyBytes(self.initScript)
stateObject.storage = self.storage.Copy()
stateObject.gasPool.Set(self.gasPool)
return stateObject return stateObject
} }
@ -280,6 +326,7 @@ func (c *StateObject) RlpDecode(data []byte) {
c.Amount = decoder.Get(1).BigInt() c.Amount = decoder.Get(1).BigInt()
c.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface())) c.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface()))
c.storage = make(map[string]*ethutil.Value) c.storage = make(map[string]*ethutil.Value)
c.gasPool = new(big.Int)
c.ScriptHash = decoder.Get(3).Bytes() c.ScriptHash = decoder.Get(3).Bytes()

View File

@ -2,8 +2,6 @@ package ethchain
import ( import (
"fmt" "fmt"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
"math/big" "math/big"
) )
@ -44,7 +42,7 @@ func (self *StateTransition) Coinbase() *StateObject {
return self.cb return self.cb
} }
self.cb = self.state.GetAccount(self.coinbase) self.cb = self.state.GetOrNewStateObject(self.coinbase)
return self.cb return self.cb
} }
func (self *StateTransition) Sender() *StateObject { func (self *StateTransition) Sender() *StateObject {
@ -52,7 +50,7 @@ func (self *StateTransition) Sender() *StateObject {
return self.sen return self.sen
} }
self.sen = self.state.GetAccount(self.tx.Sender()) self.sen = self.state.GetOrNewStateObject(self.tx.Sender())
return self.sen return self.sen
} }
@ -65,7 +63,7 @@ func (self *StateTransition) Receiver() *StateObject {
return self.rec return self.rec
} }
self.rec = self.state.GetAccount(self.tx.Recipient) self.rec = self.state.GetOrNewStateObject(self.tx.Recipient)
return self.rec return self.rec
} }
@ -176,13 +174,16 @@ func (self *StateTransition) TransitionState() (err error) {
return return
} }
/* FIXME if sender.Amount.Cmp(self.value) < 0 {
* If tx goes TO "0", goes OOG during init, reverse changes, but initial endowment should happen. The ether is lost forever return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Amount)
*/ }
var snapshot *State
var snapshot *State
// If the receiver is nil it's a contract (\0*32). // If the receiver is nil it's a contract (\0*32).
if tx.CreatesContract() { if tx.CreatesContract() {
// Subtract the (irreversible) amount from the senders account
sender.SubAmount(self.value)
snapshot = self.state.Copy() snapshot = self.state.Copy()
// Create a new state object for the contract // Create a new state object for the contract
@ -191,16 +192,17 @@ func (self *StateTransition) TransitionState() (err error) {
if receiver == nil { if receiver == nil {
return fmt.Errorf("Unable to create contract") return fmt.Errorf("Unable to create contract")
} }
// Add the amount to receivers account which should conclude this transaction
receiver.AddAmount(self.value)
} else { } else {
receiver = self.Receiver() receiver = self.Receiver()
}
// Transfer value from sender to receiver // Subtract the amount from the senders account
if err = self.transferValue(sender, receiver); err != nil { sender.SubAmount(self.value)
return // Add the amount to receivers account which should conclude this transaction
} receiver.AddAmount(self.value)
if snapshot == nil {
snapshot = self.state.Copy() 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) { func Call(vm *Vm, closure *Closure, data []byte) (ret []byte, err error) {
ret, _, err = closure.Call(vm, data) 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 return
} }

View File

@ -227,6 +227,14 @@ func (self *Receipt) String() string {
self.CumulativeGasUsed) 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 // Transaction slice type for basic sorting
type Transactions []*Transaction type Transactions []*Transaction

View File

@ -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. // XXX Leave this Println intact. Don't change this to the log system.
// Used for creating diffs between implementations // Used for creating diffs between implementations
if vm.logTy == LogTyDiff { 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() b := pc.Bytes()
if len(b) == 0 { if len(b) == 0 {
b = []byte{0} b = []byte{0}
@ -184,9 +193,9 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
var mult *big.Int var mult *big.Int
y, x := stack.Peekn() y, x := stack.Peekn()
val := closure.GetStorage(x) 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 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 mult = ethutil.Big0
} else { } else {
mult = ethutil.Big1 mult = ethutil.Big1
@ -447,7 +456,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case BYTE: case BYTE:
require(2) require(2)
val, th := stack.Popn() 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()])) byt := big.NewInt(int64(val.Bytes()[th.Int64()]))
stack.Push(byt) stack.Push(byt)
@ -482,7 +491,7 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case ORIGIN: case ORIGIN:
stack.Push(ethutil.BigD(vm.vars.Origin)) stack.Push(ethutil.BigD(vm.vars.Origin))
vm.Printf(" => %v", vm.vars.Origin) vm.Printf(" => %x", vm.vars.Origin)
case CALLER: case CALLER:
caller := closure.caller.Address() caller := closure.caller.Address()
stack.Push(ethutil.BigD(caller)) 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] 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) mem.Set(mOff, l, code)
fmt.Println(Code(mem.Get(mOff, l))) //fmt.Println(Code(mem.Get(mOff, l)))
case GASPRICE: case GASPRICE:
stack.Push(closure.Price) 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 { if closure.object.Amount.Cmp(value) < 0 {
vmlogger.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Amount) vmlogger.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Amount)
closure.ReturnGas(gas, nil, nil) closure.ReturnGas(gas, nil, nil)
stack.Push(ethutil.BigFalse) stack.Push(ethutil.BigFalse)

View File

@ -6,30 +6,35 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"runtime"
"strconv" "strconv"
"strings" "strings"
) )
func InitWords() []string { func InitWords(wordsPath string) {
_, thisfile, _, _ := runtime.Caller(1) filename := path.Join(wordsPath, "mnemonic.words.lst")
filename := path.Join(path.Dir(thisfile), "mnemonic.words.lst")
if _, err := os.Stat(filename); os.IsNotExist(err) { 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.") 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])) dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil { if err != nil {
panic(fmt.Errorf("problem getting current folder: ", err)) panic(fmt.Errorf("problem getting current folder: ", err))
} }
filename = path.Join(dir, "mnemonic.words.lst") filename = path.Join(dir, "mnemonic.words.lst")
} }
}
content, err := ioutil.ReadFile(filename) content, err := ioutil.ReadFile(filename)
if err != nil { 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 // 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 { func IndexOf(slice []string, value string) int64 {

View File

@ -81,6 +81,8 @@ type Ethereum struct {
keyManager *ethcrypto.KeyManager keyManager *ethcrypto.KeyManager
clientIdentity ethwire.ClientIdentity clientIdentity ethwire.ClientIdentity
isUpToDate bool
} }
func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager *ethcrypto.KeyManager, caps Caps, usePnp bool) (*Ethereum, error) { 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, nat: nat,
keyManager: keyManager, keyManager: keyManager,
clientIdentity: clientIdentity, clientIdentity: clientIdentity,
isUpToDate: true,
} }
ethereum.reactor = ethreact.New() ethereum.reactor = ethreact.New()
@ -158,7 +161,7 @@ func (s *Ethereum) IsUpToDate() bool {
upToDate := true upToDate := true
eachPeer(s.peers, func(peer *Peer, e *list.Element) { eachPeer(s.peers, func(peer *Peer, e *list.Element) {
if atomic.LoadInt32(&peer.connected) == 1 { if atomic.LoadInt32(&peer.connected) == 1 {
if peer.catchingUp == true { if peer.catchingUp == true && peer.versionKnown {
upToDate = false upToDate = false
} }
} }
@ -373,6 +376,7 @@ func (s *Ethereum) Start(seed bool) {
// Start the reaping processes // Start the reaping processes
go s.ReapDeadPeerHandler() go s.ReapDeadPeerHandler()
go s.update()
if seed { if seed {
s.Seed() s.Seed()
@ -514,3 +518,23 @@ out:
ethlogger.Debugln("succesfully disestablished UPnP port mapping") 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
}
}
}

View File

@ -119,7 +119,7 @@ func AddLogSystem(logSystem LogSystem) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()
if logSystems == nil { if logSystems == nil {
logMessages = make(chan *logMessage, 5) logMessages = make(chan *logMessage, 10)
quit = make(chan chan error, 1) quit = make(chan chan error, 1)
drained = make(chan bool, 1) drained = make(chan bool, 1)
go start() go start()

View File

@ -21,28 +21,32 @@ type Miner struct {
block *ethchain.Block block *ethchain.Block
powChan chan []byte powChan chan []byte
powQuitChan chan ethreact.Event 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{ miner := Miner{
pow: &ethchain.EasyPow{}, pow: &ethchain.EasyPow{},
ethereum: ethereum, ethereum: ethereum,
coinbase: coinbase, coinbase: coinbase,
} }
// Insert initial TXs in our little miner 'pool' return &miner
miner.txs = ethereum.TxPool().Flush()
miner.block = ethereum.BlockChain().NewBlock(miner.coinbase)
return miner
} }
func (miner *Miner) Start() { 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.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.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.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 // Prepare inital block
//miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State()) //miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State())
@ -61,15 +65,17 @@ func (miner *Miner) Start() {
reactor.Subscribe("newTx:pre", miner.powQuitChan) reactor.Subscribe("newTx:pre", miner.powQuitChan)
logger.Infoln("Started") logger.Infoln("Started")
reactor.Post("miner:start", miner)
} }
func (miner *Miner) listener() { func (miner *Miner) listener() {
out:
for { for {
select { select {
case <-miner.quitChan: case status := <-miner.quitChan:
logger.Infoln("Stopped") logger.Infoln("Stopped")
break out status <- nil
return
case chanMessage := <-miner.reactChan: case chanMessage := <-miner.reactChan:
if block, ok := chanMessage.Resource.(*ethchain.Block); ok { if block, ok := chanMessage.Resource.(*ethchain.Block); ok {
@ -127,7 +133,9 @@ out:
func (miner *Miner) Stop() { func (miner *Miner) Stop() {
logger.Infoln("Stopping...") logger.Infoln("Stopping...")
miner.quitChan <- true status := make(chan error)
miner.quitChan <- status
<-status
reactor := miner.ethereum.Reactor() reactor := miner.ethereum.Reactor()
reactor.Unsubscribe("newBlock", miner.powQuitChan) reactor.Unsubscribe("newBlock", miner.powQuitChan)
@ -137,6 +145,8 @@ func (miner *Miner) Stop() {
close(miner.powQuitChan) close(miner.powQuitChan)
close(miner.quitChan) close(miner.quitChan)
reactor.Post("miner:stop", miner)
} }
func (self *Miner) mineNewBlock() { func (self *Miner) mineNewBlock() {

View File

@ -179,6 +179,19 @@ func FindAddressInNameReg(stateManager *ethchain.StateManager, name string) []by
return nil 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) { func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, scriptStr string) (*PReceipt, error) {
var hash []byte var hash []byte
var contractCreation bool var contractCreation bool

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"strings" "strings"
) )
@ -46,6 +47,7 @@ type PBlock struct {
Transactions string `json:"transactions"` Transactions string `json:"transactions"`
Time int64 `json:"time"` Time int64 `json:"time"`
Coinbase string `json:"coinbase"` Coinbase string `json:"coinbase"`
Name string `json:"name"`
GasLimit string `json:"gasLimit"` GasLimit string `json:"gasLimit"`
GasUsed string `json:"gasUsed"` GasUsed string `json:"gasUsed"`
} }
@ -212,6 +214,10 @@ func (c *PStateObject) IsContract() bool {
return false return false
} }
func (self *PStateObject) EachStorage(cb ethtrie.EachCallback) {
self.object.State().EachStorage(cb)
}
type KeyVal struct { type KeyVal struct {
Key string Key string
Value string Value string

View File

@ -5,10 +5,12 @@ import (
"fmt" "fmt"
"github.com/ethereum/eth-go/ethcrypto" "github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"reflect" _ "reflect"
"sync" "sync"
) )
func __ignore() { fmt.Println("") }
func ParanoiaCheck(t1 *Trie) (bool, *Trie) { func ParanoiaCheck(t1 *Trie) (bool, *Trie) {
t2 := NewTrie(ethutil.Config.Db, "") t2 := NewTrie(ethutil.Config.Db, "")
@ -269,8 +271,7 @@ func (t *Trie) getState(node interface{}, key []int) interface{} {
} }
// It shouldn't come this far // It shouldn't come this far
fmt.Println("getState unexpected return") panic("unexpected return")
return ""
} }
func (t *Trie) getNode(node interface{}) *ethutil.Value { 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 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{} { 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 // New node
n := ethutil.NewValue(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} newNode := []interface{}{CompactEncode(key), value}
return t.Put(newNode) return t.Put(newNode)
@ -385,17 +389,22 @@ func (t *Trie) InsertState(node interface{}, key []int, value interface{}) inter
return t.Put(newNode) return t.Put(newNode)
} }
return "" panic("unexpected end")
} }
func (t *Trie) deleteState(node interface{}, key []int) interface{} { func (t *Trie) deleteState(node interface{}, key []int) interface{} {
if len(key) == 0 { if len(key) == 0 {
println("<empty ret>")
return "" return ""
} }
// New node // New node
n := ethutil.NewValue(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 "" 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) // Matching key pair (ie. there's already an object with this key)
if CompareIntSlice(k, key) { if CompareIntSlice(k, key) {
//fmt.Printf("<delete ret> %x\n", v)
return "" return ""
} else if CompareIntSlice(key[:len(k)], k) { } else if CompareIntSlice(key[:len(k)], k) {
hash := t.deleteState(v, key[len(k):]) hash := t.deleteState(v, key[len(k):])
child := t.getNode(hash) child := t.getNode(hash)
/*
if child.IsNil() {
return node
}
*/
var newNode []interface{} var newNode []interface{}
if child.Len() == 2 { if child.Len() == 2 {
@ -421,6 +437,8 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
newNode = []interface{}{currentNode.Get(0).Str(), hash} newNode = []interface{}{currentNode.Get(0).Str(), hash}
} }
//fmt.Printf("%x\n", newNode)
return t.Put(newNode) return t.Put(newNode)
} else { } else {
return node return node
@ -463,10 +481,11 @@ func (t *Trie) deleteState(node interface{}, key []int) interface{} {
newNode = n newNode = n
} }
//fmt.Printf("%x\n", newNode)
return t.Put(newNode) return t.Put(newNode)
} }
return "" panic("unexpected return")
} }
type TrieIterator struct { type TrieIterator struct {

View File

@ -1,16 +1,17 @@
package ethtrie package ethtrie
import ( import (
"bytes" _ "bytes"
"encoding/hex" _ "encoding/hex"
"encoding/json" _ "encoding/json"
"fmt" "fmt"
"io/ioutil" "github.com/ethereum/eth-go/ethutil"
"math/rand" _ "io/ioutil"
"net/http" _ "math/rand"
"reflect" _ "net/http"
_ "reflect"
"testing" "testing"
"time" _ "time"
) )
const LONG_WORD = "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ" const LONG_WORD = "1234567890abcdefghijklmnopqrstuvwxxzABCEFGHIJKLMNOPQRSTUVWXYZ"
@ -42,6 +43,7 @@ func New() (*MemDatabase, *Trie) {
return db, NewTrie(db, "") return db, NewTrie(db, "")
} }
/*
func TestTrieSync(t *testing.T) { func TestTrieSync(t *testing.T) {
db, trie := New() db, trie := New()
@ -251,8 +253,8 @@ func TestRemote(t *testing.T) {
trie.Update(get(key), get(value)) trie.Update(get(key), get(value))
} }
a := NewValue(h(test.Root)).Bytes() a := ethutil.NewValue(h(test.Root)).Bytes()
b := NewValue(trie.Root).Bytes() b := ethutil.NewValue(trie.Root).Bytes()
if bytes.Compare(a, b) != 0 { if bytes.Compare(a, b) != 0 {
t.Errorf("%-10s: %x %x", test.Name, a, b) t.Errorf("%-10s: %x %x", test.Name, a, b)
} }
@ -267,12 +269,12 @@ func TestTrieReplay(t *testing.T) {
} }
_, trie2 := New() _, trie2 := New()
trie.NewIterator().Each(func(key string, v *Value) { trie.NewIterator().Each(func(key string, v *ethutil.Value) {
trie2.Update(key, v.Str()) trie2.Update(key, v.Str())
}) })
a := NewValue(trie.Root).Bytes() a := ethutil.NewValue(trie.Root).Bytes()
b := NewValue(trie2.Root).Bytes() b := ethutil.NewValue(trie2.Root).Bytes()
if bytes.Compare(a, b) != 0 { if bytes.Compare(a, b) != 0 {
t.Errorf("%s %x %x\n", test.Name, trie.Root, trie2.Root) 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"))))
}

View File

@ -118,7 +118,7 @@ func FormatData(data string) []byte {
// Simple stupid // Simple stupid
d := new(big.Int) d := new(big.Int)
if data[0:1] == "\"" && data[len(data)-1:] == "\"" { 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" { } else if len(data) > 1 && data[:2] == "0x" {
d.SetBytes(Hex2Bytes(data[2:])) d.SetBytes(Hex2Bytes(data[2:]))
} else { } else {
@ -149,3 +149,17 @@ func LeftPadBytes(slice []byte, l int) []byte {
return padded 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
}

View File

@ -14,6 +14,7 @@ type ConfigManager struct {
ExecPath string ExecPath string
Debug bool Debug bool
Diff bool Diff bool
DiffType string
Paranoia bool Paranoia bool
conf *globalconf.GlobalConf conf *globalconf.GlobalConf

View File

@ -40,13 +40,9 @@ func (val *Value) Len() int {
//return val.kind.Len() //return val.kind.Len()
if data, ok := val.Val.([]interface{}); ok { if data, ok := val.Val.([]interface{}); ok {
return len(data) 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{} { func (val *Value) Raw() interface{} {
@ -118,6 +114,8 @@ func (val *Value) Bytes() []byte {
return []byte{s} return []byte{s}
} else if s, ok := val.Val.(string); ok { } else if s, ok := val.Val.(string); ok {
return []byte(s) return []byte(s)
} else if s, ok := val.Val.(*big.Int); ok {
return s.Bytes()
} }
return []byte{} return []byte{}
@ -190,6 +188,19 @@ func (val *Value) Get(idx int) *Value {
return NewValue(nil) 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 { func (val *Value) Cmp(o *Value) bool {
return reflect.DeepEqual(val.Val, o.Val) return reflect.DeepEqual(val.Val, o.Val)
} }

13
peer.go
View File

@ -319,7 +319,7 @@ func (p *Peer) HandleInbound() {
for atomic.LoadInt32(&p.disconnect) == 0 { for atomic.LoadInt32(&p.disconnect) == 0 {
// HMM? // HMM?
time.Sleep(500 * time.Millisecond) time.Sleep(50 * time.Millisecond)
// Wait for a message from the peer // Wait for a message from the peer
msgs, err := ethwire.ReadMessages(p.conn) msgs, err := ethwire.ReadMessages(p.conn)
if err != nil { if err != nil {
@ -328,6 +328,7 @@ func (p *Peer) HandleInbound() {
for _, msg := range msgs { for _, msg := range msgs {
peerlogger.DebugDetailf("(%v) => %v %v\n", p.conn.RemoteAddr(), msg.Type, msg.Data) peerlogger.DebugDetailf("(%v) => %v %v\n", p.conn.RemoteAddr(), msg.Type, msg.Data)
nextMsg:
switch msg.Type { switch msg.Type {
case ethwire.MsgHandshakeTy: case ethwire.MsgHandshakeTy:
// Version message // Version message
@ -373,6 +374,7 @@ func (p *Peer) HandleInbound() {
p.diverted = false p.diverted = false
if !p.ethereum.StateManager().BlockChain().FindCanonicalChainFromMsg(msg, block.PrevHash) { if !p.ethereum.StateManager().BlockChain().FindCanonicalChainFromMsg(msg, block.PrevHash) {
p.SyncWithPeerToLastKnown() p.SyncWithPeerToLastKnown()
break nextMsg
} }
break break
} }
@ -385,10 +387,11 @@ func (p *Peer) HandleInbound() {
p.blocksRequested = p.blocksRequested * 2 p.blocksRequested = p.blocksRequested * 2
peerlogger.Infof("No common ancestor found, requesting %d more blocks.\n", p.blocksRequested) peerlogger.Infof("No common ancestor found, requesting %d more blocks.\n", p.blocksRequested)
p.catchingUp = false
p.FindCommonParentBlock() p.FindCommonParentBlock()
break break nextMsg
} }
p.catchingUp = false
} }
for i := msg.Data.Len() - 1; i >= 0; i-- { 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 // Set catching up to false if
// the peer has nothing left to give // the peer has nothing left to give
p.catchingUp = false p.catchingUp = false
@ -754,7 +757,7 @@ func (p *Peer) CatchupWithPeer(blockHash []byte) {
if !p.catchingUp { if !p.catchingUp {
// Make sure nobody else is catching up when you want to do this // Make sure nobody else is catching up when you want to do this
p.catchingUp = true p.catchingUp = true
msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(10)}) msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(30)})
p.QueueMessage(msg) p.QueueMessage(msg)
peerlogger.DebugDetailf("Requesting blockchain %x... from peer %s\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4], p.conn.RemoteAddr()) peerlogger.DebugDetailf("Requesting blockchain %x... from peer %s\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4], p.conn.RemoteAddr())