From 38d6b67b5cfbfb63620a244ea01b5b534917128f Mon Sep 17 00:00:00 2001
From: obscuren <geffobscura@gmail.com>
Date: Tue, 29 Apr 2014 12:36:27 +0200
Subject: [PATCH] Fixed state problem

---
 ethchain/block.go         |  5 +----
 ethchain/block_chain.go   |  3 ++-
 ethchain/state_manager.go | 13 +++++++------
 ethminer/miner.go         | 12 +++++++-----
 ethutil/bytes.go          | 10 ++++++++++
 ethutil/trie.go           | 19 +++++++++++++++++--
 peer.go                   |  6 ++++--
 7 files changed, 48 insertions(+), 20 deletions(-)

diff --git a/ethchain/block.go b/ethchain/block.go
index d95ebf4b5..aac50ccb1 100644
--- a/ethchain/block.go
+++ b/ethchain/block.go
@@ -80,9 +80,6 @@ func CreateBlock(root interface{},
 	extra string,
 	txes []*Transaction) *Block {
 
-	// Copy over the bytes
-	copiedRoot := ethutil.NewValue(root).Bytes()
-
 	block := &Block{
 		// Slice of transactions to include in this block
 		transactions:   txes,
@@ -98,7 +95,7 @@ func CreateBlock(root interface{},
 	block.SetTransactions(txes)
 	block.SetUncles([]*Block{})
 
-	block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, copiedRoot))
+	block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, root))
 
 	for _, tx := range txes {
 		block.MakeContract(tx)
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go
index 08886c9cd..2be4cd92b 100644
--- a/ethchain/block_chain.go
+++ b/ethchain/block_chain.go
@@ -179,7 +179,8 @@ func (bc *BlockChain) ResetTillBlockHash(hash []byte) error {
 		bc.LastBlockNumber = info.Number
 	}
 
-	bc.Ethereum.StateManager().PrepareDefault(returnTo)
+	// XXX Why are we resetting? This is the block chain, it has nothing to do with states
+	//bc.Ethereum.StateManager().PrepareDefault(returnTo)
 
 	err := ethutil.Config.Db.Delete(lastBlock.Hash())
 	if err != nil {
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 628ab6a27..70d4155c3 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -158,18 +158,19 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
 	// Processing a blocks may never happen simultaneously
 	sm.mutex.Lock()
 	defer sm.mutex.Unlock()
-	// Defer the Undo on the Trie. If the block processing happened
-	// we don't want to undo but since undo only happens on dirty
-	// nodes this won't happen because Commit would have been called
-	// before that.
-	defer sm.bc.CurrentBlock.Undo()
 	hash := block.Hash()
 
 	if sm.bc.HasBlock(hash) {
-		fmt.Println("[SM] We already have this block, ignoring")
+		fmt.Println("[STATE] We already have this block, ignoring")
 		return nil
 	}
 
+	// Defer the Undo on the Trie. If the block processing happened
+	// we don't want to undo but since undo only happens on dirty
+	// nodes this won't happen because Commit would have been called
+	// before that.
+	defer sm.bc.CurrentBlock.Undo()
+
 	// Check if we have the parent hash, if it isn't known we discard it
 	// Reasons might be catching up or simply an invalid block
 	if !sm.bc.HasBlock(block.PrevHash) && sm.bc.CurrentBlock != nil {
diff --git a/ethminer/miner.go b/ethminer/miner.go
index 791e8e402..c93267161 100644
--- a/ethminer/miner.go
+++ b/ethminer/miner.go
@@ -2,6 +2,7 @@ package ethminer
 
 import (
 	"bytes"
+	"fmt"
 	"github.com/ethereum/eth-go/ethchain"
 	"github.com/ethereum/eth-go/ethutil"
 	"github.com/ethereum/eth-go/ethwire"
@@ -61,10 +62,10 @@ func (miner *Miner) listener() {
 		select {
 		case chanMessage := <-miner.reactChan:
 			if block, ok := chanMessage.Resource.(*ethchain.Block); ok {
-				//log.Println("[MINER] Got new block via Reactor")
+				log.Println("[MINER] Got new block via Reactor")
 				if bytes.Compare(miner.ethereum.BlockChain().CurrentBlock.Hash(), block.Hash()) == 0 {
 					// TODO: Perhaps continue mining to get some uncle rewards
-					//log.Println("[MINER] New top block found resetting state")
+					log.Println("[MINER] New top block found resetting state")
 
 					// Filter out which Transactions we have that were not in this block
 					var newtxs []*ethchain.Transaction
@@ -86,7 +87,7 @@ func (miner *Miner) listener() {
 
 				} else {
 					if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 {
-						//log.Println("[MINER] Adding uncle block")
+						log.Println("[MINER] Adding uncle block")
 						miner.uncles = append(miner.uncles, block)
 						miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State())
 					}
@@ -133,8 +134,9 @@ func (miner *Miner) listener() {
 				miner.ethereum.StateManager().PrepareDefault(miner.block)
 				err := miner.ethereum.StateManager().ProcessBlock(miner.block, true)
 				if err != nil {
-					log.Println("Error result from process block:", err)
-					miner.block.State().Reset()
+					log.Println(err)
+					miner.txs = []*ethchain.Transaction{} // Move this somewhere neat
+					miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs)
 				} else {
 
 					/*
diff --git a/ethutil/bytes.go b/ethutil/bytes.go
index 957fa254a..500368017 100644
--- a/ethutil/bytes.go
+++ b/ethutil/bytes.go
@@ -73,3 +73,13 @@ func BinaryLength(num int) int {
 
 	return 1 + BinaryLength(num>>8)
 }
+
+// Copy bytes
+//
+// Returns an exact copy of the provided bytes
+func CopyBytes(b []byte) (copiedBytes []byte) {
+	copiedBytes = make([]byte, len(b))
+	copy(copiedBytes, b)
+
+	return
+}
diff --git a/ethutil/trie.go b/ethutil/trie.go
index c67f750bc..4d088ccff 100644
--- a/ethutil/trie.go
+++ b/ethutil/trie.go
@@ -119,14 +119,29 @@ type Trie struct {
 	cache *Cache
 }
 
+func copyRoot(root interface{}) interface{} {
+	var prevRootCopy interface{}
+	if b, ok := root.([]byte); ok {
+		prevRootCopy = CopyBytes(b)
+	} else {
+		prevRootCopy = root
+	}
+
+	return prevRootCopy
+}
+
 func NewTrie(db Database, Root interface{}) *Trie {
-	return &Trie{cache: NewCache(db), Root: Root, prevRoot: Root}
+	// Make absolute sure the root is copied
+	r := copyRoot(Root)
+	p := copyRoot(Root)
+
+	return &Trie{cache: NewCache(db), Root: r, prevRoot: p}
 }
 
 // Save the cached value to the database.
 func (t *Trie) Sync() {
 	t.cache.Commit()
-	t.prevRoot = t.Root
+	t.prevRoot = copyRoot(t.Root)
 }
 
 func (t *Trie) Undo() {
diff --git a/peer.go b/peer.go
index 0ecd13e60..28ccc324c 100644
--- a/peer.go
+++ b/peer.go
@@ -449,8 +449,10 @@ func (p *Peer) HandleInbound() {
 				if parent != nil {
 					ethutil.Config.Log.Infof("[PEER] Found conical block, returning chain from: %x ", parent.Hash())
 					chain := p.ethereum.BlockChain().GetChainFromHash(parent.Hash(), amountOfBlocks)
-					ethutil.Config.Log.Infof("[PEER] Returning %d blocks: %x ", len(chain), parent.Hash())
-					p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, chain))
+					if len(chain) > 0 {
+						ethutil.Config.Log.Infof("[PEER] Returning %d blocks: %x ", len(chain), parent.Hash())
+						p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, chain))
+					}
 				} else {
 					ethutil.Config.Log.Infof("[PEER] Could not find a similar block")
 					// If no blocks are found we send back a reply with msg not in chain
-- 
GitLab