Browse Source

core: added chain head reset to known block

obscuren 10 năm trước cách đây
mục cha
commit
45da3e17e2
4 tập tin đã thay đổi với 65 bổ sung11 xóa
  1. 37 10
      cmd/geth/admin.go
  2. 24 0
      core/chain_manager.go
  3. 2 0
      eth/downloader/downloader.go
  4. 2 1
      eth/handler.go

+ 37 - 10
cmd/geth/admin.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"errors"
 	"fmt"
 	"os"
 	"time"
@@ -50,15 +51,10 @@ func (js *jsre) adminBindings() {
 	debug.Set("printBlock", js.printBlock)
 	debug.Set("dumpBlock", js.dumpBlock)
 	debug.Set("getBlockRlp", js.getBlockRlp)
+	debug.Set("setHead", js.setHead)
 }
 
-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 {
+func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
 	var block *types.Block
 	if len(call.ArgumentList) > 0 {
 		if call.Argument(0).IsNumber() {
@@ -68,12 +64,43 @@ func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
 			hash, _ := call.Argument(0).ToString()
 			block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
 		} 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 {
 		fmt.Println("block not found")
 		return otto.UndefinedValue()

+ 24 - 0
core/chain_manager.go

@@ -109,6 +109,30 @@ func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *Chai
 	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 {
 	self.mu.RLock()
 	defer self.mu.RUnlock()

+ 2 - 0
eth/downloader/downloader.go

@@ -472,6 +472,8 @@ func (d *Downloader) process() error {
 			}
 			break
 		} 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.
 			// instead: check all blocks leading down to this block false block and remove it
 			blocks = nil

+ 2 - 1
eth/handler.go

@@ -36,6 +36,7 @@ pm.chainman.InsertChain(blocks)
 
 import (
 	"fmt"
+	"math"
 	"math/big"
 	"sync"
 
@@ -326,7 +327,7 @@ func (pm *ProtocolManager) BroadcastBlock(hash common.Hash, block *types.Block)
 	}
 	// Broadcast block to peer set
 	// 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 {
 		peer.sendNewBlock(block)
 	}