aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelig <viktor.tron@gmail.com>2014-07-15 01:50:06 +0800
committerzelig <viktor.tron@gmail.com>2014-07-15 01:50:06 +0800
commit3d5db7288f134fef7e51b25776007705f6663654 (patch)
treeedda6e8fd23584327473058411df9cd2c53241f4
parentdc11b5c55e2888a7a3dac51fedc3864d112136ce (diff)
parent8845fb7eae3e51fd3e55c47c377bf1a9e0cfe2a9 (diff)
downloadgo-tangerine-3d5db7288f134fef7e51b25776007705f6663654.tar
go-tangerine-3d5db7288f134fef7e51b25776007705f6663654.tar.gz
go-tangerine-3d5db7288f134fef7e51b25776007705f6663654.tar.bz2
go-tangerine-3d5db7288f134fef7e51b25776007705f6663654.tar.lz
go-tangerine-3d5db7288f134fef7e51b25776007705f6663654.tar.xz
go-tangerine-3d5db7288f134fef7e51b25776007705f6663654.tar.zst
go-tangerine-3d5db7288f134fef7e51b25776007705f6663654.zip
merge upstream
-rw-r--r--ethchain/asm.go4
-rw-r--r--ethchain/block_chain.go3
-rw-r--r--ethchain/closure.go8
-rw-r--r--ethchain/dagger.go5
-rw-r--r--ethchain/state.go163
-rw-r--r--ethchain/state_manager.go18
-rw-r--r--ethchain/state_object.go54
-rw-r--r--ethchain/state_transition.go24
-rw-r--r--ethchain/vm.go109
-rw-r--r--ethcrypto/crypto.go2
-rw-r--r--ethcrypto/mnemonic.go10
-rw-r--r--ethereum.go15
-rw-r--r--ethlog/loggers.go12
-rw-r--r--ethlog/loggers_test.go12
-rw-r--r--ethminer/miner.go12
-rw-r--r--ethreact/README.md40
-rw-r--r--ethreact/reactor_test.go63
-rw-r--r--ethutil/common.go12
-rw-r--r--ethutil/config.go1
-rw-r--r--ethutil/reactor.go87
-rw-r--r--ethutil/reactor_test.go30
-rw-r--r--ethutil/script.go15
-rw-r--r--ethwire/messaging.go2
-rw-r--r--peer.go18
24 files changed, 461 insertions, 258 deletions
diff --git a/ethchain/asm.go b/ethchain/asm.go
index 09d6af56f..2697953fd 100644
--- a/ethchain/asm.go
+++ b/ethchain/asm.go
@@ -24,6 +24,10 @@ func Disassemble(script []byte) (asm []string) {
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
pc.Add(pc, ethutil.Big1)
a := int64(op) - int64(PUSH1) + 1
+ if int(pc.Int64()+a) > len(script) {
+ return nil
+ }
+
data := script[pc.Int64() : pc.Int64()+a]
if len(data) == 0 {
data = []byte{0}
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go
index df735d679..f72a77706 100644
--- a/ethchain/block_chain.go
+++ b/ethchain/block_chain.go
@@ -294,7 +294,6 @@ func (bc *BlockChain) setLastBlock() {
bc.LastBlockHash = block.Hash()
bc.LastBlockNumber = block.Number.Uint64()
- chainlogger.Infof("Last known block height #%d\n", bc.LastBlockNumber)
} else {
AddTestNetFunds(bc.genesisBlock)
@@ -309,7 +308,7 @@ func (bc *BlockChain) setLastBlock() {
// Set the last know difficulty (might be 0x0 as initial value, Genesis)
bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD())
- chainlogger.Infof("Last block: %x\n", bc.CurrentBlock.Hash())
+ chainlogger.Infof("Last block (#%d) %x\n", bc.LastBlockNumber, bc.CurrentBlock.Hash())
}
func (bc *BlockChain) SetTotalDifficulty(td *big.Int) {
diff --git a/ethchain/closure.go b/ethchain/closure.go
index cc769de30..1f7f8d703 100644
--- a/ethchain/closure.go
+++ b/ethchain/closure.go
@@ -84,13 +84,7 @@ func (c *Closure) Call(vm *Vm, args []byte) ([]byte, *big.Int, error) {
func (c *Closure) Return(ret []byte) []byte {
// Return the remaining gas to the caller
- // If no caller is present return it to
- // the origin (i.e. contract or tx)
- if c.caller != nil {
- c.caller.ReturnGas(c.Gas, c.Price, c.State)
- } else {
- c.object.ReturnGas(c.Gas, c.Price, c.State)
- }
+ c.caller.ReturnGas(c.Gas, c.Price, c.State)
return ret
}
diff --git a/ethchain/dagger.go b/ethchain/dagger.go
index adf1c2f05..4dda21ff5 100644
--- a/ethchain/dagger.go
+++ b/ethchain/dagger.go
@@ -3,7 +3,6 @@ package ethchain
import (
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog"
- "github.com/ethereum/eth-go/ethreact"
"github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/sha3"
"hash"
@@ -15,7 +14,7 @@ import (
var powlogger = ethlog.NewLogger("POW")
type PoW interface {
- Search(block *Block, reactChan chan ethreact.Event) []byte
+ Search(block *Block, reactChan chan ethutil.React) []byte
Verify(hash []byte, diff *big.Int, nonce []byte) bool
}
@@ -23,7 +22,7 @@ type EasyPow struct {
hash *big.Int
}
-func (pow *EasyPow) Search(block *Block, reactChan chan ethreact.Event) []byte {
+func (pow *EasyPow) Search(block *Block, reactChan chan ethutil.React) []byte {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
hash := block.HashNoNonce()
diff := block.Difficulty
diff --git a/ethchain/state.go b/ethchain/state.go
index 20af94fe8..8df79dcef 100644
--- a/ethchain/state.go
+++ b/ethchain/state.go
@@ -1,6 +1,7 @@
package ethchain
import (
+ "fmt"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethtrie"
"github.com/ethereum/eth-go/ethutil"
@@ -26,70 +27,36 @@ func NewState(trie *ethtrie.Trie) *State {
return &State{trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest()}
}
-// Resets the trie and all siblings
-func (s *State) Reset() {
- s.trie.Undo()
-
- // Reset all nested states
- for _, stateObject := range s.stateObjects {
- if stateObject.state == nil {
- continue
- }
-
- stateObject.state.Reset()
- }
-
- s.Empty()
+// Iterate over each storage address and yield callback
+func (s *State) EachStorage(cb ethtrie.EachCallback) {
+ it := s.trie.NewIterator()
+ it.Each(cb)
}
-// Syncs the trie and all siblings
-func (s *State) Sync() {
- // Sync all nested states
- for _, stateObject := range s.stateObjects {
- s.UpdateStateObject(stateObject)
-
- if stateObject.state == nil {
- continue
- }
-
- stateObject.state.Sync()
+// Retrieve the balance from the given address or 0 if object not found
+func (self *State) GetBalance(addr []byte) *big.Int {
+ stateObject := self.GetStateObject(addr)
+ if stateObject != nil {
+ return stateObject.Amount
}
- s.trie.Sync()
-
- s.Empty()
-}
-
-func (self *State) Empty() {
- self.stateObjects = make(map[string]*StateObject)
+ return ethutil.Big0
}
-func (self *State) Update() {
- for _, stateObject := range self.stateObjects {
- if stateObject.remove {
- self.trie.Delete(string(stateObject.Address()))
- } else {
- self.UpdateStateObject(stateObject)
- }
+func (self *State) GetNonce(addr []byte) uint64 {
+ stateObject := self.GetStateObject(addr)
+ if stateObject != nil {
+ return stateObject.Nonce
}
-}
-// Purges the current trie.
-func (s *State) Purge() int {
- return s.trie.NewIterator().Purge()
+ return 0
}
-func (s *State) EachStorage(cb ethtrie.EachCallback) {
- it := s.trie.NewIterator()
- it.Each(cb)
-}
-
-func (self *State) ResetStateObject(stateObject *StateObject) {
- delete(self.stateObjects, string(stateObject.Address()))
-
- stateObject.state.Reset()
-}
+//
+// Setting, updating & deleting state object methods
+//
+// Update the given state object and apply it to state trie
func (self *State) UpdateStateObject(stateObject *StateObject) {
addr := stateObject.Address()
@@ -100,6 +67,14 @@ func (self *State) UpdateStateObject(stateObject *StateObject) {
self.manifest.AddObjectChange(stateObject)
}
+// Delete the given state object and delete it from the state trie
+func (self *State) DeleteStateObject(stateObject *StateObject) {
+ self.trie.Delete(string(stateObject.Address()))
+
+ delete(self.stateObjects, string(stateObject.Address()))
+}
+
+// Retrieve a state object given my the address. Nil if not found
func (self *State) GetStateObject(addr []byte) *StateObject {
stateObject := self.stateObjects[string(addr)]
if stateObject != nil {
@@ -117,6 +92,7 @@ func (self *State) GetStateObject(addr []byte) *StateObject {
return stateObject
}
+// Retrieve a state object or create a new state object if nil
func (self *State) GetOrNewStateObject(addr []byte) *StateObject {
stateObject := self.GetStateObject(addr)
if stateObject == nil {
@@ -126,6 +102,7 @@ func (self *State) GetOrNewStateObject(addr []byte) *StateObject {
return stateObject
}
+// Create a state object whether it exist in the trie or not
func (self *State) NewStateObject(addr []byte) *StateObject {
statelogger.Infof("(+) %x\n", addr)
@@ -135,10 +112,15 @@ func (self *State) NewStateObject(addr []byte) *StateObject {
return stateObject
}
+// Deprecated
func (self *State) GetAccount(addr []byte) *StateObject {
return self.GetOrNewStateObject(addr)
}
+//
+// Setting, copying of the state methods
+//
+
func (s *State) Cmp(other *State) bool {
return s.trie.Cmp(other.trie)
}
@@ -161,17 +143,82 @@ func (self *State) Set(state *State) {
panic("Tried setting 'state' to nil through 'Set'")
}
- *self = *state
-}
-
-func (s *State) Put(key, object []byte) {
- s.trie.Update(string(key), string(object))
+ self.trie = state.trie
+ self.stateObjects = state.stateObjects
+ //*self = *state
}
func (s *State) Root() interface{} {
return s.trie.Root
}
+// Resets the trie and all siblings
+func (s *State) Reset() {
+ s.trie.Undo()
+
+ // Reset all nested states
+ for _, stateObject := range s.stateObjects {
+ if stateObject.state == nil {
+ continue
+ }
+
+ //stateObject.state.Reset()
+ stateObject.Reset()
+ }
+
+ s.Empty()
+}
+
+// Syncs the trie and all siblings
+func (s *State) Sync() {
+ // Sync all nested states
+ for _, stateObject := range s.stateObjects {
+ s.UpdateStateObject(stateObject)
+
+ if stateObject.state == nil {
+ continue
+ }
+
+ stateObject.state.Sync()
+ }
+
+ s.trie.Sync()
+
+ s.Empty()
+}
+
+func (self *State) Empty() {
+ self.stateObjects = make(map[string]*StateObject)
+}
+
+func (self *State) Update() {
+ for _, stateObject := range self.stateObjects {
+ if stateObject.remove {
+ self.DeleteStateObject(stateObject)
+ } else {
+ stateObject.Sync()
+
+ self.UpdateStateObject(stateObject)
+ }
+ }
+
+ // FIXME trie delete is broken
+ valid, t2 := ethtrie.ParanoiaCheck(self.trie)
+ if !valid {
+ self.trie = t2
+ }
+}
+
+// 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)
+ stateObject.state.EachStorage(func(addr string, value *ethutil.Value) {
+ fmt.Printf("0x%x 0x%x\n", addr, value.Bytes())
+ })
+ }
+}
+
// Object manifest
//
// The object manifest is used to keep changes to the state so we can keep track of the changes
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 52a73beb8..62fcda8a5 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -6,7 +6,6 @@ import (
"fmt"
"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"
@@ -37,7 +36,7 @@ type EthManager interface {
BlockChain() *BlockChain
TxPool() *TxPool
Broadcast(msgType ethwire.MsgType, data []interface{})
- Reactor() *ethreact.ReactorEngine
+ Reactor() *ethutil.ReactorEngine
PeerCount() int
IsMining() bool
IsListening() bool
@@ -67,6 +66,11 @@ type StateManager struct {
// Mining state. The mining state is used purely and solely by the mining
// operation.
miningState *State
+
+ // The last attempted block is mainly used for debugging purposes
+ // This does not have to be a valid block and will be set during
+ // 'Process' & canonical validation.
+ lastAttemptedBlock *Block
}
func NewStateManager(ethereum EthManager) *StateManager {
@@ -146,6 +150,10 @@ done:
receipts = append(receipts, receipt)
handled = append(handled, tx)
+
+ if ethutil.Config.Diff {
+ state.CreateOutputForDiff()
+ }
}
parent.GasUsed = totalUsedGas
@@ -166,6 +174,8 @@ func (sm *StateManager) Process(block *Block, dontReact bool) (err error) {
return ParentError(block.PrevHash)
}
+ sm.lastAttemptedBlock = block
+
var (
parent = sm.bc.GetBlock(block.PrevHash)
state = parent.State()
@@ -177,6 +187,10 @@ 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)
+ }
+
receipts, err := sm.ApplyDiff(state, parent, block)
defer func() {
if err != nil {
diff --git a/ethchain/state_object.go b/ethchain/state_object.go
index 5a43de35c..ebc050863 100644
--- a/ethchain/state_object.go
+++ b/ethchain/state_object.go
@@ -27,6 +27,8 @@ type StateObject struct {
script Code
initScript Code
+ storage map[string]*ethutil.Value
+
// Total gas pool is the total amount of gas currently
// left if this object is the coinbase. Gas is directly
// purchased of the coinbase.
@@ -38,6 +40,10 @@ type StateObject struct {
remove bool
}
+func (self *StateObject) Reset() {
+ self.storage = make(map[string]*ethutil.Value)
+}
+
// Converts an transaction in to a state object
func MakeContract(tx *Transaction, state *State) *StateObject {
// Create contract if there's no recipient
@@ -55,14 +61,19 @@ func MakeContract(tx *Transaction, state *State) *StateObject {
}
func NewStateObject(addr []byte) *StateObject {
- object := &StateObject{address: addr, Amount: new(big.Int), gasPool: new(big.Int)}
+ // 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)
+
+ 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)
return object
}
func NewContract(address []byte, Amount *big.Int, root []byte) *StateObject {
- contract := &StateObject{address: address, Amount: Amount, Nonce: 0}
+ contract := NewStateObject(address)
+ contract.Amount = Amount
contract.state = NewState(ethtrie.NewTrie(ethutil.Config.Db, string(root)))
return contract
@@ -84,6 +95,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)
}
func (c *StateObject) GetAddr(addr []byte) *ethutil.Value {
@@ -94,24 +106,43 @@ func (c *StateObject) SetAddr(addr []byte, value interface{}) {
c.state.trie.Update(string(addr), string(ethutil.NewValue(value).Encode()))
}
-func (c *StateObject) SetStorage(num *big.Int, val *ethutil.Value) {
- addr := ethutil.BigToBytes(num, 256)
+func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value {
+ return self.getStorage(key.Bytes())
+}
+func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) {
+ self.setStorage(key.Bytes(), value)
+}
- if val.BigInt().Cmp(ethutil.Big0) == 0 {
- c.state.trie.Delete(string(addr))
+func (self *StateObject) getStorage(key []byte) *ethutil.Value {
+ k := ethutil.LeftPadBytes(key, 32)
- return
+ value := self.storage[string(k)]
+ if value == nil {
+ value = self.GetAddr(k)
+
+ self.storage[string(k)] = value
}
- c.SetAddr(addr, val)
+ return value
}
-func (c *StateObject) GetStorage(num *big.Int) *ethutil.Value {
- nb := ethutil.BigToBytes(num, 256)
+func (self *StateObject) setStorage(key []byte, value *ethutil.Value) {
+ k := ethutil.LeftPadBytes(key, 32)
- return c.GetAddr(nb)
+ self.storage[string(k)] = value
}
+func (self *StateObject) Sync() {
+ for key, value := range self.storage {
+ if value.BigInt().Cmp(ethutil.Big0) == 0 {
+ self.state.trie.Delete(string(key))
+ continue
+ }
+
+ self.SetAddr([]byte(key), value)
+
+ }
+}
func (c *StateObject) GetInstr(pc *big.Int) *ethutil.Value {
if int64(len(c.script)-1) < pc.Int64() {
return ethutil.NewValue(0)
@@ -248,6 +279,7 @@ func (c *StateObject) RlpDecode(data []byte) {
c.Nonce = decoder.Get(0).Uint()
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.ScriptHash = decoder.Get(3).Bytes()
diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go
index 6ea9a837d..314d858f2 100644
--- a/ethchain/state_transition.go
+++ b/ethchain/state_transition.go
@@ -164,8 +164,6 @@ func (self *StateTransition) TransitionState() (err error) {
// Increment the nonce for the next transaction
sender.Nonce += 1
- receiver = self.Receiver()
-
// Transaction gas
if err = self.UseGas(GasTx); err != nil {
return
@@ -178,13 +176,23 @@ 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 the receiver is nil it's a contract (\0*32).
- if receiver == nil {
+ if tx.CreatesContract() {
+ snapshot = self.state.Copy()
+
// Create a new state object for the contract
receiver = self.MakeStateObject(self.state, tx)
+ self.rec = receiver
if receiver == nil {
return fmt.Errorf("Unable to create contract")
}
+ } else {
+ receiver = self.Receiver()
}
// Transfer value from sender to receiver
@@ -192,7 +200,9 @@ func (self *StateTransition) TransitionState() (err error) {
return
}
- //snapshot := self.state.Copy()
+ if snapshot == nil {
+ snapshot = self.state.Copy()
+ }
// Process the init code and create 'valid' contract
if IsContractAddr(self.receiver) {
@@ -203,8 +213,7 @@ func (self *StateTransition) TransitionState() (err error) {
code, err := self.Eval(receiver.Init(), receiver, "init")
if err != nil {
- //self.state.Set(snapshot)
- self.state.ResetStateObject(receiver)
+ self.state.Set(snapshot)
return fmt.Errorf("Error during init execution %v", err)
}
@@ -214,8 +223,7 @@ func (self *StateTransition) TransitionState() (err error) {
if len(receiver.Script()) > 0 {
_, err = self.Eval(receiver.Script(), receiver, "code")
if err != nil {
- //self.state.Set(snapshot)
- self.state.ResetStateObject(receiver)
+ self.state.Set(snapshot)
return fmt.Errorf("Error during code execution %v", err)
}
diff --git a/ethchain/vm.go b/ethchain/vm.go
index 769333649..f1794ff77 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -22,12 +22,16 @@ var (
GasMemory = big.NewInt(1)
GasData = big.NewInt(5)
GasTx = big.NewInt(500)
+
+ LogTyPretty byte = 0x1
+ LogTyDiff byte = 0x2
)
type Debugger interface {
BreakHook(step int, op OpCode, mem *Memory, stack *Stack, stateObject *StateObject) bool
StepHook(step int, op OpCode, mem *Memory, stack *Stack, stateObject *StateObject) bool
BreakPoints() []int64
+ SetCode(byteCode []byte)
}
type Vm struct {
@@ -44,6 +48,7 @@ type Vm struct {
Verbose bool
+ logTy byte
logStr string
err error
@@ -69,7 +74,7 @@ type RuntimeVars struct {
}
func (self *Vm) Printf(format string, v ...interface{}) *Vm {
- if self.Verbose {
+ if self.Verbose && self.logTy == LogTyPretty {
self.logStr += fmt.Sprintf(format, v...)
}
@@ -77,7 +82,7 @@ func (self *Vm) Printf(format string, v ...interface{}) *Vm {
}
func (self *Vm) Endl() *Vm {
- if self.Verbose {
+ if self.Verbose && self.logTy == LogTyPretty {
vmlogger.Debugln(self.logStr)
self.logStr = ""
}
@@ -86,7 +91,12 @@ func (self *Vm) Endl() *Vm {
}
func NewVm(state *State, stateManager *StateManager, vars RuntimeVars) *Vm {
- return &Vm{vars: vars, state: state, stateManager: stateManager}
+ lt := LogTyPretty
+ if ethutil.Config.Diff {
+ lt = LogTyDiff
+ }
+
+ return &Vm{vars: vars, state: state, stateManager: stateManager, logTy: lt}
}
var Pow256 = ethutil.BigPow(2, 256)
@@ -103,7 +113,17 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
}
}()
- vmlogger.Debugf("(%s) %x gas: %v (d) %x\n", vm.Fn, closure.object.Address(), closure.Gas, closure.Args)
+ // Debug hook
+ if vm.Dbg != nil {
+ vm.Dbg.SetCode(closure.Script)
+ }
+
+ // Don't bother with the execution if there's no code.
+ if len(closure.Script) == 0 {
+ return closure.Return(nil), nil
+ }
+
+ vmlogger.Debugf("(%s) %x gas: %v (d) %x\n", vm.Fn, closure.Address(), closure.Gas, closure.Args)
var (
op OpCode
@@ -132,6 +152,17 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
// Get the opcode (it must be an opcode!)
op = OpCode(val.Uint())
+ // XXX Leave this Println intact. Don't change this to the log system.
+ // Used for creating diffs between implementations
+ if vm.logTy == LogTyDiff {
+ b := pc.Bytes()
+ if len(b) == 0 {
+ b = []byte{0}
+ }
+
+ fmt.Printf("%x %x %x %x\n", closure.Address(), b, []byte{byte(op)}, closure.Gas.Bytes())
+ }
+
gas := new(big.Int)
addStepGasUsage := func(amount *big.Int) {
if amount.Cmp(ethutil.Big0) >= 0 {
@@ -167,7 +198,9 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
require(2)
newMemSize = stack.Peek().Uint64() + 32
case MLOAD:
+ require(1)
+ newMemSize = stack.Peek().Uint64() + 32
case MSTORE8:
require(2)
newMemSize = stack.Peek().Uint64() + 1
@@ -415,7 +448,10 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
require(2)
val, th := stack.Popn()
if th.Cmp(big.NewInt(32)) < 0 {
- stack.Push(big.NewInt(int64(len(val.Bytes())-1) - th.Int64()))
+ byt := big.NewInt(int64(val.Bytes()[th.Int64()]))
+ stack.Push(byt)
+
+ vm.Printf(" => 0x%x", byt.Bytes())
} else {
stack.Push(ethutil.BigFalse)
}
@@ -427,13 +463,26 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
data := ethcrypto.Sha3Bin(mem.Get(offset.Int64(), size.Int64()))
stack.Push(ethutil.BigD(data))
+
+ vm.Printf(" => %x", data)
// 0x30 range
case ADDRESS:
- stack.Push(ethutil.BigD(closure.Object().Address()))
+ stack.Push(ethutil.BigD(closure.Address()))
+
+ vm.Printf(" => %x", closure.Address())
case BALANCE:
- stack.Push(closure.object.Amount)
+ require(1)
+
+ addr := stack.Pop().Bytes()
+ balance := vm.state.GetBalance(addr)
+
+ stack.Push(balance)
+
+ vm.Printf(" => %v (%x)", balance, addr)
case ORIGIN:
stack.Push(ethutil.BigD(vm.vars.Origin))
+
+ vm.Printf(" => %v", vm.vars.Origin)
case CALLER:
caller := closure.caller.Address()
stack.Push(ethutil.BigD(caller))
@@ -441,6 +490,8 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
vm.Printf(" => %x", caller)
case CALLVALUE:
stack.Push(vm.vars.Value)
+
+ vm.Printf(" => %v", vm.vars.Value)
case CALLDATALOAD:
require(1)
offset := stack.Pop().Int64()
@@ -499,8 +550,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)
mem.Set(mOff, l, code)
+ fmt.Println(Code(mem.Get(mOff, l)))
case GASPRICE:
stack.Push(closure.Price)
@@ -562,8 +615,9 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case MSTORE8:
require(2)
val, mStart := stack.Popn()
- base.And(val, new(big.Int).SetInt64(0xff))
- mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(base, 256))
+ //base.And(val, new(big.Int).SetInt64(0xff))
+ //mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(base, 256))
+ mem.store[mStart.Int64()] = byte(val.Int64() & 0xff)
vm.Printf(" => 0x%x", val)
case SLOAD:
@@ -623,9 +677,9 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
)
// Generate a new address
- addr := ethcrypto.CreateAddress(closure.object.Address(), closure.object.Nonce)
+ addr := ethcrypto.CreateAddress(closure.Address(), closure.N().Uint64())
for i := uint64(0); vm.state.GetStateObject(addr) != nil; i++ {
- ethcrypto.CreateAddress(closure.object.Address(), closure.object.Nonce+i)
+ ethcrypto.CreateAddress(closure.Address(), closure.N().Uint64()+i)
}
closure.object.Nonce++
@@ -638,14 +692,15 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
contract.AddAmount(value)
// Set the init script
- contract.initScript = mem.Get(offset.Int64(), size.Int64())
+ initCode := mem.Get(offset.Int64(), size.Int64())
+ //fmt.Printf("%x\n", initCode)
// Transfer all remaining gas to the new
// contract so it may run the init script
gas := new(big.Int).Set(closure.Gas)
closure.UseGas(closure.Gas)
// Create the closure
- c := NewClosure(closure, contract, contract.initScript, vm.state, gas, closure.Price)
+ c := NewClosure(closure, contract, initCode, vm.state, gas, closure.Price)
// Call the closure and set the return value as
// main script.
contract.script, err = Call(vm, c, nil)
@@ -665,6 +720,11 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
vm.Printf("CREATE success")
}
vm.Endl()
+
+ // Debug hook
+ if vm.Dbg != nil {
+ vm.Dbg.SetCode(closure.Script)
+ }
case CALL:
require(7)
@@ -683,10 +743,11 @@ 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)
} else {
- //snapshot := vm.state.Copy()
+ snapshot := vm.state.Copy()
stateObject := vm.state.GetOrNewStateObject(addr.Bytes())
@@ -702,13 +763,17 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
vmlogger.Debugf("Closure execution failed. %v\n", err)
- //vm.state.Set(snapshot)
- vm.state.ResetStateObject(stateObject)
+ vm.state.Set(snapshot)
} else {
stack.Push(ethutil.BigTrue)
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
}
+
+ // Debug hook
+ if vm.Dbg != nil {
+ vm.Dbg.SetCode(closure.Script)
+ }
}
case RETURN:
require(2)
@@ -721,18 +786,12 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
case SUICIDE:
require(1)
- receiver := vm.state.GetAccount(stack.Pop().Bytes())
+ receiver := vm.state.GetOrNewStateObject(stack.Pop().Bytes())
+
receiver.AddAmount(closure.object.Amount)
closure.object.MarkForDeletion()
- /*
- trie := closure.object.state.trie
- trie.NewIterator().Each(func(key string, v *ethutil.Value) {
- trie.Delete(key)
- })
- */
-
fallthrough
case STOP: // Stop the closure
vm.Endl()
@@ -752,6 +811,8 @@ func (vm *Vm) RunClosure(closure *Closure) (ret []byte, err error) {
if vm.Dbg != nil {
for _, instrNo := range vm.Dbg.BreakPoints() {
if pc.Cmp(big.NewInt(instrNo)) == 0 {
+ vm.Stepping = true
+
if !vm.Dbg.BreakHook(prevStep, op, mem, stack, closure.Object()) {
return nil, nil
}
diff --git a/ethcrypto/crypto.go b/ethcrypto/crypto.go
index b4bb881a0..19f8c9e55 100644
--- a/ethcrypto/crypto.go
+++ b/ethcrypto/crypto.go
@@ -2,9 +2,9 @@ package ethcrypto
import (
"code.google.com/p/go.crypto/ripemd160"
+ "code.google.com/p/go.crypto/sha3"
"crypto/sha256"
"github.com/ethereum/eth-go/ethutil"
- "github.com/obscuren/sha3"
)
func Sha256Bin(data []byte) []byte {
diff --git a/ethcrypto/mnemonic.go b/ethcrypto/mnemonic.go
index 6134f85f7..725846792 100644
--- a/ethcrypto/mnemonic.go
+++ b/ethcrypto/mnemonic.go
@@ -3,7 +3,9 @@ package ethcrypto
import (
"fmt"
"io/ioutil"
+ "os"
"path"
+ "path/filepath"
"runtime"
"strconv"
"strings"
@@ -12,6 +14,14 @@ import (
func InitWords() []string {
_, thisfile, _, _ := runtime.Caller(1)
filename := path.Join(path.Dir(thisfile), "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))
+ }
+ 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))
diff --git a/ethereum.go b/ethereum.go
index de4e915a1..2806dfd9d 100644
--- a/ethereum.go
+++ b/ethereum.go
@@ -6,7 +6,6 @@ import (
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethcrypto"
"github.com/ethereum/eth-go/ethlog"
- "github.com/ethereum/eth-go/ethreact"
"github.com/ethereum/eth-go/ethrpc"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
@@ -21,6 +20,8 @@ import (
"time"
)
+const seedTextFileUri string = "http://www.ethereum.org/servers.poc3.txt"
+
var ethlogger = ethlog.NewLogger("SERV")
func eachPeer(peers *list.List, callback func(*Peer, *list.Element)) {
@@ -72,7 +73,7 @@ type Ethereum struct {
listening bool
- reactor *ethreact.ReactorEngine
+ reactor *ethutil.ReactorEngine
RpcServer *ethrpc.JsonRpcServer
@@ -107,7 +108,7 @@ func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager
keyManager: keyManager,
clientIdentity: clientIdentity,
}
- ethereum.reactor = ethreact.New()
+ ethereum.reactor = ethutil.NewReactorEngine()
ethereum.txPool = ethchain.NewTxPool(ethereum)
ethereum.blockChain = ethchain.NewBlockChain(ethereum)
@@ -119,7 +120,7 @@ func New(db ethutil.Database, clientIdentity ethwire.ClientIdentity, keyManager
return ethereum, nil
}
-func (s *Ethereum) Reactor() *ethreact.ReactorEngine {
+func (s *Ethereum) Reactor() *ethutil.ReactorEngine {
return s.reactor
}
@@ -351,7 +352,6 @@ func (s *Ethereum) ReapDeadPeerHandler() {
// Start the ethereum
func (s *Ethereum) Start(seed bool) {
- s.reactor.Start()
// Bind to addr and port
ln, err := net.Listen("tcp", ":"+s.Port)
if err != nil {
@@ -418,7 +418,7 @@ func (s *Ethereum) Seed() {
s.ProcessPeerList(peers)
} else {
// Fallback to servers.poc3.txt
- resp, err := http.Get("http://www.ethereum.org/servers.poc3.txt")
+ resp, err := http.Get(seedTextFileUri)
if err != nil {
ethlogger.Warnln("Fetching seed failed:", err)
return
@@ -463,9 +463,6 @@ func (s *Ethereum) Stop() {
s.txPool.Stop()
s.stateManager.Stop()
- s.reactor.Flush()
- s.reactor.Stop()
-
ethlogger.Infoln("Server stopped")
close(s.shutdownChan)
}
diff --git a/ethlog/loggers.go b/ethlog/loggers.go
index 4e950cadd..f13186102 100644
--- a/ethlog/loggers.go
+++ b/ethlog/loggers.go
@@ -97,7 +97,6 @@ func Reset() {
}
<-status
}
- logSystems = nil
}
// waits until log messages are drained (dispatched to log writers)
@@ -116,6 +115,7 @@ func NewLogger(tag string) *Logger {
}
func AddLogSystem(logSystem LogSystem) {
+ var mutex = &sync.Mutex{}
mutex.Lock()
defer mutex.Unlock()
if logSystems == nil {
@@ -128,14 +128,16 @@ func AddLogSystem(logSystem LogSystem) {
}
func (logger *Logger) sendln(level LogLevel, v ...interface{}) {
- if logSystems != nil {
- send(newPrintlnLogMessage(level, logger.tag, v...))
+ if logMessages != nil {
+ msg := newPrintlnLogMessage(level, logger.tag, v...)
+ logMessages <- msg
}
}
func (logger *Logger) sendf(level LogLevel, format string, v ...interface{}) {
- if logSystems != nil {
- send(newPrintfLogMessage(level, logger.tag, format, v...))
+ if logMessages != nil {
+ msg := newPrintfLogMessage(level, logger.tag, format, v...)
+ logMessages <- msg
}
}
diff --git a/ethlog/loggers_test.go b/ethlog/loggers_test.go
index 0e1c12e55..a9b1463e7 100644
--- a/ethlog/loggers_test.go
+++ b/ethlog/loggers_test.go
@@ -54,8 +54,9 @@ func TestLoggerPrintln(t *testing.T) {
Flush()
Reset()
output := testLogSystem.Output
+ fmt.Println(quote(output))
if output != "[TEST] error\n[TEST] warn\n" {
- t.Error("Expected logger output '[TEST] error\\n[TEST] warn\\n', got ", testLogSystem.Output)
+ t.Error("Expected logger output '[TEST] error\\n[TEST] warn\\n', got ", output)
}
}
@@ -71,7 +72,7 @@ func TestLoggerPrintf(t *testing.T) {
Reset()
output := testLogSystem.Output
if output != "[TEST] error to { 2}\n[TEST] warn" {
- t.Error("Expected logger output '[TEST] error to { 2}\\n[TEST] warn', got ", testLogSystem.Output)
+ t.Error("Expected logger output '[TEST] error to { 2}\\n[TEST] warn', got ", output)
}
}
@@ -88,10 +89,10 @@ func TestMultipleLogSystems(t *testing.T) {
output0 := testLogSystem0.Output
output1 := testLogSystem1.Output
if output0 != "[TEST] error\n" {
- t.Error("Expected logger 0 output '[TEST] error\\n', got ", testLogSystem0.Output)
+ t.Error("Expected logger 0 output '[TEST] error\\n', got ", output0)
}
if output1 != "[TEST] error\n[TEST] warn\n" {
- t.Error("Expected logger 1 output '[TEST] error\\n[TEST] warn\\n', got ", testLogSystem1.Output)
+ t.Error("Expected logger 1 output '[TEST] error\\n[TEST] warn\\n', got ", output1)
}
}
@@ -104,7 +105,6 @@ func TestFileLogSystem(t *testing.T) {
logger.Errorf("error to %s\n", filename)
logger.Warnln("warn")
Flush()
- Reset()
contents, _ := ioutil.ReadFile(filename)
output := string(contents)
if output != "[TEST] error to test.log\n[TEST] warn\n" {
@@ -117,7 +117,5 @@ func TestFileLogSystem(t *testing.T) {
func TestNoLogSystem(t *testing.T) {
logger := NewLogger("TEST")
logger.Warnln("warn")
- fmt.Println("1")
Flush()
- Reset()
}
diff --git a/ethminer/miner.go b/ethminer/miner.go
index 8224c5441..71d4b2428 100644
--- a/ethminer/miner.go
+++ b/ethminer/miner.go
@@ -4,7 +4,7 @@ import (
"bytes"
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethlog"
- "github.com/ethereum/eth-go/ethreact"
+ "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
"sort"
)
@@ -15,19 +15,19 @@ type Miner struct {
pow ethchain.PoW
ethereum ethchain.EthManager
coinbase []byte
- reactChan chan ethreact.Event
+ reactChan chan ethutil.React
txs ethchain.Transactions
uncles []*ethchain.Block
block *ethchain.Block
powChan chan []byte
- powQuitChan chan ethreact.Event
+ powQuitChan chan ethutil.React
quitChan chan bool
}
func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner {
- reactChan := make(chan ethreact.Event, 1) // This is the channel that receives 'updates' when ever a new transaction or block comes in
- powChan := make(chan []byte, 1) // This is the channel that receives valid sha hases for a given block
- powQuitChan := make(chan ethreact.Event, 1) // This is the channel that can exit the miner thread
+ reactChan := make(chan ethutil.React, 1) // This is the channel that receives 'updates' when ever a new transaction or block comes in
+ powChan := make(chan []byte, 1) // This is the channel that receives valid sha hases for a given block
+ powQuitChan := make(chan ethutil.React, 1) // This is the channel that can exit the miner thread
quitChan := make(chan bool, 1)
ethereum.Reactor().Subscribe("newBlock", reactChan)
diff --git a/ethreact/README.md b/ethreact/README.md
deleted file mode 100644
index 592b50b96..000000000
--- a/ethreact/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# ethreact
-
-ethereum event reactor. Component of the ethereum stack.
-various events like state change on an account or new block found are broadcast to subscribers.
-Broadcasting to subscribers is running on its own routine and globally order preserving.
-
-## Clients
-### subscribe
-
- eventChannel := make(chan ethreact.Event)
- reactor.Subscribe(event, eventChannel)
-
-The same channel can be subscribed to multiple events but only once for each event. In order to allow order of events to be preserved, broadcast of events is synchronous within the main broadcast loop. Therefore any blocking subscriber channels will be skipped, i.e. missing broadcasting events while they are blocked.
-
-### unsubscribe
-
- reactor.Unsubscribe(event, eventChannel)
-
-### Processing events
-
-event.Resource is of type interface{}. The actual type of event.Resource depends on event.Name and may need to be cast for processing.
-
- var event ethreact.Event
- for {
- select {
- case event = <-eventChannel:
- processTransaction(event.Resource.(Transaction))
- }
- }
-
-## Broadcast
-
- reactor := ethreact.New()
- reactor.Start()
- reactor.Post(name, resource)
- reactor.Flush() // wait till all broadcast messages are dispatched
- reactor.Stop() // stop the main broadcast loop immediately (even if there are unbroadcast events left)
-
-
-
diff --git a/ethreact/reactor_test.go b/ethreact/reactor_test.go
deleted file mode 100644
index 801a8abd0..000000000
--- a/ethreact/reactor_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package ethreact
-
-import (
- "fmt"
- "testing"
-)
-
-func TestReactorAdd(t *testing.T) {
- reactor := New()
- ch := make(chan Event)
- reactor.Subscribe("test", ch)
- if reactor.eventHandlers["test"] == nil {
- t.Error("Expected new eventHandler to be created")
- }
- reactor.Unsubscribe("test", ch)
- if reactor.eventHandlers["test"] != nil {
- t.Error("Expected eventHandler to be removed")
- }
-}
-
-func TestReactorEvent(t *testing.T) {
- var name string
- reactor := New()
- // Buffer the channel, so it doesn't block for this test
- cap := 20
- ch := make(chan Event, cap)
- reactor.Subscribe("even", ch)
- reactor.Subscribe("odd", ch)
- reactor.Post("even", "disappears") // should not broadcast if engine not started
- reactor.Start()
- for i := 0; i < cap; i++ {
- if i%2 == 0 {
- name = "even"
- } else {
- name = "odd"
- }
- reactor.Post(name, i)
- }
- reactor.Post("test", cap) // this should not block
- i := 0
- reactor.Flush()
- close(ch)
- for event := range ch {
- fmt.Printf("%d: %v", i, event)
- if i%2 == 0 {
- name = "even"
- } else {
- name = "odd"
- }
- if val, ok := event.Resource.(int); ok {
- if i != val || event.Name != name {
- t.Error("Expected event %d to be of type %s and resource %d, got ", i, name, i, val)
- }
- } else {
- t.Error("Unable to cast")
- }
- i++
- }
- if i != cap {
- t.Error("excpected exactly %d events, got ", i)
- }
- reactor.Stop()
-}
diff --git a/ethutil/common.go b/ethutil/common.go
index 6d88a1ed2..2fd031a20 100644
--- a/ethutil/common.go
+++ b/ethutil/common.go
@@ -3,8 +3,20 @@ package ethutil
import (
"fmt"
"math/big"
+ "runtime"
)
+func IsWindows() bool {
+ return runtime.GOOS == "windows"
+}
+
+func WindonizePath(path string) string {
+ if string(path[0]) == "/" && IsWindows() {
+ path = path[1:]
+ }
+ return path
+}
+
// The different number of units
var (
Douglas = BigPow(10, 42)
diff --git a/ethutil/config.go b/ethutil/config.go
index c9b86100b..2f3d706fe 100644
--- a/ethutil/config.go
+++ b/ethutil/config.go
@@ -13,6 +13,7 @@ type ConfigManager struct {
ExecPath string
Debug bool
+ Diff bool
Paranoia bool
conf *globalconf.GlobalConf
diff --git a/ethutil/reactor.go b/ethutil/reactor.go
new file mode 100644
index 000000000..7cf145245
--- /dev/null
+++ b/ethutil/reactor.go
@@ -0,0 +1,87 @@
+package ethutil
+
+import (
+ "sync"
+)
+
+type ReactorEvent struct {
+ mut sync.Mutex
+ event string
+ chans []chan React
+}
+
+// Post the specified reactor resource on the channels
+// currently subscribed
+func (e *ReactorEvent) Post(react React) {
+ e.mut.Lock()
+ defer e.mut.Unlock()
+
+ for _, ch := range e.chans {
+ go func(ch chan React) {
+ ch <- react
+ }(ch)
+ }
+}
+
+// Add a subscriber to this event
+func (e *ReactorEvent) Add(ch chan React) {
+ e.mut.Lock()
+ defer e.mut.Unlock()
+
+ e.chans = append(e.chans, ch)
+}
+
+// Remove a subscriber
+func (e *ReactorEvent) Remove(ch chan React) {
+ e.mut.Lock()
+ defer e.mut.Unlock()
+
+ for i, c := range e.chans {
+ if c == ch {
+ e.chans = append(e.chans[:i], e.chans[i+1:]...)
+ }
+ }
+}
+
+// Basic reactor resource
+type React struct {
+ Resource interface{}
+ Event string
+}
+
+// The reactor basic engine. Acts as bridge
+// between the events and the subscribers/posters
+type ReactorEngine struct {
+ patterns map[string]*ReactorEvent
+}
+
+func NewReactorEngine() *ReactorEngine {
+ return &ReactorEngine{patterns: make(map[string]*ReactorEvent)}
+}
+
+// Subscribe a channel to the specified event
+func (reactor *ReactorEngine) Subscribe(event string, ch chan React) {
+ ev := reactor.patterns[event]
+ // Create a new event if one isn't available
+ if ev == nil {
+ ev = &ReactorEvent{event: event}
+ reactor.patterns[event] = ev
+ }
+
+ // Add the channel to reactor event handler
+ ev.Add(ch)
+}
+
+func (reactor *ReactorEngine) Unsubscribe(event string, ch chan React) {
+ ev := reactor.patterns[event]
+ if ev != nil {
+ ev.Remove(ch)
+ }
+}
+
+func (reactor *ReactorEngine) Post(event string, resource interface{}) {
+ ev := reactor.patterns[event]
+ if ev != nil {
+ ev.Post(React{Resource: resource, Event: event})
+ }
+}
diff --git a/ethutil/reactor_test.go b/ethutil/reactor_test.go
new file mode 100644
index 000000000..48c2f0df3
--- /dev/null
+++ b/ethutil/reactor_test.go
@@ -0,0 +1,30 @@
+package ethutil
+
+import "testing"
+
+func TestReactorAdd(t *testing.T) {
+ engine := NewReactorEngine()
+ ch := make(chan React)
+ engine.Subscribe("test", ch)
+ if len(engine.patterns) != 1 {
+ t.Error("Expected patterns to be 1, got", len(engine.patterns))
+ }
+}
+
+func TestReactorEvent(t *testing.T) {
+ engine := NewReactorEngine()
+
+ // Buffer 1, so it doesn't block for this test
+ ch := make(chan React, 1)
+ engine.Subscribe("test", ch)
+ engine.Post("test", "hello")
+
+ value := <-ch
+ if val, ok := value.Resource.(string); ok {
+ if val != "hello" {
+ t.Error("Expected Resource to be 'hello', got", val)
+ }
+ } else {
+ t.Error("Unable to cast")
+ }
+}
diff --git a/ethutil/script.go b/ethutil/script.go
index f5c53f84c..b796e7c1e 100644
--- a/ethutil/script.go
+++ b/ethutil/script.go
@@ -4,7 +4,6 @@ import (
"fmt"
"github.com/obscuren/mutan"
"github.com/obscuren/mutan/backends"
- "github.com/obscuren/serpent-go"
"strings"
)
@@ -15,13 +14,15 @@ func Compile(script string, silent bool) (ret []byte, err error) {
if len(line) > 1 && line[0:2] == "#!" {
switch line {
- case "#!serpent":
- byteCode, err := serpent.Compile(script)
- if err != nil {
- return nil, err
- }
+ /*
+ case "#!serpent":
+ byteCode, err := serpent.Compile(script)
+ if err != nil {
+ return nil, err
+ }
- return byteCode, nil
+ return byteCode, nil
+ */
}
} else {
diff --git a/ethwire/messaging.go b/ethwire/messaging.go
index 5319d0711..f13b72353 100644
--- a/ethwire/messaging.go
+++ b/ethwire/messaging.go
@@ -279,7 +279,7 @@ func ReadMessages(conn net.Conn) (msgs []*Msg, err error) {
var totalBytes int
for {
// Give buffering some time
- conn.SetReadDeadline(time.Now().Add(50 * time.Millisecond))
+ conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond))
// Create a new temporarily buffer
b := make([]byte, 1440)
// Wait for a message from this peer
diff --git a/peer.go b/peer.go
index a93d22d93..0a4f08af5 100644
--- a/peer.go
+++ b/peer.go
@@ -21,7 +21,7 @@ const (
// The size of the output buffer for writing messages
outputBufferSize = 50
// Current protocol version
- ProtocolVersion = 21
+ ProtocolVersion = 23
// Interval for ping/pong message
pingPongTimer = 2 * time.Second
)
@@ -252,7 +252,7 @@ func (p *Peer) writeMessage(msg *ethwire.Msg) {
}
}
- peerlogger.DebugDetailln("<=", msg.Type, msg.Data)
+ peerlogger.DebugDetailf("(%v) <= %v %v\n", p.conn.RemoteAddr(), msg.Type, msg.Data)
err := ethwire.WriteMessage(p.conn, msg)
if err != nil {
@@ -326,7 +326,7 @@ func (p *Peer) HandleInbound() {
peerlogger.Debugln(err)
}
for _, msg := range msgs {
- peerlogger.DebugDetailln("=>", msg.Type, msg.Data)
+ peerlogger.DebugDetailf("(%v) => %v %v\n", p.conn.RemoteAddr(), msg.Type, msg.Data)
switch msg.Type {
case ethwire.MsgHandshakeTy:
@@ -419,6 +419,16 @@ func (p *Peer) HandleInbound() {
if err != nil {
// If the parent is unknown try to catch up with this peer
if ethchain.IsParentErr(err) {
+ /*
+ b := ethchain.NewBlockFromRlpValue(msg.Data.Get(0))
+
+ peerlogger.Infof("Attempting to catch (%x). Parent known\n", b.Hash())
+ p.catchingUp = false
+
+ p.CatchupWithPeer(b.Hash())
+
+ peerlogger.Infoln(b)
+ */
peerlogger.Infoln("Attempting to catch. Parent known")
p.catchingUp = false
p.CatchupWithPeer(p.ethereum.BlockChain().CurrentBlock.Hash())
@@ -744,7 +754,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(50)})
+ msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(10)})
p.QueueMessage(msg)
peerlogger.DebugDetailf("Requesting blockchain %x... from peer %s\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4], p.conn.RemoteAddr())