github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/blockchain.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:34</date>
    10  //</624450077523447808>
    11  
    12  
    13  //软件包核心实现以太坊共识协议。
    14  package core
    15  
    16  import (
    17  	"errors"
    18  	"fmt"
    19  	"io"
    20  	"math/big"
    21  	mrand "math/rand"
    22  	"sync"
    23  	"sync/atomic"
    24  	"time"
    25  
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/common/mclock"
    28  	"github.com/ethereum/go-ethereum/common/prque"
    29  	"github.com/ethereum/go-ethereum/consensus"
    30  	"github.com/ethereum/go-ethereum/core/rawdb"
    31  	"github.com/ethereum/go-ethereum/core/state"
    32  	"github.com/ethereum/go-ethereum/core/types"
    33  	"github.com/ethereum/go-ethereum/core/vm"
    34  	"github.com/ethereum/go-ethereum/crypto"
    35  	"github.com/ethereum/go-ethereum/ethdb"
    36  	"github.com/ethereum/go-ethereum/event"
    37  	"github.com/ethereum/go-ethereum/log"
    38  	"github.com/ethereum/go-ethereum/metrics"
    39  	"github.com/ethereum/go-ethereum/params"
    40  	"github.com/ethereum/go-ethereum/rlp"
    41  	"github.com/ethereum/go-ethereum/trie"
    42  	"github.com/hashicorp/golang-lru"
    43  )
    44  
    45  var (
    46  	blockInsertTimer     = metrics.NewRegisteredTimer("chain/inserts", nil)
    47  	blockValidationTimer = metrics.NewRegisteredTimer("chain/validation", nil)
    48  	blockExecutionTimer  = metrics.NewRegisteredTimer("chain/execution", nil)
    49  	blockWriteTimer      = metrics.NewRegisteredTimer("chain/write", nil)
    50  
    51  	ErrNoGenesis = errors.New("Genesis not found in chain")
    52  )
    53  
    54  const (
    55  	bodyCacheLimit      = 256
    56  	blockCacheLimit     = 256
    57  	receiptsCacheLimit  = 32
    58  	maxFutureBlocks     = 256
    59  	maxTimeFutureBlocks = 30
    60  	badBlockLimit       = 10
    61  	triesInMemory       = 128
    62  
    63  //blockchainversion确保不兼容的数据库强制从头开始重新同步。
    64  	BlockChainVersion uint64 = 3
    65  )
    66  
    67  //cacheconfig包含trie缓存/修剪的配置值
    68  //它位于区块链中。
    69  type CacheConfig struct {
    70  Disabled       bool          //是否禁用trie写缓存(存档节点)
    71  TrieCleanLimit int           //用于在内存中缓存trie节点的内存允许量(MB)
    72  TrieDirtyLimit int           //开始将脏的trie节点刷新到磁盘的内存限制(MB)
    73  TrieTimeLimit  time.Duration //刷新内存中当前磁盘的时间限制
    74  }
    75  
    76  //区块链表示给定数据库的标准链,其中包含一个Genesis
    77  //块。区块链管理链导入、恢复、链重组。
    78  //
    79  //将块导入到块链中是根据规则集进行的
    80  //由两阶段验证程序定义。块的处理是使用
    81  //处理所包含事务的处理器。国家的确认
    82  //在验证器的第二部分完成。失败导致中止
    83  //进口。
    84  //
    85  //区块链也有助于从包含的**任何**链返回区块。
    86  //以及表示规范链的块。它是
    87  //需要注意的是,getBlock可以返回任何块,不需要
    88  //包含在规范中,其中as getblockbynumber始终表示
    89  //规范链。
    90  type BlockChain struct {
    91  chainConfig *params.ChainConfig //链和网络配置
    92  cacheConfig *CacheConfig        //用于修剪的高速缓存配置
    93  
    94  db     ethdb.Database //用于存储最终内容的低级持久数据库
    95  triegc *prque.Prque   //优先级队列映射块号以尝试GC
    96  gcproc time.Duration  //为trie转储累积规范块处理
    97  
    98  	hc            *HeaderChain
    99  	rmLogsFeed    event.Feed
   100  	chainFeed     event.Feed
   101  	chainSideFeed event.Feed
   102  	chainHeadFeed event.Feed
   103  	logsFeed      event.Feed
   104  	scope         event.SubscriptionScope
   105  	genesisBlock  *types.Block
   106  
   107  chainmu sync.RWMutex //区块链插入锁
   108  procmu  sync.RWMutex //块处理器锁
   109  
   110  checkpoint       int          //检查站向新检查站计数
   111  currentBlock     atomic.Value //当前区块链头
   112  currentFastBlock atomic.Value //快速同步链的当前磁头(可能在区块链上方!)
   113  
   114  stateCache    state.Database //要在导入之间重用的状态数据库(包含状态缓存)
   115  bodyCache     *lru.Cache     //缓存最新的块体
   116  bodyRLPCache  *lru.Cache     //以rlp编码格式缓存最新的块体
   117  receiptsCache *lru.Cache     //缓存每个块最近的收据
   118  blockCache    *lru.Cache     //缓存最近的整个块
   119  futureBlocks  *lru.Cache     //未来的块是为以后的处理添加的块
   120  
   121  quit    chan struct{} //区块链退出渠道
   122  running int32         //运行必须以原子方式调用
   123  //
   124  procInterrupt int32          //
   125  wg            sync.WaitGroup //
   126  
   127  	engine    consensus.Engine
   128  processor Processor //
   129  validator Validator //
   130  	vmConfig  vm.Config
   131  
   132  badBlocks      *lru.Cache              //坏块高速缓存
   133  shouldPreserve func(*types.Block) bool //用于确定是否应保留给定块的函数。
   134  }
   135  
   136  //newblockchain使用信息返回完全初始化的块链
   137  //在数据库中可用。它初始化默认的以太坊验证器并
   138  //处理器。
   139  func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) {
   140  	if cacheConfig == nil {
   141  		cacheConfig = &CacheConfig{
   142  			TrieCleanLimit: 256,
   143  			TrieDirtyLimit: 256,
   144  			TrieTimeLimit:  5 * time.Minute,
   145  		}
   146  	}
   147  	bodyCache, _ := lru.New(bodyCacheLimit)
   148  	bodyRLPCache, _ := lru.New(bodyCacheLimit)
   149  	receiptsCache, _ := lru.New(receiptsCacheLimit)
   150  	blockCache, _ := lru.New(blockCacheLimit)
   151  	futureBlocks, _ := lru.New(maxFutureBlocks)
   152  	badBlocks, _ := lru.New(badBlockLimit)
   153  
   154  	bc := &BlockChain{
   155  		chainConfig:    chainConfig,
   156  		cacheConfig:    cacheConfig,
   157  		db:             db,
   158  		triegc:         prque.New(nil),
   159  		stateCache:     state.NewDatabaseWithCache(db, cacheConfig.TrieCleanLimit),
   160  		quit:           make(chan struct{}),
   161  		shouldPreserve: shouldPreserve,
   162  		bodyCache:      bodyCache,
   163  		bodyRLPCache:   bodyRLPCache,
   164  		receiptsCache:  receiptsCache,
   165  		blockCache:     blockCache,
   166  		futureBlocks:   futureBlocks,
   167  		engine:         engine,
   168  		vmConfig:       vmConfig,
   169  		badBlocks:      badBlocks,
   170  	}
   171  	bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
   172  	bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
   173  
   174  	var err error
   175  	bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.getProcInterrupt)
   176  	if err != nil {
   177  		return nil, err
   178  	}
   179  	bc.genesisBlock = bc.GetBlockByNumber(0)
   180  	if bc.genesisBlock == nil {
   181  		return nil, ErrNoGenesis
   182  	}
   183  	if err := bc.loadLastState(); err != nil {
   184  		return nil, err
   185  	}
   186  //检查块哈希的当前状态,确保链中没有任何坏块
   187  	for hash := range BadHashes {
   188  		if header := bc.GetHeaderByHash(hash); header != nil {
   189  //获取与有问题的头的编号相对应的规范块
   190  			headerByNumber := bc.GetHeaderByNumber(header.Number.Uint64())
   191  //确保headerByNumber(如果存在)位于当前的规范链中。
   192  			if headerByNumber != nil && headerByNumber.Hash() == header.Hash() {
   193  				log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash)
   194  				bc.SetHead(header.Number.Uint64() - 1)
   195  				log.Error("Chain rewind was successful, resuming normal operation")
   196  			}
   197  		}
   198  	}
   199  //取得这个国家的所有权
   200  	go bc.update()
   201  	return bc, nil
   202  }
   203  
   204  func (bc *BlockChain) getProcInterrupt() bool {
   205  	return atomic.LoadInt32(&bc.procInterrupt) == 1
   206  }
   207  
   208  //getvmconfig返回块链vm config。
   209  func (bc *BlockChain) GetVMConfig() *vm.Config {
   210  	return &bc.vmConfig
   211  }
   212  
   213  //loadLastState从数据库加载最后一个已知的链状态。这种方法
   214  //假定保持链管理器互斥锁。
   215  func (bc *BlockChain) loadLastState() error {
   216  //恢复上一个已知的头块
   217  	head := rawdb.ReadHeadBlockHash(bc.db)
   218  	if head == (common.Hash{}) {
   219  //数据库已损坏或为空,从头开始初始化
   220  		log.Warn("Empty database, resetting chain")
   221  		return bc.Reset()
   222  	}
   223  //确保整个头块可用
   224  	currentBlock := bc.GetBlockByHash(head)
   225  	if currentBlock == nil {
   226  //数据库已损坏或为空,从头开始初始化
   227  		log.Warn("Head block missing, resetting chain", "hash", head)
   228  		return bc.Reset()
   229  	}
   230  //确保与块关联的状态可用
   231  	if _, err := state.New(currentBlock.Root(), bc.stateCache); err != nil {
   232  //没有关联状态的挂起块,从头开始初始化
   233  		log.Warn("Head state missing, repairing chain", "number", currentBlock.Number(), "hash", currentBlock.Hash())
   234  		if err := bc.repair(&currentBlock); err != nil {
   235  			return err
   236  		}
   237  	}
   238  //一切似乎都很好,设为头挡
   239  	bc.currentBlock.Store(currentBlock)
   240  
   241  //恢复上一个已知的头段
   242  	currentHeader := currentBlock.Header()
   243  	if head := rawdb.ReadHeadHeaderHash(bc.db); head != (common.Hash{}) {
   244  		if header := bc.GetHeaderByHash(head); header != nil {
   245  			currentHeader = header
   246  		}
   247  	}
   248  	bc.hc.SetCurrentHeader(currentHeader)
   249  
   250  //恢复上一个已知的头快速块
   251  	bc.currentFastBlock.Store(currentBlock)
   252  	if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) {
   253  		if block := bc.GetBlockByHash(head); block != nil {
   254  			bc.currentFastBlock.Store(block)
   255  		}
   256  	}
   257  
   258  //为用户发出状态日志
   259  	currentFastBlock := bc.CurrentFastBlock()
   260  
   261  	headerTd := bc.GetTd(currentHeader.Hash(), currentHeader.Number.Uint64())
   262  	blockTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
   263  	fastTd := bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64())
   264  
   265  	log.Info("Loaded most recent local header", "number", currentHeader.Number, "hash", currentHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(currentHeader.Time.Int64(), 0)))
   266  	log.Info("Loaded most recent local full block", "number", currentBlock.Number(), "hash", currentBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(currentBlock.Time().Int64(), 0)))
   267  	log.Info("Loaded most recent local fast block", "number", currentFastBlock.Number(), "hash", currentFastBlock.Hash(), "td", fastTd, "age", common.PrettyAge(time.Unix(currentFastBlock.Time().Int64(), 0)))
   268  
   269  	return nil
   270  }
   271  
   272  //sethead将本地链重绕到新的head。在头的情况下,一切
   273  //上面的新头部将被删除和新的一套。如果是积木
   274  //但是,如果块体丢失(非存档),头部可能会被进一步重绕
   275  //快速同步后的节点)。
   276  func (bc *BlockChain) SetHead(head uint64) error {
   277  	log.Warn("Rewinding blockchain", "target", head)
   278  
   279  	bc.chainmu.Lock()
   280  	defer bc.chainmu.Unlock()
   281  
   282  //倒带标题链,删除所有块体,直到
   283  	delFn := func(db rawdb.DatabaseDeleter, hash common.Hash, num uint64) {
   284  		rawdb.DeleteBody(db, hash, num)
   285  	}
   286  	bc.hc.SetHead(head, delFn)
   287  	currentHeader := bc.hc.CurrentHeader()
   288  
   289  //从缓存中清除所有过时的内容
   290  	bc.bodyCache.Purge()
   291  	bc.bodyRLPCache.Purge()
   292  	bc.receiptsCache.Purge()
   293  	bc.blockCache.Purge()
   294  	bc.futureBlocks.Purge()
   295  
   296  //倒带区块链,确保不会以无状态头区块结束。
   297  	if currentBlock := bc.CurrentBlock(); currentBlock != nil && currentHeader.Number.Uint64() < currentBlock.NumberU64() {
   298  		bc.currentBlock.Store(bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64()))
   299  	}
   300  	if currentBlock := bc.CurrentBlock(); currentBlock != nil {
   301  		if _, err := state.New(currentBlock.Root(), bc.stateCache); err != nil {
   302  //重绕状态丢失,回滚到轴之前,重置为Genesis
   303  			bc.currentBlock.Store(bc.genesisBlock)
   304  		}
   305  	}
   306  //以简单的方式将快速块倒回目标头
   307  	if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && currentHeader.Number.Uint64() < currentFastBlock.NumberU64() {
   308  		bc.currentFastBlock.Store(bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64()))
   309  	}
   310  //如果任一块达到零,则重置为“创世”状态。
   311  	if currentBlock := bc.CurrentBlock(); currentBlock == nil {
   312  		bc.currentBlock.Store(bc.genesisBlock)
   313  	}
   314  	if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock == nil {
   315  		bc.currentFastBlock.Store(bc.genesisBlock)
   316  	}
   317  	currentBlock := bc.CurrentBlock()
   318  	currentFastBlock := bc.CurrentFastBlock()
   319  
   320  	rawdb.WriteHeadBlockHash(bc.db, currentBlock.Hash())
   321  	rawdb.WriteHeadFastBlockHash(bc.db, currentFastBlock.Hash())
   322  
   323  	return bc.loadLastState()
   324  }
   325  
   326  //fastsynccommithead将当前头块设置为哈希定义的头块
   327  //与之前的链内容无关。
   328  func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
   329  //确保块及其状态trie都存在
   330  	block := bc.GetBlockByHash(hash)
   331  	if block == nil {
   332  		return fmt.Errorf("non existent block [%x…]", hash[:4])
   333  	}
   334  	if _, err := trie.NewSecure(block.Root(), bc.stateCache.TrieDB(), 0); err != nil {
   335  		return err
   336  	}
   337  //如果全部签出,手动设置头块
   338  	bc.chainmu.Lock()
   339  	bc.currentBlock.Store(block)
   340  	bc.chainmu.Unlock()
   341  
   342  	log.Info("Committed new head block", "number", block.Number(), "hash", hash)
   343  	return nil
   344  }
   345  
   346  //gas limit返回当前头块的气体限制。
   347  func (bc *BlockChain) GasLimit() uint64 {
   348  	return bc.CurrentBlock().GasLimit()
   349  }
   350  
   351  //currentBlock检索规范链的当前头块。这个
   352  //块从区块链的内部缓存中检索。
   353  func (bc *BlockChain) CurrentBlock() *types.Block {
   354  	return bc.currentBlock.Load().(*types.Block)
   355  }
   356  
   357  //currentFastBlock检索规范的当前快速同步头块
   358  //链。块从区块链的内部缓存中检索。
   359  func (bc *BlockChain) CurrentFastBlock() *types.Block {
   360  	return bc.currentFastBlock.Load().(*types.Block)
   361  }
   362  
   363  //setprocessor设置进行状态修改所需的处理器。
   364  func (bc *BlockChain) SetProcessor(processor Processor) {
   365  	bc.procmu.Lock()
   366  	defer bc.procmu.Unlock()
   367  	bc.processor = processor
   368  }
   369  
   370  //setvalidator设置用于验证传入块的验证程序。
   371  func (bc *BlockChain) SetValidator(validator Validator) {
   372  	bc.procmu.Lock()
   373  	defer bc.procmu.Unlock()
   374  	bc.validator = validator
   375  }
   376  
   377  //验证器返回当前验证器。
   378  func (bc *BlockChain) Validator() Validator {
   379  	bc.procmu.RLock()
   380  	defer bc.procmu.RUnlock()
   381  	return bc.validator
   382  }
   383  
   384  //处理器返回当前处理器。
   385  func (bc *BlockChain) Processor() Processor {
   386  	bc.procmu.RLock()
   387  	defer bc.procmu.RUnlock()
   388  	return bc.processor
   389  }
   390  
   391  //State返回基于当前头块的新可变状态。
   392  func (bc *BlockChain) State() (*state.StateDB, error) {
   393  	return bc.StateAt(bc.CurrentBlock().Root())
   394  }
   395  
   396  //stateat返回基于特定时间点的新可变状态。
   397  func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) {
   398  	return state.New(root, bc.stateCache)
   399  }
   400  
   401  //StateCache返回支撑区块链实例的缓存数据库。
   402  func (bc *BlockChain) StateCache() state.Database {
   403  	return bc.stateCache
   404  }
   405  
   406  //重置清除整个区块链,将其恢复到其创始状态。
   407  func (bc *BlockChain) Reset() error {
   408  	return bc.ResetWithGenesisBlock(bc.genesisBlock)
   409  }
   410  
   411  //ResetWithGenerisBlock清除整个区块链,将其恢复到
   412  //指定的创世状态。
   413  func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
   414  //转储整个块链并清除缓存
   415  	if err := bc.SetHead(0); err != nil {
   416  		return err
   417  	}
   418  	bc.chainmu.Lock()
   419  	defer bc.chainmu.Unlock()
   420  
   421  //准备Genesis块并重新初始化链
   422  	if err := bc.hc.WriteTd(genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()); err != nil {
   423  		log.Crit("Failed to write genesis block TD", "err", err)
   424  	}
   425  	rawdb.WriteBlock(bc.db, genesis)
   426  
   427  	bc.genesisBlock = genesis
   428  	bc.insert(bc.genesisBlock)
   429  	bc.currentBlock.Store(bc.genesisBlock)
   430  	bc.hc.SetGenesis(bc.genesisBlock.Header())
   431  	bc.hc.SetCurrentHeader(bc.genesisBlock.Header())
   432  	bc.currentFastBlock.Store(bc.genesisBlock)
   433  
   434  	return nil
   435  }
   436  
   437  //修复试图通过回滚当前块来修复当前区块链
   438  //直到找到一个具有关联状态的。这需要修复不完整的数据库
   439  //由崩溃/断电或简单的未提交尝试引起的写入。
   440  //
   441  //此方法只回滚当前块。当前标题和当前
   442  //快速挡块完好无损。
   443  func (bc *BlockChain) repair(head **types.Block) error {
   444  	for {
   445  //如果我们重绕到一个有关联状态的头块,则中止
   446  		if _, err := state.New((*head).Root(), bc.stateCache); err == nil {
   447  			log.Info("Rewound blockchain to past state", "number", (*head).Number(), "hash", (*head).Hash())
   448  			return nil
   449  		}
   450  //否则,倒带一个块并在那里重新检查状态可用性
   451  		block := bc.GetBlock((*head).ParentHash(), (*head).NumberU64()-1)
   452  		if block == nil {
   453  			return fmt.Errorf("missing block %d [%x]", (*head).NumberU64()-1, (*head).ParentHash())
   454  		}
   455  		(*head) = block
   456  	}
   457  }
   458  
   459  //export将活动链写入给定的编写器。
   460  func (bc *BlockChain) Export(w io.Writer) error {
   461  	return bc.ExportN(w, uint64(0), bc.CurrentBlock().NumberU64())
   462  }
   463  
   464  //exportn将活动链的一个子集写入给定的编写器。
   465  func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error {
   466  	bc.chainmu.RLock()
   467  	defer bc.chainmu.RUnlock()
   468  
   469  	if first > last {
   470  		return fmt.Errorf("export failed: first (%d) is greater than last (%d)", first, last)
   471  	}
   472  	log.Info("Exporting batch of blocks", "count", last-first+1)
   473  
   474  	start, reported := time.Now(), time.Now()
   475  	for nr := first; nr <= last; nr++ {
   476  		block := bc.GetBlockByNumber(nr)
   477  		if block == nil {
   478  			return fmt.Errorf("export failed on #%d: not found", nr)
   479  		}
   480  		if err := block.EncodeRLP(w); err != nil {
   481  			return err
   482  		}
   483  		if time.Since(reported) >= statsReportLimit {
   484  			log.Info("Exporting blocks", "exported", block.NumberU64()-first, "elapsed", common.PrettyDuration(time.Since(start)))
   485  			reported = time.Now()
   486  		}
   487  	}
   488  	return nil
   489  }
   490  
   491  //插入将新的头块插入当前的块链。这种方法
   492  //假设该块确实是一个真正的头。它还将重置头部
   493  //头和头快速同步块与此非常相同的块(如果它们较旧)
   494  //或者如果它们在另一条边链上。
   495  //
   496  //注意,此函数假定保持“mu”互斥!
   497  func (bc *BlockChain) insert(block *types.Block) {
   498  //如果木块位于侧链或未知链条上,也应将其他头压到链条上。
   499  	updateHeads := rawdb.ReadCanonicalHash(bc.db, block.NumberU64()) != block.Hash()
   500  
   501  //将块添加到规范链编号方案并标记为头
   502  	rawdb.WriteCanonicalHash(bc.db, block.Hash(), block.NumberU64())
   503  	rawdb.WriteHeadBlockHash(bc.db, block.Hash())
   504  
   505  	bc.currentBlock.Store(block)
   506  
   507  //如果块比我们的头更好或位于不同的链上,则强制更新头
   508  	if updateHeads {
   509  		bc.hc.SetCurrentHeader(block.Header())
   510  		rawdb.WriteHeadFastBlockHash(bc.db, block.Hash())
   511  
   512  		bc.currentFastBlock.Store(block)
   513  	}
   514  }
   515  
   516  //Genesis检索链的Genesis块。
   517  func (bc *BlockChain) Genesis() *types.Block {
   518  	return bc.genesisBlock
   519  }
   520  
   521  //getbody通过以下方式从数据库中检索块体(事务和uncles)
   522  //哈希,如果找到,则缓存它。
   523  func (bc *BlockChain) GetBody(hash common.Hash) *types.Body {
   524  //如果主体已在缓存中,则短路,否则检索
   525  	if cached, ok := bc.bodyCache.Get(hash); ok {
   526  		body := cached.(*types.Body)
   527  		return body
   528  	}
   529  	number := bc.hc.GetBlockNumber(hash)
   530  	if number == nil {
   531  		return nil
   532  	}
   533  	body := rawdb.ReadBody(bc.db, hash, *number)
   534  	if body == nil {
   535  		return nil
   536  	}
   537  //缓存下一次找到的正文并返回
   538  	bc.bodyCache.Add(hash, body)
   539  	return body
   540  }
   541  
   542  //getBodyrlp通过哈希从数据库中检索以rlp编码的块体,
   543  //如果找到,则缓存它。
   544  func (bc *BlockChain) GetBodyRLP(hash common.Hash) rlp.RawValue {
   545  //如果主体已在缓存中,则短路,否则检索
   546  	if cached, ok := bc.bodyRLPCache.Get(hash); ok {
   547  		return cached.(rlp.RawValue)
   548  	}
   549  	number := bc.hc.GetBlockNumber(hash)
   550  	if number == nil {
   551  		return nil
   552  	}
   553  	body := rawdb.ReadBodyRLP(bc.db, hash, *number)
   554  	if len(body) == 0 {
   555  		return nil
   556  	}
   557  //缓存下一次找到的正文并返回
   558  	bc.bodyRLPCache.Add(hash, body)
   559  	return body
   560  }
   561  
   562  //hasblock检查数据库中是否完全存在块。
   563  func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
   564  	if bc.blockCache.Contains(hash) {
   565  		return true
   566  	}
   567  	return rawdb.HasBody(bc.db, hash, number)
   568  }
   569  
   570  //hasFastBlock检查数据库中是否完全存在快速块。
   571  func (bc *BlockChain) HasFastBlock(hash common.Hash, number uint64) bool {
   572  	if !bc.HasBlock(hash, number) {
   573  		return false
   574  	}
   575  	if bc.receiptsCache.Contains(hash) {
   576  		return true
   577  	}
   578  	return rawdb.HasReceipts(bc.db, hash, number)
   579  }
   580  
   581  //hasstate检查数据库中是否完全存在状态trie。
   582  func (bc *BlockChain) HasState(hash common.Hash) bool {
   583  	_, err := bc.stateCache.OpenTrie(hash)
   584  	return err == nil
   585  }
   586  
   587  //hasblockandstate检查块和关联状态trie是否完全存在
   588  //在数据库中或不在数据库中,缓存它(如果存在)。
   589  func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool {
   590  //首先检查块本身是否已知
   591  	block := bc.GetBlock(hash, number)
   592  	if block == nil {
   593  		return false
   594  	}
   595  	return bc.HasState(block.Root())
   596  }
   597  
   598  //GetBlock按哈希和数字从数据库中检索块,
   599  //如果找到,则缓存它。
   600  func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
   601  //如果块已在缓存中,则短路,否则检索
   602  	if block, ok := bc.blockCache.Get(hash); ok {
   603  		return block.(*types.Block)
   604  	}
   605  	block := rawdb.ReadBlock(bc.db, hash, number)
   606  	if block == nil {
   607  		return nil
   608  	}
   609  //下次缓存找到的块并返回
   610  	bc.blockCache.Add(block.Hash(), block)
   611  	return block
   612  }
   613  
   614  //GetBlockByHash通过哈希从数据库中检索一个块,如果找到该块,则将其缓存。
   615  func (bc *BlockChain) GetBlockByHash(hash common.Hash) *types.Block {
   616  	number := bc.hc.GetBlockNumber(hash)
   617  	if number == nil {
   618  		return nil
   619  	}
   620  	return bc.GetBlock(hash, *number)
   621  }
   622  
   623  //GetBlockByNumber按编号从数据库中检索块,并将其缓存
   624  //(与哈希关联)如果找到。
   625  func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block {
   626  	hash := rawdb.ReadCanonicalHash(bc.db, number)
   627  	if hash == (common.Hash{}) {
   628  		return nil
   629  	}
   630  	return bc.GetBlock(hash, number)
   631  }
   632  
   633  //getReceiptsByHash检索给定块中所有事务的收据。
   634  func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
   635  	if receipts, ok := bc.receiptsCache.Get(hash); ok {
   636  		return receipts.(types.Receipts)
   637  	}
   638  	number := rawdb.ReadHeaderNumber(bc.db, hash)
   639  	if number == nil {
   640  		return nil
   641  	}
   642  	receipts := rawdb.ReadReceipts(bc.db, hash, *number)
   643  	if receipts == nil {
   644  		return nil
   645  	}
   646  	bc.receiptsCache.Add(hash, receipts)
   647  	return receipts
   648  }
   649  
   650  //GetBlocksFromHash返回与哈希和N-1祖先对应的块。
   651  //[被ETH/62否决]
   652  func (bc *BlockChain) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) {
   653  	number := bc.hc.GetBlockNumber(hash)
   654  	if number == nil {
   655  		return nil
   656  	}
   657  	for i := 0; i < n; i++ {
   658  		block := bc.GetBlock(hash, *number)
   659  		if block == nil {
   660  			break
   661  		}
   662  		blocks = append(blocks, block)
   663  		hash = block.ParentHash()
   664  		*number--
   665  	}
   666  	return
   667  }
   668  
   669  //getUnbenshinchain从给定块中向后检索所有叔叔,直到
   670  //达到特定距离。
   671  func (bc *BlockChain) GetUnclesInChain(block *types.Block, length int) []*types.Header {
   672  	uncles := []*types.Header{}
   673  	for i := 0; block != nil && i < length; i++ {
   674  		uncles = append(uncles, block.Uncles()...)
   675  		block = bc.GetBlock(block.ParentHash(), block.NumberU64()-1)
   676  	}
   677  	return uncles
   678  }
   679  
   680  //trie node检索与trie节点(或代码哈希)关联的一个数据块。
   681  //要么来自短暂的内存缓存,要么来自持久存储。
   682  func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) {
   683  	return bc.stateCache.TrieDB().Node(hash)
   684  }
   685  
   686  //停止停止区块链服务。如果任何导入当前正在进行中
   687  //它将使用procInterrupt中止它们。
   688  func (bc *BlockChain) Stop() {
   689  	if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) {
   690  		return
   691  	}
   692  //取消订阅从区块链注册的所有订阅
   693  	bc.scope.Close()
   694  	close(bc.quit)
   695  	atomic.StoreInt32(&bc.procInterrupt, 1)
   696  
   697  	bc.wg.Wait()
   698  
   699  //在退出之前,请确保最近块的状态也存储到磁盘。
   700  //我们编写了三种不同的状态来捕捉不同的重启场景:
   701  //头:所以一般情况下我们不需要重新处理任何块。
   702  //-head-1:所以如果我们的头变成叔叔,我们就不会进行大重组。
   703  //-HEAD-127:因此我们对重新执行的块数有一个硬限制
   704  	if !bc.cacheConfig.Disabled {
   705  		triedb := bc.stateCache.TrieDB()
   706  
   707  		for _, offset := range []uint64{0, 1, triesInMemory - 1} {
   708  			if number := bc.CurrentBlock().NumberU64(); number > offset {
   709  				recent := bc.GetBlockByNumber(number - offset)
   710  
   711  				log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
   712  				if err := triedb.Commit(recent.Root(), true); err != nil {
   713  					log.Error("Failed to commit recent state trie", "err", err)
   714  				}
   715  			}
   716  		}
   717  		for !bc.triegc.Empty() {
   718  			triedb.Dereference(bc.triegc.PopItem().(common.Hash))
   719  		}
   720  		if size, _ := triedb.Size(); size != 0 {
   721  			log.Error("Dangling trie nodes after full cleanup")
   722  		}
   723  	}
   724  	log.Info("Blockchain manager stopped")
   725  }
   726  
   727  func (bc *BlockChain) procFutureBlocks() {
   728  	blocks := make([]*types.Block, 0, bc.futureBlocks.Len())
   729  	for _, hash := range bc.futureBlocks.Keys() {
   730  		if block, exist := bc.futureBlocks.Peek(hash); exist {
   731  			blocks = append(blocks, block.(*types.Block))
   732  		}
   733  	}
   734  	if len(blocks) > 0 {
   735  		types.BlockBy(types.Number).Sort(blocks)
   736  
   737  //逐个插入,因为链插入需要块之间的连续祖先
   738  		for i := range blocks {
   739  			bc.InsertChain(blocks[i : i+1])
   740  		}
   741  	}
   742  }
   743  
   744  //写入状态写入状态
   745  type WriteStatus byte
   746  
   747  const (
   748  	NonStatTy WriteStatus = iota
   749  	CanonStatTy
   750  	SideStatTy
   751  )
   752  
   753  //回滚的目的是从数据库中删除一系列链接,而这些链接不是
   754  //足够确定有效。
   755  func (bc *BlockChain) Rollback(chain []common.Hash) {
   756  	bc.chainmu.Lock()
   757  	defer bc.chainmu.Unlock()
   758  
   759  	for i := len(chain) - 1; i >= 0; i-- {
   760  		hash := chain[i]
   761  
   762  		currentHeader := bc.hc.CurrentHeader()
   763  		if currentHeader.Hash() == hash {
   764  			bc.hc.SetCurrentHeader(bc.GetHeader(currentHeader.ParentHash, currentHeader.Number.Uint64()-1))
   765  		}
   766  		if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock.Hash() == hash {
   767  			newFastBlock := bc.GetBlock(currentFastBlock.ParentHash(), currentFastBlock.NumberU64()-1)
   768  			bc.currentFastBlock.Store(newFastBlock)
   769  			rawdb.WriteHeadFastBlockHash(bc.db, newFastBlock.Hash())
   770  		}
   771  		if currentBlock := bc.CurrentBlock(); currentBlock.Hash() == hash {
   772  			newBlock := bc.GetBlock(currentBlock.ParentHash(), currentBlock.NumberU64()-1)
   773  			bc.currentBlock.Store(newBlock)
   774  			rawdb.WriteHeadBlockHash(bc.db, newBlock.Hash())
   775  		}
   776  	}
   777  }
   778  
   779  //setReceiptsData计算收据的所有非共识字段
   780  func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts types.Receipts) error {
   781  	signer := types.MakeSigner(config, block.Number())
   782  
   783  	transactions, logIndex := block.Transactions(), uint(0)
   784  	if len(transactions) != len(receipts) {
   785  		return errors.New("transaction and receipt count mismatch")
   786  	}
   787  
   788  	for j := 0; j < len(receipts); j++ {
   789  //可以从事务本身检索事务哈希
   790  		receipts[j].TxHash = transactions[j].Hash()
   791  
   792  //合同地址可以从事务本身派生
   793  		if transactions[j].To() == nil {
   794  //获得签名者很昂贵,只有在实际需要的时候才这么做
   795  			from, _ := types.Sender(signer, transactions[j])
   796  			receipts[j].ContractAddress = crypto.CreateAddress(from, transactions[j].Nonce())
   797  		}
   798  //使用过的气体可根据以前的收据进行计算。
   799  		if j == 0 {
   800  			receipts[j].GasUsed = receipts[j].CumulativeGasUsed
   801  		} else {
   802  			receipts[j].GasUsed = receipts[j].CumulativeGasUsed - receipts[j-1].CumulativeGasUsed
   803  		}
   804  //派生的日志字段可以简单地从块和事务中设置。
   805  		for k := 0; k < len(receipts[j].Logs); k++ {
   806  			receipts[j].Logs[k].BlockNumber = block.NumberU64()
   807  			receipts[j].Logs[k].BlockHash = block.Hash()
   808  			receipts[j].Logs[k].TxHash = receipts[j].TxHash
   809  			receipts[j].Logs[k].TxIndex = uint(j)
   810  			receipts[j].Logs[k].Index = logIndex
   811  			logIndex++
   812  		}
   813  	}
   814  	return nil
   815  }
   816  
   817  //InsertReceiptChain尝试使用
   818  //交易和收据数据。
   819  func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
   820  	bc.wg.Add(1)
   821  	defer bc.wg.Done()
   822  
   823  //做一个健全的检查,确保提供的链实际上是有序的和链接的
   824  	for i := 1; i < len(blockChain); i++ {
   825  		if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() {
   826  			log.Error("Non contiguous receipt insert", "number", blockChain[i].Number(), "hash", blockChain[i].Hash(), "parent", blockChain[i].ParentHash(),
   827  				"prevnumber", blockChain[i-1].Number(), "prevhash", blockChain[i-1].Hash())
   828  			return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, blockChain[i-1].NumberU64(),
   829  				blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4])
   830  		}
   831  	}
   832  
   833  	var (
   834  		stats = struct{ processed, ignored int32 }{}
   835  		start = time.Now()
   836  		bytes = 0
   837  		batch = bc.db.NewBatch()
   838  	)
   839  	for i, block := range blockChain {
   840  		receipts := receiptChain[i]
   841  //关闭或处理失败时短路插入
   842  		if atomic.LoadInt32(&bc.procInterrupt) == 1 {
   843  			return 0, nil
   844  		}
   845  //所有者标题未知时短路
   846  		if !bc.HasHeader(block.Hash(), block.NumberU64()) {
   847  			return i, fmt.Errorf("containing header #%d [%x…] unknown", block.Number(), block.Hash().Bytes()[:4])
   848  		}
   849  //如果整个数据已知,则跳过
   850  		if bc.HasBlock(block.Hash(), block.NumberU64()) {
   851  			stats.ignored++
   852  			continue
   853  		}
   854  //计算收据的所有非一致字段
   855  		if err := SetReceiptsData(bc.chainConfig, block, receipts); err != nil {
   856  			return i, fmt.Errorf("failed to set receipts data: %v", err)
   857  		}
   858  //将所有数据写入数据库
   859  		rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
   860  		rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receipts)
   861  		rawdb.WriteTxLookupEntries(batch, block)
   862  
   863  		stats.processed++
   864  
   865  		if batch.ValueSize() >= ethdb.IdealBatchSize {
   866  			if err := batch.Write(); err != nil {
   867  				return 0, err
   868  			}
   869  			bytes += batch.ValueSize()
   870  			batch.Reset()
   871  		}
   872  	}
   873  	if batch.ValueSize() > 0 {
   874  		bytes += batch.ValueSize()
   875  		if err := batch.Write(); err != nil {
   876  			return 0, err
   877  		}
   878  	}
   879  
   880  //如果更好的话,更新head fast sync块
   881  	bc.chainmu.Lock()
   882  	head := blockChain[len(blockChain)-1]
   883  if td := bc.GetTd(head.Hash(), head.NumberU64()); td != nil { //可能发生倒带,在这种情况下跳过
   884  		currentFastBlock := bc.CurrentFastBlock()
   885  		if bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64()).Cmp(td) < 0 {
   886  			rawdb.WriteHeadFastBlockHash(bc.db, head.Hash())
   887  			bc.currentFastBlock.Store(head)
   888  		}
   889  	}
   890  	bc.chainmu.Unlock()
   891  
   892  	context := []interface{}{
   893  		"count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
   894  		"number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(head.Time().Int64(), 0)),
   895  		"size", common.StorageSize(bytes),
   896  	}
   897  	if stats.ignored > 0 {
   898  		context = append(context, []interface{}{"ignored", stats.ignored}...)
   899  	}
   900  	log.Info("Imported new block receipts", context...)
   901  
   902  	return 0, nil
   903  }
   904  
   905  var lastWrite uint64
   906  
   907  //WriteBlockWithOutState只将块及其元数据写入数据库,
   908  //但不写任何状态。这是用来构建竞争侧叉
   909  //直到他们超过了标准的总难度。
   910  func (bc *BlockChain) WriteBlockWithoutState(block *types.Block, td *big.Int) (err error) {
   911  	bc.wg.Add(1)
   912  	defer bc.wg.Done()
   913  
   914  	if err := bc.hc.WriteTd(block.Hash(), block.NumberU64(), td); err != nil {
   915  		return err
   916  	}
   917  	rawdb.WriteBlock(bc.db, block)
   918  
   919  	return nil
   920  }
   921  
   922  //WriteBlockWithState将块和所有关联状态写入数据库。
   923  func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) (status WriteStatus, err error) {
   924  	bc.chainmu.Lock()
   925  	defer bc.chainmu.Unlock()
   926  
   927  	return bc.writeBlockWithState(block, receipts, state)
   928  }
   929  
   930  //WriteBlockWithState将块和所有关联状态写入数据库,
   931  //但IS希望保持链互斥。
   932  func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) (status WriteStatus, err error) {
   933  	bc.wg.Add(1)
   934  	defer bc.wg.Done()
   935  
   936  //计算块的总难度
   937  	ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
   938  	if ptd == nil {
   939  		return NonStatTy, consensus.ErrUnknownAncestor
   940  	}
   941  //确保插入期间没有不一致的状态泄漏
   942  	currentBlock := bc.CurrentBlock()
   943  	localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
   944  	externTd := new(big.Int).Add(block.Difficulty(), ptd)
   945  
   946  //与规范状态无关,将块本身写入数据库
   947  	if err := bc.hc.WriteTd(block.Hash(), block.NumberU64(), externTd); err != nil {
   948  		return NonStatTy, err
   949  	}
   950  	rawdb.WriteBlock(bc.db, block)
   951  
   952  	root, err := state.Commit(bc.chainConfig.IsEIP158(block.Number()))
   953  	if err != nil {
   954  		return NonStatTy, err
   955  	}
   956  	triedb := bc.stateCache.TrieDB()
   957  
   958  //如果我们正在运行存档节点,请始终刷新
   959  	if bc.cacheConfig.Disabled {
   960  		if err := triedb.Commit(root, false); err != nil {
   961  			return NonStatTy, err
   962  		}
   963  	} else {
   964  //完整但不是存档节点,请执行正确的垃圾收集
   965  triedb.Reference(root, common.Hash{}) //保持trie活动的元数据引用
   966  		bc.triegc.Push(root, -int64(block.NumberU64()))
   967  
   968  		if current := block.NumberU64(); current > triesInMemory {
   969  //如果超出内存限制,将成熟的单例节点刷新到磁盘
   970  			var (
   971  				nodes, imgs = triedb.Size()
   972  				limit       = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
   973  			)
   974  			if nodes > limit || imgs > 4*1024*1024 {
   975  				triedb.Cap(limit - ethdb.IdealBatchSize)
   976  			}
   977  //找到我们需要承诺的下一个州
   978  			header := bc.GetHeaderByNumber(current - triesInMemory)
   979  			chosen := header.Number.Uint64()
   980  
   981  //如果超出超时限制,将整个trie刷新到磁盘
   982  			if bc.gcproc > bc.cacheConfig.TrieTimeLimit {
   983  //如果我们超出了限制,但没有达到足够大的内存缺口,
   984  //警告用户系统正在变得不稳定。
   985  				if chosen < lastWrite+triesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
   986  					log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/triesInMemory)
   987  				}
   988  //刷新整个trie并重新启动计数器
   989  				triedb.Commit(header.Root, true)
   990  				lastWrite = chosen
   991  				bc.gcproc = 0
   992  			}
   993  //垃圾收集低于我们要求的写保留的任何内容
   994  			for !bc.triegc.Empty() {
   995  				root, number := bc.triegc.Pop()
   996  				if uint64(-number) > chosen {
   997  					bc.triegc.Push(root, number)
   998  					break
   999  				}
  1000  				triedb.Dereference(root.(common.Hash))
  1001  			}
  1002  		}
  1003  	}
  1004  
  1005  //使用批处理写入其他块数据。
  1006  	batch := bc.db.NewBatch()
  1007  	rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receipts)
  1008  
  1009  //如果总的困难比我们已知的要高,就把它加到规范链中去。
  1010  //if语句中的第二个子句减少了自私挖掘的脆弱性。
  1011  //请参阅http://www.cs.cornell.edu/~ie53/publications/btcrpocfc.pdf
  1012  	reorg := externTd.Cmp(localTd) > 0
  1013  	currentBlock = bc.CurrentBlock()
  1014  	if !reorg && externTd.Cmp(localTd) == 0 {
  1015  //按数字拆分相同的难度块,然后优先选择
  1016  //由本地矿工生成的作为规范块的块。
  1017  		if block.NumberU64() < currentBlock.NumberU64() {
  1018  			reorg = true
  1019  		} else if block.NumberU64() == currentBlock.NumberU64() {
  1020  			var currentPreserve, blockPreserve bool
  1021  			if bc.shouldPreserve != nil {
  1022  				currentPreserve, blockPreserve = bc.shouldPreserve(currentBlock), bc.shouldPreserve(block)
  1023  			}
  1024  			reorg = !currentPreserve && (blockPreserve || mrand.Float64() < 0.5)
  1025  		}
  1026  	}
  1027  	if reorg {
  1028  //如果父级不是头块,则重新组织链
  1029  		if block.ParentHash() != currentBlock.Hash() {
  1030  			if err := bc.reorg(currentBlock, block); err != nil {
  1031  				return NonStatTy, err
  1032  			}
  1033  		}
  1034  //为事务/收据查找和预映像编写位置元数据
  1035  		rawdb.WriteTxLookupEntries(batch, block)
  1036  		rawdb.WritePreimages(batch, state.Preimages())
  1037  
  1038  		status = CanonStatTy
  1039  	} else {
  1040  		status = SideStatTy
  1041  	}
  1042  	if err := batch.Write(); err != nil {
  1043  		return NonStatTy, err
  1044  	}
  1045  
  1046  //树立新的头脑。
  1047  	if status == CanonStatTy {
  1048  		bc.insert(block)
  1049  	}
  1050  	bc.futureBlocks.Remove(block.Hash())
  1051  	return status, nil
  1052  }
  1053  
  1054  //AddFutureBlock检查块是否在允许的最大窗口内
  1055  //接受以供将来处理,如果块太远则返回错误
  1056  //前面没有添加。
  1057  func (bc *BlockChain) addFutureBlock(block *types.Block) error {
  1058  	max := big.NewInt(time.Now().Unix() + maxTimeFutureBlocks)
  1059  	if block.Time().Cmp(max) > 0 {
  1060  		return fmt.Errorf("future block timestamp %v > allowed %v", block.Time(), max)
  1061  	}
  1062  	bc.futureBlocks.Add(block.Hash(), block)
  1063  	return nil
  1064  }
  1065  
  1066  //
  1067  //用链子或其他方法,创建一个叉子。如果返回错误,它将返回
  1068  //失败块的索引号以及描述所执行操作的错误
  1069  //错了。
  1070  //
  1071  //插入完成后,将激发所有累积的事件。
  1072  func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
  1073  //检查我们有什么有意义的东西要导入
  1074  	if len(chain) == 0 {
  1075  		return 0, nil
  1076  	}
  1077  //做一个健全的检查,确保提供的链实际上是有序的和链接的
  1078  	for i := 1; i < len(chain); i++ {
  1079  		if chain[i].NumberU64() != chain[i-1].NumberU64()+1 || chain[i].ParentHash() != chain[i-1].Hash() {
  1080  //断链祖先、记录消息(编程错误)和跳过插入
  1081  			log.Error("Non contiguous block insert", "number", chain[i].Number(), "hash", chain[i].Hash(),
  1082  				"parent", chain[i].ParentHash(), "prevnumber", chain[i-1].Number(), "prevhash", chain[i-1].Hash())
  1083  
  1084  			return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, chain[i-1].NumberU64(),
  1085  				chain[i-1].Hash().Bytes()[:4], i, chain[i].NumberU64(), chain[i].Hash().Bytes()[:4], chain[i].ParentHash().Bytes()[:4])
  1086  		}
  1087  	}
  1088  //预检查通过,开始全块导入
  1089  	bc.wg.Add(1)
  1090  	bc.chainmu.Lock()
  1091  	n, events, logs, err := bc.insertChain(chain, true)
  1092  	bc.chainmu.Unlock()
  1093  	bc.wg.Done()
  1094  
  1095  	bc.PostChainEvents(events, logs)
  1096  	return n, err
  1097  }
  1098  
  1099  //insertchain是insertchain的内部实现,它假定
  1100  //1)链是连续的,2)链互斥被保持。
  1101  //
  1102  //此方法被拆分,以便导入需要重新注入的批
  1103  //历史块可以这样做,而不释放锁,这可能导致
  1104  //赛马行为。如果侧链导入正在进行,以及历史状态
  1105  //是导入的,但在实际侧链之前添加新的Canon头
  1106  //完成,然后历史状态可以再次修剪
  1107  func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []interface{}, []*types.Log, error) {
  1108  //如果链终止,甚至不用麻烦启动U
  1109  	if atomic.LoadInt32(&bc.procInterrupt) == 1 {
  1110  		return 0, nil, nil, nil
  1111  	}
  1112  //开始并行签名恢复(签名者将在fork转换时出错,性能损失最小)
  1113  	senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain)
  1114  
  1115  //用于传递事件的排队方法。这通常是
  1116  //比直接传送更快,而且需要更少的互斥。
  1117  //获取。
  1118  	var (
  1119  		stats         = insertStats{startTime: mclock.Now()}
  1120  		events        = make([]interface{}, 0, len(chain))
  1121  		lastCanon     *types.Block
  1122  		coalescedLogs []*types.Log
  1123  	)
  1124  //启动并行头验证程序
  1125  	headers := make([]*types.Header, len(chain))
  1126  	seals := make([]bool, len(chain))
  1127  
  1128  	for i, block := range chain {
  1129  		headers[i] = block.Header()
  1130  		seals[i] = verifySeals
  1131  	}
  1132  	abort, results := bc.engine.VerifyHeaders(bc, headers, seals)
  1133  	defer close(abort)
  1134  
  1135  //查看第一个块的错误以决定直接导入逻辑
  1136  	it := newInsertIterator(chain, results, bc.Validator())
  1137  
  1138  	block, err := it.next()
  1139  	switch {
  1140  //第一个块被修剪,插入为侧链,只有当td足够长时才重新排序。
  1141  	case err == consensus.ErrPrunedAncestor:
  1142  		return bc.insertSidechain(it)
  1143  
  1144  //第一个块是未来,将其(和所有子块)推送到未来队列(未知的祖先)
  1145  	case err == consensus.ErrFutureBlock || (err == consensus.ErrUnknownAncestor && bc.futureBlocks.Contains(it.first().ParentHash())):
  1146  		for block != nil && (it.index == 0 || err == consensus.ErrUnknownAncestor) {
  1147  			if err := bc.addFutureBlock(block); err != nil {
  1148  				return it.index, events, coalescedLogs, err
  1149  			}
  1150  			block, err = it.next()
  1151  		}
  1152  		stats.queued += it.processed()
  1153  		stats.ignored += it.remaining()
  1154  
  1155  //如果还有剩余,则标记为“忽略”
  1156  		return it.index, events, coalescedLogs, err
  1157  
  1158  //已知第一个块(和状态)
  1159  //1。我们做了一个回滚,现在应该重新导入
  1160  //2。该块存储为侧链,并基于它的StateRoot,传递一个StateRoot
  1161  //来自规范链,尚未验证。
  1162  	case err == ErrKnownBlock:
  1163  //跳过我们身后所有已知的街区
  1164  		current := bc.CurrentBlock().NumberU64()
  1165  
  1166  		for block != nil && err == ErrKnownBlock && current >= block.NumberU64() {
  1167  			stats.ignored++
  1168  			block, err = it.next()
  1169  		}
  1170  //通过块导入
  1171  
  1172  //发生其他错误,中止
  1173  	case err != nil:
  1174  		stats.ignored += len(it.chain)
  1175  		bc.reportBlock(block, nil, err)
  1176  		return it.index, events, coalescedLogs, err
  1177  	}
  1178  //第一个块没有验证错误(或跳过链前缀)
  1179  	for ; block != nil && err == nil; block, err = it.next() {
  1180  //如果链终止,则停止处理块
  1181  		if atomic.LoadInt32(&bc.procInterrupt) == 1 {
  1182  			log.Debug("Premature abort during blocks processing")
  1183  			break
  1184  		}
  1185  //如果标题是禁止的,直接中止
  1186  		if BadHashes[block.Hash()] {
  1187  			bc.reportBlock(block, nil, ErrBlacklistedHash)
  1188  			return it.index, events, coalescedLogs, ErrBlacklistedHash
  1189  		}
  1190  //检索父块,它的状态为在上面执行
  1191  		start := time.Now()
  1192  
  1193  		parent := it.previous()
  1194  		if parent == nil {
  1195  			parent = bc.GetBlock(block.ParentHash(), block.NumberU64()-1)
  1196  		}
  1197  		state, err := state.New(parent.Root(), bc.stateCache)
  1198  		if err != nil {
  1199  			return it.index, events, coalescedLogs, err
  1200  		}
  1201  //使用父状态作为参考点处理块。
  1202  		t0 := time.Now()
  1203  		receipts, logs, usedGas, err := bc.processor.Process(block, state, bc.vmConfig)
  1204  		t1 := time.Now()
  1205  		if err != nil {
  1206  			bc.reportBlock(block, receipts, err)
  1207  			return it.index, events, coalescedLogs, err
  1208  		}
  1209  //使用默认验证器验证状态
  1210  		if err := bc.Validator().ValidateState(block, parent, state, receipts, usedGas); err != nil {
  1211  			bc.reportBlock(block, receipts, err)
  1212  			return it.index, events, coalescedLogs, err
  1213  		}
  1214  		t2 := time.Now()
  1215  		proctime := time.Since(start)
  1216  
  1217  //将块写入链并获取状态。
  1218  		status, err := bc.writeBlockWithState(block, receipts, state)
  1219  		t3 := time.Now()
  1220  		if err != nil {
  1221  			return it.index, events, coalescedLogs, err
  1222  		}
  1223  		blockInsertTimer.UpdateSince(start)
  1224  		blockExecutionTimer.Update(t1.Sub(t0))
  1225  		blockValidationTimer.Update(t2.Sub(t1))
  1226  		blockWriteTimer.Update(t3.Sub(t2))
  1227  		switch status {
  1228  		case CanonStatTy:
  1229  			log.Debug("Inserted new block", "number", block.Number(), "hash", block.Hash(),
  1230  				"uncles", len(block.Uncles()), "txs", len(block.Transactions()), "gas", block.GasUsed(),
  1231  				"elapsed", common.PrettyDuration(time.Since(start)),
  1232  				"root", block.Root())
  1233  
  1234  			coalescedLogs = append(coalescedLogs, logs...)
  1235  			events = append(events, ChainEvent{block, block.Hash(), logs})
  1236  			lastCanon = block
  1237  
  1238  //仅统计GC处理时间的规范块
  1239  			bc.gcproc += proctime
  1240  
  1241  		case SideStatTy:
  1242  			log.Debug("Inserted forked block", "number", block.Number(), "hash", block.Hash(),
  1243  				"diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)),
  1244  				"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
  1245  				"root", block.Root())
  1246  			events = append(events, ChainSideEvent{block})
  1247  		}
  1248  		blockInsertTimer.UpdateSince(start)
  1249  		stats.processed++
  1250  		stats.usedGas += usedGas
  1251  
  1252  		cache, _ := bc.stateCache.TrieDB().Size()
  1253  		stats.report(chain, it.index, cache)
  1254  	}
  1255  //还有街区吗?我们唯一关心的是未来的
  1256  	if block != nil && err == consensus.ErrFutureBlock {
  1257  		if err := bc.addFutureBlock(block); err != nil {
  1258  			return it.index, events, coalescedLogs, err
  1259  		}
  1260  		block, err = it.next()
  1261  
  1262  		for ; block != nil && err == consensus.ErrUnknownAncestor; block, err = it.next() {
  1263  			if err := bc.addFutureBlock(block); err != nil {
  1264  				return it.index, events, coalescedLogs, err
  1265  			}
  1266  			stats.queued++
  1267  		}
  1268  	}
  1269  	stats.ignored += it.remaining()
  1270  
  1271  //如果我们已经进行了链,则附加一个单链头事件
  1272  	if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
  1273  		events = append(events, ChainHeadEvent{lastCanon})
  1274  	}
  1275  	return it.index, events, coalescedLogs, err
  1276  }
  1277  
  1278  //当导入批处理碰到修剪后的祖先时调用InsertSideChain。
  1279  //错误,当具有足够旧的叉块的侧链
  1280  //找到了。
  1281  //
  1282  //该方法将所有(头和正文有效)块写入磁盘,然后尝试
  1283  //如果td超过当前链,则切换到新链。
  1284  func (bc *BlockChain) insertSidechain(it *insertIterator) (int, []interface{}, []*types.Log, error) {
  1285  	var (
  1286  		externTd *big.Int
  1287  		current  = bc.CurrentBlock()
  1288  	)
  1289  //第一个侧链块错误已被验证为errprunedancestor。
  1290  //既然我们不在这里进口它们,我们希望剩下的人知道错误。
  1291  //那些。任何其他错误表示块无效,不应写入
  1292  //到磁盘。
  1293  	block, err := it.current(), consensus.ErrPrunedAncestor
  1294  	for ; block != nil && (err == consensus.ErrPrunedAncestor); block, err = it.next() {
  1295  //检查该数字的规范化状态根目录
  1296  		if number := block.NumberU64(); current.NumberU64() >= number {
  1297  			if canonical := bc.GetBlockByNumber(number); canonical != nil && canonical.Root() == block.Root() {
  1298  //这很可能是影子国家的攻击。当叉子导入到
  1299  //数据库,它最终达到一个未修剪的块高度,我们
  1300  //刚刚发现状态已经存在!这意味着侧链块
  1301  //指已经存在于我们的佳能链中的状态。
  1302  //
  1303  //如果不选中,我们现在将继续导入块,而实际上
  1304  //已经验证了前面块的状态。
  1305  				log.Warn("Sidechain ghost-state attack detected", "number", block.NumberU64(), "sideroot", block.Root(), "canonroot", canonical.Root())
  1306  
  1307  //如果有人合法地将地雷挡在一边,它们仍然会像往常一样被进口。然而,
  1308  //当未验证的块明显以修剪为目标时,我们不能冒险将它们写入磁盘。
  1309  //机制。
  1310  				return it.index, nil, nil, errors.New("sidechain ghost-state attack")
  1311  			}
  1312  		}
  1313  		if externTd == nil {
  1314  			externTd = bc.GetTd(block.ParentHash(), block.NumberU64()-1)
  1315  		}
  1316  		externTd = new(big.Int).Add(externTd, block.Difficulty())
  1317  
  1318  		if !bc.HasBlock(block.Hash(), block.NumberU64()) {
  1319  			start := time.Now()
  1320  			if err := bc.WriteBlockWithoutState(block, externTd); err != nil {
  1321  				return it.index, nil, nil, err
  1322  			}
  1323  			log.Debug("Inserted sidechain block", "number", block.Number(), "hash", block.Hash(),
  1324  				"diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)),
  1325  				"txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()),
  1326  				"root", block.Root())
  1327  		}
  1328  	}
  1329  //此时,我们已经将所有的侧链块写入数据库。循环结束
  1330  //或者是其他错误,或者是全部被处理。如果还有其他的
  1331  //错误,我们可以忽略这些块的其余部分。
  1332  //
  1333  //如果externtd大于本地td,我们现在需要重新导入上一个
  1334  //重新生成所需状态的块
  1335  	localTd := bc.GetTd(current.Hash(), current.NumberU64())
  1336  	if localTd.Cmp(externTd) > 0 {
  1337  		log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().NumberU64(), "sidetd", externTd, "localtd", localTd)
  1338  		return it.index, nil, nil, err
  1339  	}
  1340  //收集所有侧链散列(完整的块可能内存很重)
  1341  	var (
  1342  		hashes  []common.Hash
  1343  		numbers []uint64
  1344  	)
  1345  	parent := bc.GetHeader(it.previous().Hash(), it.previous().NumberU64())
  1346  	for parent != nil && !bc.HasState(parent.Root) {
  1347  		hashes = append(hashes, parent.Hash())
  1348  		numbers = append(numbers, parent.Number.Uint64())
  1349  
  1350  		parent = bc.GetHeader(parent.ParentHash, parent.Number.Uint64()-1)
  1351  	}
  1352  	if parent == nil {
  1353  		return it.index, nil, nil, errors.New("missing parent")
  1354  	}
  1355  //导入所有修剪的块以使状态可用
  1356  	var (
  1357  		blocks []*types.Block
  1358  		memory common.StorageSize
  1359  	)
  1360  	for i := len(hashes) - 1; i >= 0; i-- {
  1361  //将下一个块追加到批处理中
  1362  		block := bc.GetBlock(hashes[i], numbers[i])
  1363  
  1364  		blocks = append(blocks, block)
  1365  		memory += block.Size()
  1366  
  1367  //如果内存使用量增长过大,请导入并继续。可悲的是我们需要抛弃
  1368  //所有从通知中引发的事件和日志,因为我们对
  1369  //记忆在这里。
  1370  		if len(blocks) >= 2048 || memory > 64*1024*1024 {
  1371  			log.Info("Importing heavy sidechain segment", "blocks", len(blocks), "start", blocks[0].NumberU64(), "end", block.NumberU64())
  1372  			if _, _, _, err := bc.insertChain(blocks, false); err != nil {
  1373  				return 0, nil, nil, err
  1374  			}
  1375  			blocks, memory = blocks[:0], 0
  1376  
  1377  //如果链终止,则停止处理块
  1378  			if atomic.LoadInt32(&bc.procInterrupt) == 1 {
  1379  				log.Debug("Premature abort during blocks processing")
  1380  				return 0, nil, nil, nil
  1381  			}
  1382  		}
  1383  	}
  1384  	if len(blocks) > 0 {
  1385  		log.Info("Importing sidechain segment", "start", blocks[0].NumberU64(), "end", blocks[len(blocks)-1].NumberU64())
  1386  		return bc.insertChain(blocks, false)
  1387  	}
  1388  	return 0, nil, nil, nil
  1389  }
  1390  
  1391  //REORG需要两个块,一个旧链和一个新链,并将重建块并插入它们
  1392  //成为新规范链的一部分并累积潜在的丢失事务,然后发布
  1393  //关于他们的事件
  1394  func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
  1395  	var (
  1396  		newChain    types.Blocks
  1397  		oldChain    types.Blocks
  1398  		commonBlock *types.Block
  1399  		deletedTxs  types.Transactions
  1400  		deletedLogs []*types.Log
  1401  //CollectLogs收集在
  1402  //处理与给定哈希对应的块。
  1403  //这些日志随后被宣布为已删除。
  1404  		collectLogs = func(hash common.Hash) {
  1405  //合并日志并设置为“已删除”。
  1406  			number := bc.hc.GetBlockNumber(hash)
  1407  			if number == nil {
  1408  				return
  1409  			}
  1410  			receipts := rawdb.ReadReceipts(bc.db, hash, *number)
  1411  			for _, receipt := range receipts {
  1412  				for _, log := range receipt.Logs {
  1413  					del := *log
  1414  					del.Removed = true
  1415  					deletedLogs = append(deletedLogs, &del)
  1416  				}
  1417  			}
  1418  		}
  1419  	)
  1420  
  1421  //先降低谁是上界
  1422  	if oldBlock.NumberU64() > newBlock.NumberU64() {
  1423  //减少旧链条
  1424  		for ; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1) {
  1425  			oldChain = append(oldChain, oldBlock)
  1426  			deletedTxs = append(deletedTxs, oldBlock.Transactions()...)
  1427  
  1428  			collectLogs(oldBlock.Hash())
  1429  		}
  1430  	} else {
  1431  //减少新的链并附加新的链块以便以后插入
  1432  		for ; newBlock != nil && newBlock.NumberU64() != oldBlock.NumberU64(); newBlock = bc.GetBlock(newBlock.ParentHash(), newBlock.NumberU64()-1) {
  1433  			newChain = append(newChain, newBlock)
  1434  		}
  1435  	}
  1436  	if oldBlock == nil {
  1437  		return fmt.Errorf("Invalid old chain")
  1438  	}
  1439  	if newBlock == nil {
  1440  		return fmt.Errorf("Invalid new chain")
  1441  	}
  1442  
  1443  	for {
  1444  		if oldBlock.Hash() == newBlock.Hash() {
  1445  			commonBlock = oldBlock
  1446  			break
  1447  		}
  1448  
  1449  		oldChain = append(oldChain, oldBlock)
  1450  		newChain = append(newChain, newBlock)
  1451  		deletedTxs = append(deletedTxs, oldBlock.Transactions()...)
  1452  		collectLogs(oldBlock.Hash())
  1453  
  1454  		oldBlock, newBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1), bc.GetBlock(newBlock.ParentHash(), newBlock.NumberU64()-1)
  1455  		if oldBlock == nil {
  1456  			return fmt.Errorf("Invalid old chain")
  1457  		}
  1458  		if newBlock == nil {
  1459  			return fmt.Errorf("Invalid new chain")
  1460  		}
  1461  	}
  1462  //确保用户看到大量的订单
  1463  	if len(oldChain) > 0 && len(newChain) > 0 {
  1464  		logFn := log.Debug
  1465  		if len(oldChain) > 63 {
  1466  			logFn = log.Warn
  1467  		}
  1468  		logFn("Chain split detected", "number", commonBlock.Number(), "hash", commonBlock.Hash(),
  1469  			"drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash())
  1470  	} else {
  1471  		log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "newnum", newBlock.Number(), "newhash", newBlock.Hash())
  1472  	}
  1473  //插入新链条,注意正确的增量顺序
  1474  	var addedTxs types.Transactions
  1475  	for i := len(newChain) - 1; i >= 0; i-- {
  1476  //以规范的方式插入块,重新编写历史记录
  1477  		bc.insert(newChain[i])
  1478  //为基于哈希的交易/收据搜索写入查找条目
  1479  		rawdb.WriteTxLookupEntries(bc.db, newChain[i])
  1480  		addedTxs = append(addedTxs, newChain[i].Transactions()...)
  1481  	}
  1482  //计算已删除和已添加交易记录之间的差额
  1483  	diff := types.TxDifference(deletedTxs, addedTxs)
  1484  //当事务从数据库中删除时,这意味着
  1485  //在fork中创建的收据也必须删除
  1486  	batch := bc.db.NewBatch()
  1487  	for _, tx := range diff {
  1488  		rawdb.DeleteTxLookupEntry(batch, tx.Hash())
  1489  	}
  1490  	batch.Write()
  1491  
  1492  	if len(deletedLogs) > 0 {
  1493  		go bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
  1494  	}
  1495  	if len(oldChain) > 0 {
  1496  		go func() {
  1497  			for _, block := range oldChain {
  1498  				bc.chainSideFeed.Send(ChainSideEvent{Block: block})
  1499  			}
  1500  		}()
  1501  	}
  1502  
  1503  	return nil
  1504  }
  1505  
  1506  //Postchainevents迭代链插入生成的事件,并
  1507  //将它们发布到事件提要中。
  1508  //托多:不应该暴露后遗症。应在WriteBlock中发布链事件。
  1509  func (bc *BlockChain) PostChainEvents(events []interface{}, logs []*types.Log) {
  1510  //发布事件日志以进行进一步处理
  1511  	if logs != nil {
  1512  		bc.logsFeed.Send(logs)
  1513  	}
  1514  	for _, event := range events {
  1515  		switch ev := event.(type) {
  1516  		case ChainEvent:
  1517  			bc.chainFeed.Send(ev)
  1518  
  1519  		case ChainHeadEvent:
  1520  			bc.chainHeadFeed.Send(ev)
  1521  
  1522  		case ChainSideEvent:
  1523  			bc.chainSideFeed.Send(ev)
  1524  		}
  1525  	}
  1526  }
  1527  
  1528  func (bc *BlockChain) update() {
  1529  	futureTimer := time.NewTicker(5 * time.Second)
  1530  	defer futureTimer.Stop()
  1531  	for {
  1532  		select {
  1533  		case <-futureTimer.C:
  1534  			bc.procFutureBlocks()
  1535  		case <-bc.quit:
  1536  			return
  1537  		}
  1538  	}
  1539  }
  1540  
  1541  //bad blocks返回客户端在网络上看到的最后一个“坏块”的列表
  1542  func (bc *BlockChain) BadBlocks() []*types.Block {
  1543  	blocks := make([]*types.Block, 0, bc.badBlocks.Len())
  1544  	for _, hash := range bc.badBlocks.Keys() {
  1545  		if blk, exist := bc.badBlocks.Peek(hash); exist {
  1546  			block := blk.(*types.Block)
  1547  			blocks = append(blocks, block)
  1548  		}
  1549  	}
  1550  	return blocks
  1551  }
  1552  
  1553  //addbadblock向坏块lru缓存添加坏块
  1554  func (bc *BlockChain) addBadBlock(block *types.Block) {
  1555  	bc.badBlocks.Add(block.Hash(), block)
  1556  }
  1557  
  1558  //ReportBlock记录错误的块错误。
  1559  func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) {
  1560  	bc.addBadBlock(block)
  1561  
  1562  	var receiptString string
  1563  	for i, receipt := range receipts {
  1564  		receiptString += fmt.Sprintf("\t %d: cumulative: %v gas: %v contract: %v status: %v tx: %v logs: %v bloom: %x state: %x\n",
  1565  			i, receipt.CumulativeGasUsed, receipt.GasUsed, receipt.ContractAddress.Hex(),
  1566  			receipt.Status, receipt.TxHash.Hex(), receipt.Logs, receipt.Bloom, receipt.PostState)
  1567  	}
  1568  	log.Error(fmt.Sprintf(`
  1569  ########## BAD BLOCK #########
  1570  Chain config: %v
  1571  
  1572  Number: %v
  1573  Hash: 0x%x
  1574  %v
  1575  
  1576  Error: %v
  1577  ##############################
  1578  `, bc.chainConfig, block.Number(), block.Hash(), receiptString, err))
  1579  }
  1580  
  1581  //insert header chain尝试将给定的头链插入本地
  1582  //链,可能创建REORG。如果返回错误,它将返回
  1583  //失败头的索引号以及描述出错原因的错误。
  1584  //
  1585  //verify参数可用于微调非ce验证
  1586  //是否应该做。可选检查背后的原因是
  1587  //其中的头检索机制已经需要验证nonce,以及
  1588  //因为nonce可以被稀疏地验证,不需要检查每一个。
  1589  func (bc *BlockChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
  1590  	start := time.Now()
  1591  	if i, err := bc.hc.ValidateHeaderChain(chain, checkFreq); err != nil {
  1592  		return i, err
  1593  	}
  1594  
  1595  //确保一次只有一个线程操作链
  1596  	bc.chainmu.Lock()
  1597  	defer bc.chainmu.Unlock()
  1598  
  1599  	bc.wg.Add(1)
  1600  	defer bc.wg.Done()
  1601  
  1602  	whFunc := func(header *types.Header) error {
  1603  		_, err := bc.hc.WriteHeader(header)
  1604  		return err
  1605  	}
  1606  	return bc.hc.InsertHeaderChain(chain, whFunc, start)
  1607  }
  1608  
  1609  //当前头检索规范链的当前头。这个
  1610  //从HeaderChain的内部缓存中检索头。
  1611  func (bc *BlockChain) CurrentHeader() *types.Header {
  1612  	return bc.hc.CurrentHeader()
  1613  }
  1614  
  1615  //gettd从
  1616  //按哈希和数字排列的数据库,如果找到,则将其缓存。
  1617  func (bc *BlockChain) GetTd(hash common.Hash, number uint64) *big.Int {
  1618  	return bc.hc.GetTd(hash, number)
  1619  }
  1620  
  1621  //getDByHash从
  1622  //通过哈希对数据库进行缓存(如果找到)。
  1623  func (bc *BlockChain) GetTdByHash(hash common.Hash) *big.Int {
  1624  	return bc.hc.GetTdByHash(hash)
  1625  }
  1626  
  1627  //GetHeader按哈希和数字从数据库中检索块头,
  1628  //如果找到,则缓存它。
  1629  func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header {
  1630  	return bc.hc.GetHeader(hash, number)
  1631  }
  1632  
  1633  //GetHeaderByHash通过哈希从数据库中检索块头,如果
  1634  //找到了。
  1635  func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header {
  1636  	return bc.hc.GetHeaderByHash(hash)
  1637  }
  1638  
  1639  //hasheader检查数据库中是否存在块头,缓存
  1640  //如果存在的话。
  1641  func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
  1642  	return bc.hc.HasHeader(hash, number)
  1643  }
  1644  
  1645  //GetBlockHashesFromHash从给定的
  1646  //哈什,向创世纪街区走去。
  1647  func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
  1648  	return bc.hc.GetBlockHashesFromHash(hash, max)
  1649  }
  1650  
  1651  //getAncestor检索给定块的第n个祖先。它假定给定的块或
  1652  //它的近亲是典型的。maxnoncanonical指向向下计数器,限制
  1653  //到达规范链之前要单独检查的块数。
  1654  //
  1655  //注意:ancestor==0返回相同的块,1返回其父块,依此类推。
  1656  func (bc *BlockChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) {
  1657  	bc.chainmu.RLock()
  1658  	defer bc.chainmu.RUnlock()
  1659  
  1660  	return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical)
  1661  }
  1662  
  1663  //GetHeaderByNumber按编号从数据库中检索块头,
  1664  //如果找到,则缓存它(与其哈希关联)。
  1665  func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header {
  1666  	return bc.hc.GetHeaderByNumber(number)
  1667  }
  1668  
  1669  //config检索区块链的链配置。
  1670  func (bc *BlockChain) Config() *params.ChainConfig { return bc.chainConfig }
  1671  
  1672  //引擎检索区块链的共识引擎。
  1673  func (bc *BlockChain) Engine() consensus.Engine { return bc.engine }
  1674  
  1675  //subscripreMovedLogSevent注册removedLogSevent的订阅。
  1676  func (bc *BlockChain) SubscribeRemovedLogsEvent(ch chan<- RemovedLogsEvent) event.Subscription {
  1677  	return bc.scope.Track(bc.rmLogsFeed.Subscribe(ch))
  1678  }
  1679  
  1680  //subscribeChainevent注册chainEvent的订阅。
  1681  func (bc *BlockChain) SubscribeChainEvent(ch chan<- ChainEvent) event.Subscription {
  1682  	return bc.scope.Track(bc.chainFeed.Subscribe(ch))
  1683  }
  1684  
  1685  //subscribeChainHeadEvent注册chainHeadEvent的订阅。
  1686  func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription {
  1687  	return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
  1688  }
  1689  
  1690  //subscribeChainSideEvent注册chainSideEvent的订阅。
  1691  func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription {
  1692  	return bc.scope.Track(bc.chainSideFeed.Subscribe(ch))
  1693  }
  1694  
  1695  //subscriptLogSevent注册了一个订阅[]*types.log。
  1696  func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
  1697  	return bc.scope.Track(bc.logsFeed.Subscribe(ch))
  1698  }
  1699