Fixed state problem

This commit is contained in:
obscuren 2014-04-29 12:36:27 +02:00
parent 5516efdfa0
commit 38d6b67b5c
7 changed files with 48 additions and 20 deletions

View File

@ -80,9 +80,6 @@ func CreateBlock(root interface{},
extra string, extra string,
txes []*Transaction) *Block { txes []*Transaction) *Block {
// Copy over the bytes
copiedRoot := ethutil.NewValue(root).Bytes()
block := &Block{ block := &Block{
// Slice of transactions to include in this block // Slice of transactions to include in this block
transactions: txes, transactions: txes,
@ -98,7 +95,7 @@ func CreateBlock(root interface{},
block.SetTransactions(txes) block.SetTransactions(txes)
block.SetUncles([]*Block{}) 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 { for _, tx := range txes {
block.MakeContract(tx) block.MakeContract(tx)

View File

@ -179,7 +179,8 @@ func (bc *BlockChain) ResetTillBlockHash(hash []byte) error {
bc.LastBlockNumber = info.Number 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()) err := ethutil.Config.Db.Delete(lastBlock.Hash())
if err != nil { if err != nil {

View File

@ -158,17 +158,18 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
// Processing a blocks may never happen simultaneously // Processing a blocks may never happen simultaneously
sm.mutex.Lock() sm.mutex.Lock()
defer sm.mutex.Unlock() defer sm.mutex.Unlock()
hash := block.Hash()
if sm.bc.HasBlock(hash) {
fmt.Println("[STATE] We already have this block, ignoring")
return nil
}
// Defer the Undo on the Trie. If the block processing happened // Defer the Undo on the Trie. If the block processing happened
// we don't want to undo but since undo only happens on dirty // we don't want to undo but since undo only happens on dirty
// nodes this won't happen because Commit would have been called // nodes this won't happen because Commit would have been called
// before that. // before that.
defer sm.bc.CurrentBlock.Undo() defer sm.bc.CurrentBlock.Undo()
hash := block.Hash()
if sm.bc.HasBlock(hash) {
fmt.Println("[SM] We already have this block, ignoring")
return nil
}
// Check if we have the parent hash, if it isn't known we discard it // 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 // Reasons might be catching up or simply an invalid block

View File

@ -2,6 +2,7 @@ package ethminer
import ( import (
"bytes" "bytes"
"fmt"
"github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire" "github.com/ethereum/eth-go/ethwire"
@ -61,10 +62,10 @@ func (miner *Miner) listener() {
select { select {
case chanMessage := <-miner.reactChan: case chanMessage := <-miner.reactChan:
if block, ok := chanMessage.Resource.(*ethchain.Block); ok { 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 { if bytes.Compare(miner.ethereum.BlockChain().CurrentBlock.Hash(), block.Hash()) == 0 {
// TODO: Perhaps continue mining to get some uncle rewards // 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 // Filter out which Transactions we have that were not in this block
var newtxs []*ethchain.Transaction var newtxs []*ethchain.Transaction
@ -86,7 +87,7 @@ func (miner *Miner) listener() {
} else { } else {
if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 { 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.uncles = append(miner.uncles, block)
miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State()) miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State())
} }
@ -133,8 +134,9 @@ func (miner *Miner) listener() {
miner.ethereum.StateManager().PrepareDefault(miner.block) miner.ethereum.StateManager().PrepareDefault(miner.block)
err := miner.ethereum.StateManager().ProcessBlock(miner.block, true) err := miner.ethereum.StateManager().ProcessBlock(miner.block, true)
if err != nil { if err != nil {
log.Println("Error result from process block:", err) log.Println(err)
miner.block.State().Reset() miner.txs = []*ethchain.Transaction{} // Move this somewhere neat
miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs)
} else { } else {
/* /*

View File

@ -73,3 +73,13 @@ func BinaryLength(num int) int {
return 1 + BinaryLength(num>>8) 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
}

View File

@ -119,14 +119,29 @@ type Trie struct {
cache *Cache 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 { 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. // Save the cached value to the database.
func (t *Trie) Sync() { func (t *Trie) Sync() {
t.cache.Commit() t.cache.Commit()
t.prevRoot = t.Root t.prevRoot = copyRoot(t.Root)
} }
func (t *Trie) Undo() { func (t *Trie) Undo() {

View File

@ -449,8 +449,10 @@ func (p *Peer) HandleInbound() {
if parent != nil { if parent != nil {
ethutil.Config.Log.Infof("[PEER] Found conical block, returning chain from: %x ", parent.Hash()) ethutil.Config.Log.Infof("[PEER] Found conical block, returning chain from: %x ", parent.Hash())
chain := p.ethereum.BlockChain().GetChainFromHash(parent.Hash(), amountOfBlocks) chain := p.ethereum.BlockChain().GetChainFromHash(parent.Hash(), amountOfBlocks)
if len(chain) > 0 {
ethutil.Config.Log.Infof("[PEER] Returning %d blocks: %x ", len(chain), parent.Hash()) ethutil.Config.Log.Infof("[PEER] Returning %d blocks: %x ", len(chain), parent.Hash())
p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, chain)) p.QueueMessage(ethwire.NewMessage(ethwire.MsgBlockTy, chain))
}
} else { } else {
ethutil.Config.Log.Infof("[PEER] Could not find a similar block") 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 // If no blocks are found we send back a reply with msg not in chain