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 }