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(¤tBlock); 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