core: added chain head reset to known block

This commit is contained in:
obscuren 2015-04-20 12:29:02 +02:00
parent 52584596d4
commit 45da3e17e2
4 changed files with 66 additions and 12 deletions

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"time" "time"
@ -50,15 +51,10 @@ func (js *jsre) adminBindings() {
debug.Set("printBlock", js.printBlock) debug.Set("printBlock", js.printBlock)
debug.Set("dumpBlock", js.dumpBlock) debug.Set("dumpBlock", js.dumpBlock)
debug.Set("getBlockRlp", js.getBlockRlp) debug.Set("getBlockRlp", js.getBlockRlp)
debug.Set("setHead", js.setHead)
} }
func (js *jsre) downloadProgress(call otto.FunctionCall) otto.Value { func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
current, max := js.ethereum.Downloader().Stats()
return js.re.ToVal(fmt.Sprintf("%d/%d", current, max))
}
func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
var block *types.Block var block *types.Block
if len(call.ArgumentList) > 0 { if len(call.ArgumentList) > 0 {
if call.Argument(0).IsNumber() { if call.Argument(0).IsNumber() {
@ -68,12 +64,43 @@ func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
hash, _ := call.Argument(0).ToString() hash, _ := call.Argument(0).ToString()
block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash)) block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
} else { } else {
fmt.Println("invalid argument for dump. Either hex string or number") return nil, errors.New("invalid argument for dump. Either hex string or number")
} }
return block, nil
} else {
block = js.ethereum.ChainManager().CurrentBlock()
} }
return nil, errors.New("requires block number or block hash as argument")
}
func (js *jsre) setHead(call otto.FunctionCall) otto.Value {
block, err := js.getBlock(call)
if err != nil {
fmt.Println(err)
return otto.UndefinedValue()
}
if block == nil {
fmt.Println("block not found")
return otto.UndefinedValue()
}
js.ethereum.ChainManager().SetHead(block)
return otto.UndefinedValue()
}
func (js *jsre) downloadProgress(call otto.FunctionCall) otto.Value {
current, max := js.ethereum.Downloader().Stats()
return js.re.ToVal(fmt.Sprintf("%d/%d", current, max))
}
func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
block, err := js.getBlock(call)
if err != nil {
fmt.Println(err)
return otto.UndefinedValue()
}
if block == nil { if block == nil {
fmt.Println("block not found") fmt.Println("block not found")
return otto.UndefinedValue() return otto.UndefinedValue()

View File

@ -109,6 +109,30 @@ func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *Chai
return bc return bc
} }
func (bc *ChainManager) SetHead(block *types.Block) {
bc.mu.Lock()
defer bc.mu.Unlock()
for block := bc.currentBlock; block != nil && block.Hash() != block.Hash(); block = bc.GetBlock(block.Header().ParentHash) {
bc.removeBlock(block)
}
if bc.cache == nil {
bc.cache = NewBlockCache(blockCacheLimit)
}
bc.currentBlock = block
bc.makeCache()
statedb := state.New(block.Root(), bc.stateDb)
bc.txState = state.ManageState(statedb)
bc.transState = statedb.Copy()
bc.setTotalDifficulty(block.Td)
bc.setLastBlock()
bc.insert(block)
bc.setLastBlock()
}
func (self *ChainManager) Td() *big.Int { func (self *ChainManager) Td() *big.Int {
self.mu.RLock() self.mu.RLock()
defer self.mu.RUnlock() defer self.mu.RUnlock()

View File

@ -472,6 +472,8 @@ func (d *Downloader) process() error {
} }
break break
} else if err != nil { } else if err != nil {
// immediatly unregister the false peer but do not disconnect
d.UnregisterPeer(d.activePeer)
// Reset chain completely. This needs much, much improvement. // Reset chain completely. This needs much, much improvement.
// instead: check all blocks leading down to this block false block and remove it // instead: check all blocks leading down to this block false block and remove it
blocks = nil blocks = nil

View File

@ -36,6 +36,7 @@ pm.chainman.InsertChain(blocks)
import ( import (
"fmt" "fmt"
"math"
"math/big" "math/big"
"sync" "sync"
@ -326,7 +327,7 @@ func (pm *ProtocolManager) BroadcastBlock(hash common.Hash, block *types.Block)
} }
// Broadcast block to peer set // Broadcast block to peer set
// XXX due to the current shit state of the network disable the limit // XXX due to the current shit state of the network disable the limit
//peers = peers[:int(math.Sqrt(float64(len(peers))))] peers = peers[:int(math.Sqrt(float64(len(peers))))]
for _, peer := range peers { for _, peer := range peers {
peer.sendNewBlock(block) peer.sendNewBlock(block)
} }