github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/headerchain.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2015 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package core
    26  
    27  import (
    28  	crand "crypto/rand"
    29  	"errors"
    30  	"fmt"
    31  	"math"
    32  	"math/big"
    33  	mrand "math/rand"
    34  	"sync/atomic"
    35  	"time"
    36  
    37  	"github.com/ethereum/go-ethereum/common"
    38  	"github.com/ethereum/go-ethereum/consensus"
    39  	"github.com/ethereum/go-ethereum/core/rawdb"
    40  	"github.com/ethereum/go-ethereum/core/types"
    41  	"github.com/ethereum/go-ethereum/ethdb"
    42  	"github.com/ethereum/go-ethereum/log"
    43  	"github.com/ethereum/go-ethereum/params"
    44  	"github.com/hashicorp/golang-lru"
    45  )
    46  
    47  const (
    48  	headerCacheLimit = 512
    49  	tdCacheLimit     = 1024
    50  	numberCacheLimit = 2048
    51  )
    52  
    53  //HeaderChain实现由共享的基本块头链逻辑
    54  //core.blockback和light.lightchain。它本身不可用,只是
    55  //两种结构的一部分。
    56  //它也不是线程安全的,封装链结构应该这样做
    57  //必要的互斥锁/解锁。
    58  type HeaderChain struct {
    59  	config *params.ChainConfig
    60  
    61  	chainDb       ethdb.Database
    62  	genesisHeader *types.Header
    63  
    64  currentHeader     atomic.Value //收割台链条的当前收割台(可能位于区块链上方!)
    65  currentHeaderHash common.Hash  //头链当前头的哈希(禁止随时重新计算)
    66  
    67  headerCache *lru.Cache //缓存最新的块头
    68  tdCache     *lru.Cache //缓存最近的块总困难
    69  numberCache *lru.Cache //缓存最新的块号
    70  
    71  	procInterrupt func() bool
    72  
    73  	rand   *mrand.Rand
    74  	engine consensus.Engine
    75  }
    76  
    77  //新的headerchain创建新的headerchain结构。
    78  //GetValidator应返回父级的验证程序
    79  //procInterrupt指向父级的中断信号量
    80  //wg指向父级的关闭等待组
    81  func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine consensus.Engine, procInterrupt func() bool) (*HeaderChain, error) {
    82  	headerCache, _ := lru.New(headerCacheLimit)
    83  	tdCache, _ := lru.New(tdCacheLimit)
    84  	numberCache, _ := lru.New(numberCacheLimit)
    85  
    86  //设定一个快速但加密的随机生成器
    87  	seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	hc := &HeaderChain{
    93  		config:        config,
    94  		chainDb:       chainDb,
    95  		headerCache:   headerCache,
    96  		tdCache:       tdCache,
    97  		numberCache:   numberCache,
    98  		procInterrupt: procInterrupt,
    99  		rand:          mrand.New(mrand.NewSource(seed.Int64())),
   100  		engine:        engine,
   101  	}
   102  
   103  	hc.genesisHeader = hc.GetHeaderByNumber(0)
   104  	if hc.genesisHeader == nil {
   105  		return nil, ErrNoGenesis
   106  	}
   107  
   108  	hc.currentHeader.Store(hc.genesisHeader)
   109  	if head := rawdb.ReadHeadBlockHash(chainDb); head != (common.Hash{}) {
   110  		if chead := hc.GetHeaderByHash(head); chead != nil {
   111  			hc.currentHeader.Store(chead)
   112  		}
   113  	}
   114  	hc.currentHeaderHash = hc.CurrentHeader().Hash()
   115  
   116  	return hc, nil
   117  }
   118  
   119  //GetBlockNumber检索属于给定哈希的块号
   120  //从缓存或数据库
   121  func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 {
   122  	if cached, ok := hc.numberCache.Get(hash); ok {
   123  		number := cached.(uint64)
   124  		return &number
   125  	}
   126  	number := rawdb.ReadHeaderNumber(hc.chainDb, hash)
   127  	if number != nil {
   128  		hc.numberCache.Add(hash, *number)
   129  	}
   130  	return number
   131  }
   132  
   133  //WRITEHEADER将头写入本地链,因为它的父级是
   134  //已经知道了。如果新插入的标题的总难度变为
   135  //大于当前已知的td,则重新路由规范链。
   136  //
   137  //注意:此方法与同时插入块不同时安全
   138  //在链中,由于无法模拟由重组引起的副作用
   139  //没有真正的街区。因此,只应直接编写头文件
   140  //在两种情况下:纯头段操作模式(轻客户端),或正确
   141  //单独的头段/块阶段(非存档客户端)。
   142  func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, err error) {
   143  //缓存一些值以防止常量重新计算
   144  	var (
   145  		hash   = header.Hash()
   146  		number = header.Number.Uint64()
   147  	)
   148  //计算收割台的总难度
   149  	ptd := hc.GetTd(header.ParentHash, number-1)
   150  	if ptd == nil {
   151  		return NonStatTy, consensus.ErrUnknownAncestor
   152  	}
   153  	localTd := hc.GetTd(hc.currentHeaderHash, hc.CurrentHeader().Number.Uint64())
   154  	externTd := new(big.Int).Add(header.Difficulty, ptd)
   155  
   156  //与规范状态无关,将td和header写入数据库
   157  	if err := hc.WriteTd(hash, number, externTd); err != nil {
   158  		log.Crit("Failed to write header total difficulty", "err", err)
   159  	}
   160  	rawdb.WriteHeader(hc.chainDb, header)
   161  
   162  //如果总的困难比我们已知的要高,就把它加到规范链中去。
   163  //if语句中的第二个子句减少了自私挖掘的脆弱性。
   164  //请参阅http://www.cs.cornell.edu/~ie53/publications/btcrpocfc.pdf
   165  	if externTd.Cmp(localTd) > 0 || (externTd.Cmp(localTd) == 0 && mrand.Float64() < 0.5) {
   166  //删除新标题上方的所有规范编号分配
   167  		batch := hc.chainDb.NewBatch()
   168  		for i := number + 1; ; i++ {
   169  			hash := rawdb.ReadCanonicalHash(hc.chainDb, i)
   170  			if hash == (common.Hash{}) {
   171  				break
   172  			}
   173  			rawdb.DeleteCanonicalHash(batch, i)
   174  		}
   175  		batch.Write()
   176  
   177  //覆盖任何过时的规范编号分配
   178  		var (
   179  			headHash   = header.ParentHash
   180  			headNumber = header.Number.Uint64() - 1
   181  			headHeader = hc.GetHeader(headHash, headNumber)
   182  		)
   183  		for rawdb.ReadCanonicalHash(hc.chainDb, headNumber) != headHash {
   184  			rawdb.WriteCanonicalHash(hc.chainDb, headHash, headNumber)
   185  
   186  			headHash = headHeader.ParentHash
   187  			headNumber = headHeader.Number.Uint64() - 1
   188  			headHeader = hc.GetHeader(headHash, headNumber)
   189  		}
   190  //用新的头扩展规范链
   191  		rawdb.WriteCanonicalHash(hc.chainDb, hash, number)
   192  		rawdb.WriteHeadHeaderHash(hc.chainDb, hash)
   193  
   194  		hc.currentHeaderHash = hash
   195  		hc.currentHeader.Store(types.CopyHeader(header))
   196  
   197  		status = CanonStatTy
   198  	} else {
   199  		status = SideStatTy
   200  	}
   201  
   202  	hc.headerCache.Add(hash, header)
   203  	hc.numberCache.Add(hash, number)
   204  
   205  	return
   206  }
   207  
   208  //whcallback是用于插入单个头的回调函数。
   209  //回调有两个原因:第一,在LightChain中,状态应为
   210  //处理并发送轻链事件,而在区块链中,这不是
   211  //这是必需的,因为在插入块后发送链事件。第二,
   212  //头写入应该由父链互斥体单独保护。
   213  type WhCallback func(*types.Header) error
   214  
   215  func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
   216  //做一个健全的检查,确保提供的链实际上是有序的和链接的
   217  	for i := 1; i < len(chain); i++ {
   218  		if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 || chain[i].ParentHash != chain[i-1].Hash() {
   219  //断链祖先、记录消息(编程错误)和跳过插入
   220  			log.Error("Non contiguous header insert", "number", chain[i].Number, "hash", chain[i].Hash(),
   221  				"parent", chain[i].ParentHash, "prevnumber", chain[i-1].Number, "prevhash", chain[i-1].Hash())
   222  
   223  			return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, chain[i-1].Number,
   224  				chain[i-1].Hash().Bytes()[:4], i, chain[i].Number, chain[i].Hash().Bytes()[:4], chain[i].ParentHash[:4])
   225  		}
   226  	}
   227  
   228  //生成密封验证请求列表,并启动并行验证程序
   229  	seals := make([]bool, len(chain))
   230  	for i := 0; i < len(seals)/checkFreq; i++ {
   231  		index := i*checkFreq + hc.rand.Intn(checkFreq)
   232  		if index >= len(seals) {
   233  			index = len(seals) - 1
   234  		}
   235  		seals[index] = true
   236  	}
   237  seals[len(seals)-1] = true //应始终验证最后一个以避免垃圾
   238  
   239  	abort, results := hc.engine.VerifyHeaders(hc, chain, seals)
   240  	defer close(abort)
   241  
   242  //遍历头并确保它们都签出
   243  	for i, header := range chain {
   244  //如果链终止,则停止处理块
   245  		if hc.procInterrupt() {
   246  			log.Debug("Premature abort during headers verification")
   247  			return 0, errors.New("aborted")
   248  		}
   249  //如果标题是禁止的,直接中止
   250  		if BadHashes[header.Hash()] {
   251  			return i, ErrBlacklistedHash
   252  		}
   253  //否则,等待头检查并确保它们通过
   254  		if err := <-results; err != nil {
   255  			return i, err
   256  		}
   257  	}
   258  
   259  	return 0, nil
   260  }
   261  
   262  //insert header chain尝试将给定的头链插入本地
   263  //链,可能创建REORG。如果返回错误,它将返回
   264  //失败头的索引号以及描述出错原因的错误。
   265  //
   266  //verify参数可用于微调非ce验证
   267  //是否应该做。可选检查背后的原因是
   268  //其中的头检索机制已经需要验证nonce,以及
   269  //因为nonce可以被稀疏地验证,不需要检查每一个。
   270  func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, writeHeader WhCallback, start time.Time) (int, error) {
   271  //收集一些要报告的进口统计数据
   272  	stats := struct{ processed, ignored int }{}
   273  //所有头都通过了验证,将它们导入数据库
   274  	for i, header := range chain {
   275  //关闭时短路插入
   276  		if hc.procInterrupt() {
   277  			log.Debug("Premature abort during headers import")
   278  			return i, errors.New("aborted")
   279  		}
   280  //如果头已经知道,跳过它,否则存储
   281  		if hc.HasHeader(header.Hash(), header.Number.Uint64()) {
   282  			stats.ignored++
   283  			continue
   284  		}
   285  		if err := writeHeader(header); err != nil {
   286  			return i, err
   287  		}
   288  		stats.processed++
   289  	}
   290  //报告一些公共统计数据,这样用户就可以知道发生了什么。
   291  	last := chain[len(chain)-1]
   292  	log.Info("Imported new block headers", "count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
   293  		"number", last.Number, "hash", last.Hash(), "ignored", stats.ignored)
   294  
   295  	return 0, nil
   296  }
   297  
   298  //GetBlockHashesFromHash从给定的
   299  //哈什,向创世纪街区走去。
   300  func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash {
   301  //获取要从中获取的源标题
   302  	header := hc.GetHeaderByHash(hash)
   303  	if header == nil {
   304  		return nil
   305  	}
   306  //重复这些头文件,直到收集到足够的文件或达到创世标准。
   307  	chain := make([]common.Hash, 0, max)
   308  	for i := uint64(0); i < max; i++ {
   309  		next := header.ParentHash
   310  		if header = hc.GetHeader(next, header.Number.Uint64()-1); header == nil {
   311  			break
   312  		}
   313  		chain = append(chain, next)
   314  		if header.Number.Sign() == 0 {
   315  			break
   316  		}
   317  	}
   318  	return chain
   319  }
   320  
   321  //getAncestor检索给定块的第n个祖先。它假定给定的块或
   322  //它的近亲是典型的。maxnoncanonical指向向下计数器,限制
   323  //到达规范链之前要单独检查的块数。
   324  //
   325  //注意:ancestor==0返回相同的块,1返回其父块,依此类推。
   326  func (hc *HeaderChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) {
   327  	if ancestor > number {
   328  		return common.Hash{}, 0
   329  	}
   330  	if ancestor == 1 {
   331  //在这种情况下,只需读取标题就更便宜了
   332  		if header := hc.GetHeader(hash, number); header != nil {
   333  			return header.ParentHash, number - 1
   334  		} else {
   335  			return common.Hash{}, 0
   336  		}
   337  	}
   338  	for ancestor != 0 {
   339  		if rawdb.ReadCanonicalHash(hc.chainDb, number) == hash {
   340  			number -= ancestor
   341  			return rawdb.ReadCanonicalHash(hc.chainDb, number), number
   342  		}
   343  		if *maxNonCanonical == 0 {
   344  			return common.Hash{}, 0
   345  		}
   346  		*maxNonCanonical--
   347  		ancestor--
   348  		header := hc.GetHeader(hash, number)
   349  		if header == nil {
   350  			return common.Hash{}, 0
   351  		}
   352  		hash = header.ParentHash
   353  		number--
   354  	}
   355  	return hash, number
   356  }
   357  
   358  //gettd从
   359  //按哈希和数字排列的数据库,如果找到,则将其缓存。
   360  func (hc *HeaderChain) GetTd(hash common.Hash, number uint64) *big.Int {
   361  //如果td已经在缓存中,则短路,否则检索
   362  	if cached, ok := hc.tdCache.Get(hash); ok {
   363  		return cached.(*big.Int)
   364  	}
   365  	td := rawdb.ReadTd(hc.chainDb, hash, number)
   366  	if td == nil {
   367  		return nil
   368  	}
   369  //缓存下一次找到的正文并返回
   370  	hc.tdCache.Add(hash, td)
   371  	return td
   372  }
   373  
   374  //getDByHash从
   375  //通过哈希对数据库进行缓存(如果找到)。
   376  func (hc *HeaderChain) GetTdByHash(hash common.Hash) *big.Int {
   377  	number := hc.GetBlockNumber(hash)
   378  	if number == nil {
   379  		return nil
   380  	}
   381  	return hc.GetTd(hash, *number)
   382  }
   383  
   384  //writetd将一个块的总难度存储到数据库中,并对其进行缓存
   385  //一路走来。
   386  func (hc *HeaderChain) WriteTd(hash common.Hash, number uint64, td *big.Int) error {
   387  	rawdb.WriteTd(hc.chainDb, hash, number, td)
   388  	hc.tdCache.Add(hash, new(big.Int).Set(td))
   389  	return nil
   390  }
   391  
   392  //GetHeader按哈希和数字从数据库中检索块头,
   393  //如果找到,则缓存它。
   394  func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header {
   395  //如果头已经在缓存中,则短路,否则检索
   396  	if header, ok := hc.headerCache.Get(hash); ok {
   397  		return header.(*types.Header)
   398  	}
   399  	header := rawdb.ReadHeader(hc.chainDb, hash, number)
   400  	if header == nil {
   401  		return nil
   402  	}
   403  //下次缓存找到的头并返回
   404  	hc.headerCache.Add(hash, header)
   405  	return header
   406  }
   407  
   408  //GetHeaderByHash通过哈希从数据库中检索块头,如果
   409  //找到了。
   410  func (hc *HeaderChain) GetHeaderByHash(hash common.Hash) *types.Header {
   411  	number := hc.GetBlockNumber(hash)
   412  	if number == nil {
   413  		return nil
   414  	}
   415  	return hc.GetHeader(hash, *number)
   416  }
   417  
   418  //hasheader检查数据库中是否存在块头。
   419  func (hc *HeaderChain) HasHeader(hash common.Hash, number uint64) bool {
   420  	if hc.numberCache.Contains(hash) || hc.headerCache.Contains(hash) {
   421  		return true
   422  	}
   423  	return rawdb.HasHeader(hc.chainDb, hash, number)
   424  }
   425  
   426  //GetHeaderByNumber按编号从数据库中检索块头,
   427  //如果找到,则缓存它(与其哈希关联)。
   428  func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
   429  	hash := rawdb.ReadCanonicalHash(hc.chainDb, number)
   430  	if hash == (common.Hash{}) {
   431  		return nil
   432  	}
   433  	return hc.GetHeader(hash, number)
   434  }
   435  
   436  //当前头检索规范链的当前头。这个
   437  //从HeaderChain的内部缓存中检索头。
   438  func (hc *HeaderChain) CurrentHeader() *types.Header {
   439  	return hc.currentHeader.Load().(*types.Header)
   440  }
   441  
   442  //setcurrentheader设置规范链的当前头。
   443  func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
   444  	rawdb.WriteHeadHeaderHash(hc.chainDb, head.Hash())
   445  
   446  	hc.currentHeader.Store(head)
   447  	hc.currentHeaderHash = head.Hash()
   448  }
   449  
   450  //deleteCallback是一个回调函数,由sethead在
   451  //删除每个标题。
   452  type DeleteCallback func(rawdb.DatabaseDeleter, common.Hash, uint64)
   453  
   454  //sethead将本地链重绕到新的head。新脑袋上的一切
   455  //将被删除和新的一组。
   456  func (hc *HeaderChain) SetHead(head uint64, delFn DeleteCallback) {
   457  	height := uint64(0)
   458  
   459  	if hdr := hc.CurrentHeader(); hdr != nil {
   460  		height = hdr.Number.Uint64()
   461  	}
   462  	batch := hc.chainDb.NewBatch()
   463  	for hdr := hc.CurrentHeader(); hdr != nil && hdr.Number.Uint64() > head; hdr = hc.CurrentHeader() {
   464  		hash := hdr.Hash()
   465  		num := hdr.Number.Uint64()
   466  		if delFn != nil {
   467  			delFn(batch, hash, num)
   468  		}
   469  		rawdb.DeleteHeader(batch, hash, num)
   470  		rawdb.DeleteTd(batch, hash, num)
   471  
   472  		hc.currentHeader.Store(hc.GetHeader(hdr.ParentHash, hdr.Number.Uint64()-1))
   473  	}
   474  //回滚规范链编号
   475  	for i := height; i > head; i-- {
   476  		rawdb.DeleteCanonicalHash(batch, i)
   477  	}
   478  	batch.Write()
   479  
   480  //从缓存中清除所有过时的内容
   481  	hc.headerCache.Purge()
   482  	hc.tdCache.Purge()
   483  	hc.numberCache.Purge()
   484  
   485  	if hc.CurrentHeader() == nil {
   486  		hc.currentHeader.Store(hc.genesisHeader)
   487  	}
   488  	hc.currentHeaderHash = hc.CurrentHeader().Hash()
   489  
   490  	rawdb.WriteHeadHeaderHash(hc.chainDb, hc.currentHeaderHash)
   491  }
   492  
   493  //setGenesis为链设置新的Genesis块头
   494  func (hc *HeaderChain) SetGenesis(head *types.Header) {
   495  	hc.genesisHeader = head
   496  }
   497  
   498  //config检索头链的链配置。
   499  func (hc *HeaderChain) Config() *params.ChainConfig { return hc.config }
   500  
   501  //引擎检索收割台链的共识引擎。
   502  func (hc *HeaderChain) Engine() consensus.Engine { return hc.engine }
   503  
   504  //getBlock实现consumeration.chainReader,并为每个输入返回nil作为
   505  //标题链没有可供检索的块。
   506  func (hc *HeaderChain) GetBlock(hash common.Hash, number uint64) *types.Block {
   507  	return nil
   508  }