github.com/immesys/bw2bc@v1.1.0/core/chain_manager.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package core implements the Ethereum consensus protocol.
    18  package core
    19  
    20  import (
    21  	"errors"
    22  	"fmt"
    23  	"io"
    24  	"math/big"
    25  	"runtime"
    26  	"sync"
    27  	"sync/atomic"
    28  	"time"
    29  
    30  	"github.com/ethereum/go-ethereum/common"
    31  	"github.com/ethereum/go-ethereum/core/state"
    32  	"github.com/ethereum/go-ethereum/core/types"
    33  	"github.com/ethereum/go-ethereum/event"
    34  	"github.com/ethereum/go-ethereum/logger"
    35  	"github.com/ethereum/go-ethereum/logger/glog"
    36  	"github.com/ethereum/go-ethereum/metrics"
    37  	"github.com/ethereum/go-ethereum/pow"
    38  	"github.com/hashicorp/golang-lru"
    39  )
    40  
    41  var (
    42  	chainlogger = logger.NewLogger("CHAIN")
    43  	jsonlogger  = logger.NewJsonLogger()
    44  
    45  	blockInsertTimer = metrics.NewTimer("chain/inserts")
    46  
    47  	ErrNoGenesis = errors.New("Genesis not found in chain")
    48  )
    49  
    50  const (
    51  	blockCacheLimit     = 256
    52  	maxFutureBlocks     = 256
    53  	maxTimeFutureBlocks = 30
    54  	checkpointLimit     = 200
    55  )
    56  
    57  type ChainManager struct {
    58  	//eth          EthManager
    59  	chainDb      common.Database
    60  	processor    types.BlockProcessor
    61  	eventMux     *event.TypeMux
    62  	genesisBlock *types.Block
    63  	// Last known total difficulty
    64  	mu      sync.RWMutex
    65  	chainmu sync.RWMutex
    66  	tsmu    sync.RWMutex
    67  
    68  	checkpoint      int // checkpoint counts towards the new checkpoint
    69  	td              *big.Int
    70  	currentBlock    *types.Block
    71  	lastBlockHash   common.Hash
    72  	currentGasLimit *big.Int
    73  
    74  	cache        *lru.Cache // cache is the LRU caching
    75  	futureBlocks *lru.Cache // future blocks are blocks added for later processing
    76  
    77  	quit    chan struct{}
    78  	running int32 // running must be called automically
    79  	// procInterrupt must be atomically called
    80  	procInterrupt int32 // interrupt signaler for block processing
    81  	wg            sync.WaitGroup
    82  
    83  	pow pow.PoW
    84  }
    85  
    86  func NewChainManager(chainDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) {
    87  	cache, _ := lru.New(blockCacheLimit)
    88  	bc := &ChainManager{
    89  		chainDb:  chainDb,
    90  		eventMux: mux,
    91  		quit:     make(chan struct{}),
    92  		cache:    cache,
    93  		pow:      pow,
    94  	}
    95  
    96  	bc.genesisBlock = bc.GetBlockByNumber(0)
    97  	if bc.genesisBlock == nil {
    98  		reader, err := NewDefaultGenesisReader()
    99  		if err != nil {
   100  			return nil, err
   101  		}
   102  		bc.genesisBlock, err = WriteGenesisBlock(chainDb, reader)
   103  		if err != nil {
   104  			return nil, err
   105  		}
   106  		glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block")
   107  	}
   108  
   109  	if err := bc.setLastState(); err != nil {
   110  		return nil, err
   111  	}
   112  
   113  	// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
   114  	for hash, _ := range BadHashes {
   115  		if block := bc.GetBlock(hash); block != nil {
   116  			glog.V(logger.Error).Infof("Found bad hash. Reorganising chain to state %x\n", block.ParentHash().Bytes()[:4])
   117  			block = bc.GetBlock(block.ParentHash())
   118  			if block == nil {
   119  				glog.Fatal("Unable to complete. Parent block not found. Corrupted DB?")
   120  			}
   121  			bc.SetHead(block)
   122  
   123  			glog.V(logger.Error).Infoln("Chain reorg was successfull. Resuming normal operation")
   124  		}
   125  	}
   126  
   127  	// Take ownership of this particular state
   128  
   129  	bc.futureBlocks, _ = lru.New(maxFutureBlocks)
   130  	bc.makeCache()
   131  
   132  	go bc.update()
   133  
   134  	return bc, nil
   135  }
   136  
   137  func (bc *ChainManager) SetHead(head *types.Block) {
   138  	bc.mu.Lock()
   139  	defer bc.mu.Unlock()
   140  
   141  	for block := bc.currentBlock; block != nil && block.Hash() != head.Hash(); block = bc.GetBlock(block.ParentHash()) {
   142  		bc.removeBlock(block)
   143  	}
   144  
   145  	bc.cache, _ = lru.New(blockCacheLimit)
   146  	bc.currentBlock = head
   147  	bc.makeCache()
   148  
   149  	bc.setTotalDifficulty(head.Td)
   150  	bc.insert(head)
   151  	bc.setLastState()
   152  }
   153  
   154  func (self *ChainManager) Td() *big.Int {
   155  	self.mu.RLock()
   156  	defer self.mu.RUnlock()
   157  
   158  	return new(big.Int).Set(self.td)
   159  }
   160  
   161  func (self *ChainManager) GasLimit() *big.Int {
   162  	self.mu.RLock()
   163  	defer self.mu.RUnlock()
   164  
   165  	return self.currentBlock.GasLimit()
   166  }
   167  
   168  func (self *ChainManager) LastBlockHash() common.Hash {
   169  	self.mu.RLock()
   170  	defer self.mu.RUnlock()
   171  
   172  	return self.lastBlockHash
   173  }
   174  
   175  func (self *ChainManager) CurrentBlock() *types.Block {
   176  	self.mu.RLock()
   177  	defer self.mu.RUnlock()
   178  
   179  	return self.currentBlock
   180  }
   181  
   182  func (self *ChainManager) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) {
   183  	self.mu.RLock()
   184  	defer self.mu.RUnlock()
   185  
   186  	return new(big.Int).Set(self.td), self.currentBlock.Hash(), self.genesisBlock.Hash()
   187  }
   188  
   189  func (self *ChainManager) SetProcessor(proc types.BlockProcessor) {
   190  	self.processor = proc
   191  }
   192  
   193  func (self *ChainManager) State() *state.StateDB {
   194  	return state.New(self.CurrentBlock().Root(), self.chainDb)
   195  }
   196  
   197  func (bc *ChainManager) recover() bool {
   198  	data, _ := bc.chainDb.Get([]byte("checkpoint"))
   199  	if len(data) != 0 {
   200  		block := bc.GetBlock(common.BytesToHash(data))
   201  		if block != nil {
   202  			err := bc.chainDb.Put([]byte("LastBlock"), block.Hash().Bytes())
   203  			if err != nil {
   204  				glog.Fatalln("db write err:", err)
   205  			}
   206  
   207  			bc.currentBlock = block
   208  			bc.lastBlockHash = block.Hash()
   209  			return true
   210  		}
   211  	}
   212  	return false
   213  }
   214  
   215  func (bc *ChainManager) setLastState() error {
   216  	data, _ := bc.chainDb.Get([]byte("LastBlock"))
   217  	if len(data) != 0 {
   218  		block := bc.GetBlock(common.BytesToHash(data))
   219  		if block != nil {
   220  			bc.currentBlock = block
   221  			bc.lastBlockHash = block.Hash()
   222  		} else {
   223  			glog.Infof("LastBlock (%x) not found. Recovering...\n", data)
   224  			if bc.recover() {
   225  				glog.Infof("Recover successful")
   226  			} else {
   227  				glog.Fatalf("Recover failed. Please report")
   228  			}
   229  		}
   230  	} else {
   231  		bc.Reset()
   232  	}
   233  	bc.td = bc.currentBlock.Td
   234  	bc.currentGasLimit = CalcGasLimit(bc.currentBlock)
   235  
   236  	if glog.V(logger.Info) {
   237  		glog.Infof("Last block (#%v) %x TD=%v\n", bc.currentBlock.Number(), bc.currentBlock.Hash(), bc.td)
   238  	}
   239  
   240  	return nil
   241  }
   242  
   243  func (bc *ChainManager) makeCache() {
   244  	bc.cache, _ = lru.New(blockCacheLimit)
   245  	// load in last `blockCacheLimit` - 1 blocks. Last block is the current.
   246  	bc.cache.Add(bc.genesisBlock.Hash(), bc.genesisBlock)
   247  	for _, block := range bc.GetBlocksFromHash(bc.currentBlock.Hash(), blockCacheLimit) {
   248  		bc.cache.Add(block.Hash(), block)
   249  	}
   250  }
   251  
   252  func (bc *ChainManager) Reset() {
   253  	bc.mu.Lock()
   254  	defer bc.mu.Unlock()
   255  
   256  	for block := bc.currentBlock; block != nil; block = bc.GetBlock(block.ParentHash()) {
   257  		bc.removeBlock(block)
   258  	}
   259  
   260  	bc.cache, _ = lru.New(blockCacheLimit)
   261  
   262  	// Prepare the genesis block
   263  	err := WriteBlock(bc.chainDb, bc.genesisBlock)
   264  	if err != nil {
   265  		glog.Fatalln("db err:", err)
   266  	}
   267  
   268  	bc.insert(bc.genesisBlock)
   269  	bc.currentBlock = bc.genesisBlock
   270  	bc.makeCache()
   271  
   272  	bc.setTotalDifficulty(common.Big("0"))
   273  }
   274  
   275  func (bc *ChainManager) removeBlock(block *types.Block) {
   276  	bc.chainDb.Delete(append(blockHashPre, block.Hash().Bytes()...))
   277  }
   278  
   279  func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
   280  	bc.mu.Lock()
   281  	defer bc.mu.Unlock()
   282  
   283  	for block := bc.currentBlock; block != nil; block = bc.GetBlock(block.ParentHash()) {
   284  		bc.removeBlock(block)
   285  	}
   286  
   287  	// Prepare the genesis block
   288  	gb.Td = gb.Difficulty()
   289  	bc.genesisBlock = gb
   290  
   291  	err := WriteBlock(bc.chainDb, bc.genesisBlock)
   292  	if err != nil {
   293  		glog.Fatalln("db err:", err)
   294  	}
   295  
   296  	bc.insert(bc.genesisBlock)
   297  	bc.currentBlock = bc.genesisBlock
   298  	bc.makeCache()
   299  	bc.td = gb.Difficulty()
   300  }
   301  
   302  // Export writes the active chain to the given writer.
   303  func (self *ChainManager) Export(w io.Writer) error {
   304  	if err := self.ExportN(w, uint64(0), self.currentBlock.NumberU64()); err != nil {
   305  		return err
   306  	}
   307  	return nil
   308  }
   309  
   310  // ExportN writes a subset of the active chain to the given writer.
   311  func (self *ChainManager) ExportN(w io.Writer, first uint64, last uint64) error {
   312  	self.mu.RLock()
   313  	defer self.mu.RUnlock()
   314  
   315  	if first > last {
   316  		return fmt.Errorf("export failed: first (%d) is greater than last (%d)", first, last)
   317  	}
   318  
   319  	glog.V(logger.Info).Infof("exporting %d blocks...\n", last-first+1)
   320  
   321  	for nr := first; nr <= last; nr++ {
   322  		block := self.GetBlockByNumber(nr)
   323  		if block == nil {
   324  			return fmt.Errorf("export failed on #%d: not found", nr)
   325  		}
   326  
   327  		if err := block.EncodeRLP(w); err != nil {
   328  			return err
   329  		}
   330  	}
   331  
   332  	return nil
   333  }
   334  
   335  // insert injects a block into the current chain block chain. Note, this function
   336  // assumes that the `mu` mutex is held!
   337  func (bc *ChainManager) insert(block *types.Block) {
   338  	err := WriteHead(bc.chainDb, block)
   339  	if err != nil {
   340  		glog.Fatal("db write fail:", err)
   341  	}
   342  
   343  	bc.checkpoint++
   344  	if bc.checkpoint > checkpointLimit {
   345  		err = bc.chainDb.Put([]byte("checkpoint"), block.Hash().Bytes())
   346  		if err != nil {
   347  			glog.Fatal("db write fail:", err)
   348  		}
   349  
   350  		bc.checkpoint = 0
   351  	}
   352  
   353  	bc.currentBlock = block
   354  	bc.lastBlockHash = block.Hash()
   355  }
   356  
   357  // Accessors
   358  func (bc *ChainManager) Genesis() *types.Block {
   359  	return bc.genesisBlock
   360  }
   361  
   362  // Block fetching methods
   363  func (bc *ChainManager) HasBlock(hash common.Hash) bool {
   364  	if bc.cache.Contains(hash) {
   365  		return true
   366  	}
   367  
   368  	data, _ := bc.chainDb.Get(append(blockHashPre, hash[:]...))
   369  	return len(data) != 0
   370  }
   371  
   372  func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) (chain []common.Hash) {
   373  	block := self.GetBlock(hash)
   374  	if block == nil {
   375  		return
   376  	}
   377  	// XXX Could be optimised by using a different database which only holds hashes (i.e., linked list)
   378  	for i := uint64(0); i < max; i++ {
   379  		block = self.GetBlock(block.ParentHash())
   380  		if block == nil {
   381  			break
   382  		}
   383  
   384  		chain = append(chain, block.Hash())
   385  		if block.Number().Cmp(common.Big0) <= 0 {
   386  			break
   387  		}
   388  	}
   389  
   390  	return
   391  }
   392  
   393  func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
   394  	if block, ok := self.cache.Get(hash); ok {
   395  		return block.(*types.Block)
   396  	}
   397  
   398  	block := GetBlockByHash(self.chainDb, hash)
   399  	if block == nil {
   400  		return nil
   401  	}
   402  
   403  	// Add the block to the cache
   404  	self.cache.Add(hash, (*types.Block)(block))
   405  
   406  	return (*types.Block)(block)
   407  }
   408  
   409  func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
   410  	self.mu.RLock()
   411  	defer self.mu.RUnlock()
   412  
   413  	return self.getBlockByNumber(num)
   414  
   415  }
   416  
   417  // GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors.
   418  func (self *ChainManager) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) {
   419  	for i := 0; i < n; i++ {
   420  		block := self.GetBlock(hash)
   421  		if block == nil {
   422  			break
   423  		}
   424  		blocks = append(blocks, block)
   425  		hash = block.ParentHash()
   426  	}
   427  	return
   428  }
   429  
   430  // non blocking version
   431  func (self *ChainManager) getBlockByNumber(num uint64) *types.Block {
   432  	return GetBlockByNumber(self.chainDb, num)
   433  }
   434  
   435  func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncles []*types.Header) {
   436  	for i := 0; block != nil && i < length; i++ {
   437  		uncles = append(uncles, block.Uncles()...)
   438  		block = self.GetBlock(block.ParentHash())
   439  	}
   440  
   441  	return
   442  }
   443  
   444  // setTotalDifficulty updates the TD of the chain manager. Note, this function
   445  // assumes that the `mu` mutex is held!
   446  func (bc *ChainManager) setTotalDifficulty(td *big.Int) {
   447  	bc.td = new(big.Int).Set(td)
   448  }
   449  
   450  func (bc *ChainManager) Stop() {
   451  	if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) {
   452  		return
   453  	}
   454  	close(bc.quit)
   455  	atomic.StoreInt32(&bc.procInterrupt, 1)
   456  
   457  	bc.wg.Wait()
   458  
   459  	glog.V(logger.Info).Infoln("Chain manager stopped")
   460  }
   461  
   462  type queueEvent struct {
   463  	queue          []interface{}
   464  	canonicalCount int
   465  	sideCount      int
   466  	splitCount     int
   467  }
   468  
   469  func (self *ChainManager) procFutureBlocks() {
   470  	blocks := make([]*types.Block, self.futureBlocks.Len())
   471  	for i, hash := range self.futureBlocks.Keys() {
   472  		block, _ := self.futureBlocks.Get(hash)
   473  		blocks[i] = block.(*types.Block)
   474  	}
   475  	if len(blocks) > 0 {
   476  		types.BlockBy(types.Number).Sort(blocks)
   477  		self.InsertChain(blocks)
   478  	}
   479  }
   480  
   481  type writeStatus byte
   482  
   483  const (
   484  	NonStatTy writeStatus = iota
   485  	CanonStatTy
   486  	SplitStatTy
   487  	SideStatTy
   488  )
   489  
   490  // WriteBlock writes the block to the chain (or pending queue)
   491  func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status writeStatus, err error) {
   492  	self.wg.Add(1)
   493  	defer self.wg.Done()
   494  
   495  	cblock := self.currentBlock
   496  	// Compare the TD of the last known block in the canonical chain to make sure it's greater.
   497  	// At this point it's possible that a different chain (fork) becomes the new canonical chain.
   498  	if block.Td.Cmp(self.Td()) > 0 {
   499  		// chain fork
   500  		if block.ParentHash() != cblock.Hash() {
   501  			// during split we merge two different chains and create the new canonical chain
   502  			err := self.merge(cblock, block)
   503  			if err != nil {
   504  				return NonStatTy, err
   505  			}
   506  
   507  			status = SplitStatTy
   508  		}
   509  
   510  		self.mu.Lock()
   511  		self.setTotalDifficulty(block.Td)
   512  		self.insert(block)
   513  		self.mu.Unlock()
   514  
   515  		status = CanonStatTy
   516  	} else {
   517  		status = SideStatTy
   518  	}
   519  
   520  	err = WriteBlock(self.chainDb, block)
   521  	if err != nil {
   522  		glog.Fatalln("db err:", err)
   523  	}
   524  	// Delete from future blocks
   525  	self.futureBlocks.Remove(block.Hash())
   526  
   527  	return
   528  }
   529  
   530  // InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned
   531  // it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go).
   532  func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
   533  	self.wg.Add(1)
   534  	defer self.wg.Done()
   535  
   536  	self.chainmu.Lock()
   537  	defer self.chainmu.Unlock()
   538  
   539  	// A queued approach to delivering events. This is generally
   540  	// faster than direct delivery and requires much less mutex
   541  	// acquiring.
   542  	var (
   543  		queue      = make([]interface{}, len(chain))
   544  		queueEvent = queueEvent{queue: queue}
   545  		stats      struct{ queued, processed, ignored int }
   546  		tstart     = time.Now()
   547  
   548  		nonceDone    = make(chan nonceResult, len(chain))
   549  		nonceQuit    = make(chan struct{})
   550  		nonceChecked = make([]bool, len(chain))
   551  	)
   552  
   553  	// Start the parallel nonce verifier.
   554  	go verifyNonces(self.pow, chain, nonceQuit, nonceDone)
   555  	defer close(nonceQuit)
   556  
   557  	txcount := 0
   558  	for i, block := range chain {
   559  		if atomic.LoadInt32(&self.procInterrupt) == 1 {
   560  			glog.V(logger.Debug).Infoln("Premature abort during chain processing")
   561  			break
   562  		}
   563  
   564  		bstart := time.Now()
   565  		// Wait for block i's nonce to be verified before processing
   566  		// its state transition.
   567  		for !nonceChecked[i] {
   568  			r := <-nonceDone
   569  			nonceChecked[r.i] = true
   570  			if !r.valid {
   571  				block := chain[r.i]
   572  				return r.i, &BlockNonceErr{Hash: block.Hash(), Number: block.Number(), Nonce: block.Nonce()}
   573  			}
   574  		}
   575  
   576  		if BadHashes[block.Hash()] {
   577  			err := fmt.Errorf("Found known bad hash in chain %x", block.Hash())
   578  			blockErr(block, err)
   579  			return i, err
   580  		}
   581  
   582  		// Setting block.Td regardless of error (known for example) prevents errors down the line
   583  		// in the protocol handler
   584  		block.Td = new(big.Int).Set(CalcTD(block, self.GetBlock(block.ParentHash())))
   585  
   586  		// Call in to the block processor and check for errors. It's likely that if one block fails
   587  		// all others will fail too (unless a known block is returned).
   588  		logs, receipts, err := self.processor.Process(block)
   589  		if err != nil {
   590  			if IsKnownBlockErr(err) {
   591  				stats.ignored++
   592  				continue
   593  			}
   594  
   595  			if err == BlockFutureErr {
   596  				// Allow up to MaxFuture second in the future blocks. If this limit
   597  				// is exceeded the chain is discarded and processed at a later time
   598  				// if given.
   599  				max := big.NewInt(time.Now().Unix() + maxTimeFutureBlocks)
   600  				if block.Time().Cmp(max) == 1 {
   601  					return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max)
   602  				}
   603  
   604  				self.futureBlocks.Add(block.Hash(), block)
   605  				stats.queued++
   606  				continue
   607  			}
   608  
   609  			if IsParentErr(err) && self.futureBlocks.Contains(block.ParentHash()) {
   610  				self.futureBlocks.Add(block.Hash(), block)
   611  				stats.queued++
   612  				continue
   613  			}
   614  
   615  			blockErr(block, err)
   616  
   617  			go ReportBlock(block, err)
   618  
   619  			return i, err
   620  		}
   621  
   622  		txcount += len(block.Transactions())
   623  
   624  		// write the block to the chain and get the status
   625  		status, err := self.WriteBlock(block, true)
   626  		if err != nil {
   627  			return i, err
   628  		}
   629  		switch status {
   630  		case CanonStatTy:
   631  			if glog.V(logger.Debug) {
   632  				glog.Infof("[%v] inserted block #%d (%d TXs %v G %d UNCs) (%x...). Took %v\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), block.GasUsed(), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart))
   633  			}
   634  			queue[i] = ChainEvent{block, block.Hash(), logs}
   635  			queueEvent.canonicalCount++
   636  
   637  			// This puts transactions in a extra db for rpc
   638  			PutTransactions(self.chainDb, block, block.Transactions())
   639  			// store the receipts
   640  			PutReceipts(self.chainDb, receipts)
   641  		case SideStatTy:
   642  			if glog.V(logger.Detail) {
   643  				glog.Infof("inserted forked block #%d (TD=%v) (%d TXs %d UNCs) (%x...). Took %v\n", block.Number(), block.Difficulty(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart))
   644  			}
   645  			queue[i] = ChainSideEvent{block, logs}
   646  			queueEvent.sideCount++
   647  		case SplitStatTy:
   648  			queue[i] = ChainSplitEvent{block, logs}
   649  			queueEvent.splitCount++
   650  		}
   651  		if err := PutBlockReceipts(self.chainDb, block, receipts); err != nil {
   652  			glog.V(logger.Warn).Infoln("error writing block receipts:", err)
   653  		}
   654  
   655  		stats.processed++
   656  	}
   657  
   658  	if (stats.queued > 0 || stats.processed > 0 || stats.ignored > 0) && bool(glog.V(logger.Info)) {
   659  		tend := time.Since(tstart)
   660  		start, end := chain[0], chain[len(chain)-1]
   661  		glog.Infof("imported %d block(s) (%d queued %d ignored) including %d txs in %v. #%v [%x / %x]\n", stats.processed, stats.queued, stats.ignored, txcount, tend, end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4])
   662  	}
   663  
   664  	go self.eventMux.Post(queueEvent)
   665  
   666  	return 0, nil
   667  }
   668  
   669  // diff takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
   670  // to be part of the new canonical chain.
   671  func (self *ChainManager) diff(oldBlock, newBlock *types.Block) (types.Blocks, error) {
   672  	var (
   673  		newChain    types.Blocks
   674  		commonBlock *types.Block
   675  		oldStart    = oldBlock
   676  		newStart    = newBlock
   677  	)
   678  
   679  	// first reduce whoever is higher bound
   680  	if oldBlock.NumberU64() > newBlock.NumberU64() {
   681  		// reduce old chain
   682  		for oldBlock = oldBlock; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = self.GetBlock(oldBlock.ParentHash()) {
   683  		}
   684  	} else {
   685  		// reduce new chain and append new chain blocks for inserting later on
   686  		for newBlock = newBlock; newBlock != nil && newBlock.NumberU64() != oldBlock.NumberU64(); newBlock = self.GetBlock(newBlock.ParentHash()) {
   687  			newChain = append(newChain, newBlock)
   688  		}
   689  	}
   690  	if oldBlock == nil {
   691  		return nil, fmt.Errorf("Invalid old chain")
   692  	}
   693  	if newBlock == nil {
   694  		return nil, fmt.Errorf("Invalid new chain")
   695  	}
   696  
   697  	numSplit := newBlock.Number()
   698  	for {
   699  		if oldBlock.Hash() == newBlock.Hash() {
   700  			commonBlock = oldBlock
   701  			break
   702  		}
   703  		newChain = append(newChain, newBlock)
   704  
   705  		oldBlock, newBlock = self.GetBlock(oldBlock.ParentHash()), self.GetBlock(newBlock.ParentHash())
   706  		if oldBlock == nil {
   707  			return nil, fmt.Errorf("Invalid old chain")
   708  		}
   709  		if newBlock == nil {
   710  			return nil, fmt.Errorf("Invalid new chain")
   711  		}
   712  	}
   713  
   714  	if glog.V(logger.Debug) {
   715  		commonHash := commonBlock.Hash()
   716  		glog.Infof("Chain split detected @ %x. Reorganising chain from #%v %x to %x", commonHash[:4], numSplit, oldStart.Hash().Bytes()[:4], newStart.Hash().Bytes()[:4])
   717  	}
   718  
   719  	return newChain, nil
   720  }
   721  
   722  // merge merges two different chain to the new canonical chain
   723  func (self *ChainManager) merge(oldBlock, newBlock *types.Block) error {
   724  	newChain, err := self.diff(oldBlock, newBlock)
   725  	if err != nil {
   726  		return fmt.Errorf("chain reorg failed: %v", err)
   727  	}
   728  
   729  	// insert blocks. Order does not matter. Last block will be written in ImportChain itself which creates the new head properly
   730  	self.mu.Lock()
   731  	for _, block := range newChain {
   732  		// insert the block in the canonical way, re-writing history
   733  		self.insert(block)
   734  		// write canonical receipts and transactions
   735  		PutTransactions(self.chainDb, block, block.Transactions())
   736  		PutReceipts(self.chainDb, GetBlockReceipts(self.chainDb, block.Hash()))
   737  
   738  	}
   739  	self.mu.Unlock()
   740  
   741  	return nil
   742  }
   743  
   744  func (self *ChainManager) update() {
   745  	events := self.eventMux.Subscribe(queueEvent{})
   746  	futureTimer := time.Tick(5 * time.Second)
   747  out:
   748  	for {
   749  		select {
   750  		case ev := <-events.Chan():
   751  			switch ev := ev.(type) {
   752  			case queueEvent:
   753  				for _, event := range ev.queue {
   754  					switch event := event.(type) {
   755  					case ChainEvent:
   756  						// We need some control over the mining operation. Acquiring locks and waiting for the miner to create new block takes too long
   757  						// and in most cases isn't even necessary.
   758  						if self.lastBlockHash == event.Hash {
   759  							self.currentGasLimit = CalcGasLimit(event.Block)
   760  							self.eventMux.Post(ChainHeadEvent{event.Block})
   761  						}
   762  					}
   763  
   764  					self.eventMux.Post(event)
   765  				}
   766  			}
   767  		case <-futureTimer:
   768  			self.procFutureBlocks()
   769  		case <-self.quit:
   770  			break out
   771  		}
   772  	}
   773  }
   774  
   775  func blockErr(block *types.Block, err error) {
   776  	h := block.Header()
   777  	glog.V(logger.Error).Infof("Bad block #%v (%x)\n", h.Number, h.Hash().Bytes())
   778  	glog.V(logger.Error).Infoln(err)
   779  	glog.V(logger.Debug).Infoln(verifyNonces)
   780  }
   781  
   782  type nonceResult struct {
   783  	i     int
   784  	valid bool
   785  }
   786  
   787  // block verifies nonces of the given blocks in parallel and returns
   788  // an error if one of the blocks nonce verifications failed.
   789  func verifyNonces(pow pow.PoW, blocks []*types.Block, quit <-chan struct{}, done chan<- nonceResult) {
   790  	// Spawn a few workers. They listen for blocks on the in channel
   791  	// and send results on done. The workers will exit in the
   792  	// background when in is closed.
   793  	var (
   794  		in       = make(chan int)
   795  		nworkers = runtime.GOMAXPROCS(0)
   796  	)
   797  	defer close(in)
   798  	if len(blocks) < nworkers {
   799  		nworkers = len(blocks)
   800  	}
   801  	for i := 0; i < nworkers; i++ {
   802  		go func() {
   803  			for i := range in {
   804  				done <- nonceResult{i: i, valid: pow.Verify(blocks[i])}
   805  			}
   806  		}()
   807  	}
   808  	// Feed block indices to the workers.
   809  	for i := range blocks {
   810  		select {
   811  		case in <- i:
   812  			continue
   813  		case <-quit:
   814  			return
   815  		}
   816  	}
   817  }