github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/light/lightchain.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:39</date> 10 //</624450096355872768> 11 12 13 package light 14 15 import ( 16 "context" 17 "errors" 18 "math/big" 19 "sync" 20 "sync/atomic" 21 "time" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/consensus" 25 "github.com/ethereum/go-ethereum/core" 26 "github.com/ethereum/go-ethereum/core/rawdb" 27 "github.com/ethereum/go-ethereum/core/state" 28 "github.com/ethereum/go-ethereum/core/types" 29 "github.com/ethereum/go-ethereum/ethdb" 30 "github.com/ethereum/go-ethereum/event" 31 "github.com/ethereum/go-ethereum/log" 32 "github.com/ethereum/go-ethereum/params" 33 "github.com/ethereum/go-ethereum/rlp" 34 "github.com/hashicorp/golang-lru" 35 ) 36 37 var ( 38 bodyCacheLimit = 256 39 blockCacheLimit = 256 40 ) 41 42 //lightchain表示默认情况下只处理块的规范链 43 //通过ODR按需下载块体和收据。 44 //接口。它只在链插入期间进行头验证。 45 type LightChain struct { 46 hc *core.HeaderChain 47 indexerConfig *IndexerConfig 48 chainDb ethdb.Database 49 odr OdrBackend 50 chainFeed event.Feed 51 chainSideFeed event.Feed 52 chainHeadFeed event.Feed 53 scope event.SubscriptionScope 54 genesisBlock *types.Block 55 56 chainmu sync.RWMutex 57 58 bodyCache *lru.Cache //缓存最新的块体 59 bodyRLPCache *lru.Cache //以rlp编码格式缓存最新的块体 60 blockCache *lru.Cache //缓存最近的整个块 61 62 quit chan struct{} 63 running int32 //必须自动调用running 64 //必须原子地调用ProcInterrupt 65 procInterrupt int32 //用于块处理的中断信号器 66 wg sync.WaitGroup 67 68 engine consensus.Engine 69 } 70 71 //newlightchain使用信息返回完全初始化的光链 72 //在数据库中可用。它初始化默认的以太坊头文件 73 //验证器。 74 func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.Engine) (*LightChain, error) { 75 bodyCache, _ := lru.New(bodyCacheLimit) 76 bodyRLPCache, _ := lru.New(bodyCacheLimit) 77 blockCache, _ := lru.New(blockCacheLimit) 78 79 bc := &LightChain{ 80 chainDb: odr.Database(), 81 indexerConfig: odr.IndexerConfig(), 82 odr: odr, 83 quit: make(chan struct{}), 84 bodyCache: bodyCache, 85 bodyRLPCache: bodyRLPCache, 86 blockCache: blockCache, 87 engine: engine, 88 } 89 var err error 90 bc.hc, err = core.NewHeaderChain(odr.Database(), config, bc.engine, bc.getProcInterrupt) 91 if err != nil { 92 return nil, err 93 } 94 bc.genesisBlock, _ = bc.GetBlockByNumber(NoOdr, 0) 95 if bc.genesisBlock == nil { 96 return nil, core.ErrNoGenesis 97 } 98 if cp, ok := trustedCheckpoints[bc.genesisBlock.Hash()]; ok { 99 bc.addTrustedCheckpoint(cp) 100 } 101 if err := bc.loadLastState(); err != nil { 102 return nil, err 103 } 104 //检查块哈希的当前状态,确保链中没有任何坏块 105 for hash := range core.BadHashes { 106 if header := bc.GetHeaderByHash(hash); header != nil { 107 log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash) 108 bc.SetHead(header.Number.Uint64() - 1) 109 log.Error("Chain rewind was successful, resuming normal operation") 110 } 111 } 112 return bc, nil 113 } 114 115 //AddTrustedCheckpoint向区块链添加受信任的检查点 116 func (self *LightChain) addTrustedCheckpoint(cp *params.TrustedCheckpoint) { 117 if self.odr.ChtIndexer() != nil { 118 StoreChtRoot(self.chainDb, cp.SectionIndex, cp.SectionHead, cp.CHTRoot) 119 self.odr.ChtIndexer().AddCheckpoint(cp.SectionIndex, cp.SectionHead) 120 } 121 if self.odr.BloomTrieIndexer() != nil { 122 StoreBloomTrieRoot(self.chainDb, cp.SectionIndex, cp.SectionHead, cp.BloomRoot) 123 self.odr.BloomTrieIndexer().AddCheckpoint(cp.SectionIndex, cp.SectionHead) 124 } 125 if self.odr.BloomIndexer() != nil { 126 self.odr.BloomIndexer().AddCheckpoint(cp.SectionIndex, cp.SectionHead) 127 } 128 log.Info("Added trusted checkpoint", "chain", cp.Name, "block", (cp.SectionIndex+1)*self.indexerConfig.ChtSize-1, "hash", cp.SectionHead) 129 } 130 131 func (self *LightChain) getProcInterrupt() bool { 132 return atomic.LoadInt32(&self.procInterrupt) == 1 133 } 134 135 //ODR返回链的ODR后端 136 func (self *LightChain) Odr() OdrBackend { 137 return self.odr 138 } 139 140 //loadLastState从数据库加载最后一个已知的链状态。这种方法 141 //假定保持链管理器互斥锁。 142 func (self *LightChain) loadLastState() error { 143 if head := rawdb.ReadHeadHeaderHash(self.chainDb); head == (common.Hash{}) { 144 //数据库已损坏或为空,从头开始初始化 145 self.Reset() 146 } else { 147 if header := self.GetHeaderByHash(head); header != nil { 148 self.hc.SetCurrentHeader(header) 149 } 150 } 151 152 //发布状态日志并返回 153 header := self.hc.CurrentHeader() 154 headerTd := self.GetTd(header.Hash(), header.Number.Uint64()) 155 log.Info("Loaded most recent local header", "number", header.Number, "hash", header.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(header.Time.Int64(), 0))) 156 157 return nil 158 } 159 160 //sethead将本地链重绕到新的head。一切都在新的之上 161 //头将被删除,新的一套。 162 func (bc *LightChain) SetHead(head uint64) { 163 bc.chainmu.Lock() 164 defer bc.chainmu.Unlock() 165 166 bc.hc.SetHead(head, nil) 167 bc.loadLastState() 168 } 169 170 //gas limit返回当前头块的气体限制。 171 func (self *LightChain) GasLimit() uint64 { 172 return self.hc.CurrentHeader().GasLimit 173 } 174 175 //重置清除整个区块链,将其恢复到其创始状态。 176 func (bc *LightChain) Reset() { 177 bc.ResetWithGenesisBlock(bc.genesisBlock) 178 } 179 180 //ResetWithGenerisBlock清除整个区块链,将其恢复到 181 //指定的创世状态。 182 func (bc *LightChain) ResetWithGenesisBlock(genesis *types.Block) { 183 //转储整个块链并清除缓存 184 bc.SetHead(0) 185 186 bc.chainmu.Lock() 187 defer bc.chainmu.Unlock() 188 189 //准备Genesis块并重新初始化链 190 rawdb.WriteTd(bc.chainDb, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()) 191 rawdb.WriteBlock(bc.chainDb, genesis) 192 193 bc.genesisBlock = genesis 194 bc.hc.SetGenesis(bc.genesisBlock.Header()) 195 bc.hc.SetCurrentHeader(bc.genesisBlock.Header()) 196 } 197 198 //访问器 199 200 //引擎检索轻链的共识引擎。 201 func (bc *LightChain) Engine() consensus.Engine { return bc.engine } 202 203 //Genesis返回Genesis块 204 func (bc *LightChain) Genesis() *types.Block { 205 return bc.genesisBlock 206 } 207 208 //State返回基于当前头块的新可变状态。 209 func (bc *LightChain) State() (*state.StateDB, error) { 210 return nil, errors.New("not implemented, needs client/server interface split") 211 } 212 213 //getbody从数据库中检索块体(事务和uncles) 214 //或者通过散列来实现ODR服务,如果找到了,就缓存它。 215 func (self *LightChain) GetBody(ctx context.Context, hash common.Hash) (*types.Body, error) { 216 //如果主体已在缓存中,则短路,否则检索 217 if cached, ok := self.bodyCache.Get(hash); ok { 218 body := cached.(*types.Body) 219 return body, nil 220 } 221 number := self.hc.GetBlockNumber(hash) 222 if number == nil { 223 return nil, errors.New("unknown block") 224 } 225 body, err := GetBody(ctx, self.odr, hash, *number) 226 if err != nil { 227 return nil, err 228 } 229 //缓存下一次找到的正文并返回 230 self.bodyCache.Add(hash, body) 231 return body, nil 232 } 233 234 //getBodyrlp从数据库中检索以rlp编码的块体,或者 235 //通过哈希的ODR服务,如果找到,将其缓存。 236 func (self *LightChain) GetBodyRLP(ctx context.Context, hash common.Hash) (rlp.RawValue, error) { 237 //如果主体已在缓存中,则短路,否则检索 238 if cached, ok := self.bodyRLPCache.Get(hash); ok { 239 return cached.(rlp.RawValue), nil 240 } 241 number := self.hc.GetBlockNumber(hash) 242 if number == nil { 243 return nil, errors.New("unknown block") 244 } 245 body, err := GetBodyRLP(ctx, self.odr, hash, *number) 246 if err != nil { 247 return nil, err 248 } 249 //缓存下一次找到的正文并返回 250 self.bodyRLPCache.Add(hash, body) 251 return body, nil 252 } 253 254 //HasBlock checks if a block is fully present in the database or not, caching 255 //如果存在的话。 256 func (bc *LightChain) HasBlock(hash common.Hash, number uint64) bool { 257 blk, _ := bc.GetBlock(NoOdr, hash, number) 258 return blk != nil 259 } 260 261 //GetBlock通过哈希和数字从数据库或ODR服务中检索块, 262 //如果找到,则缓存它。 263 func (self *LightChain) GetBlock(ctx context.Context, hash common.Hash, number uint64) (*types.Block, error) { 264 //如果块已在缓存中,则短路,否则检索 265 if block, ok := self.blockCache.Get(hash); ok { 266 return block.(*types.Block), nil 267 } 268 block, err := GetBlock(ctx, self.odr, hash, number) 269 if err != nil { 270 return nil, err 271 } 272 //下次缓存找到的块并返回 273 self.blockCache.Add(block.Hash(), block) 274 return block, nil 275 } 276 277 //GetBlockByHash通过哈希从数据库或ODR服务中检索块, 278 //如果找到,则缓存它。 279 func (self *LightChain) GetBlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 280 number := self.hc.GetBlockNumber(hash) 281 if number == nil { 282 return nil, errors.New("unknown block") 283 } 284 return self.GetBlock(ctx, hash, *number) 285 } 286 287 //GetBlockByNumber通过以下方式从数据库或ODR服务中检索块 288 //数字,如果找到,则缓存它(与其哈希关联)。 289 func (self *LightChain) GetBlockByNumber(ctx context.Context, number uint64) (*types.Block, error) { 290 hash, err := GetCanonicalHash(ctx, self.odr, number) 291 if hash == (common.Hash{}) || err != nil { 292 return nil, err 293 } 294 return self.GetBlock(ctx, hash, number) 295 } 296 297 //停止停止区块链服务。如果任何导入当前正在进行中 298 //它将使用procInterrupt中止它们。 299 func (bc *LightChain) Stop() { 300 if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) { 301 return 302 } 303 close(bc.quit) 304 atomic.StoreInt32(&bc.procInterrupt, 1) 305 306 bc.wg.Wait() 307 log.Info("Blockchain manager stopped") 308 } 309 310 //回滚的目的是从数据库中删除一系列链接,而这些链接不是 311 //足够确定有效。 312 func (self *LightChain) Rollback(chain []common.Hash) { 313 self.chainmu.Lock() 314 defer self.chainmu.Unlock() 315 316 for i := len(chain) - 1; i >= 0; i-- { 317 hash := chain[i] 318 319 if head := self.hc.CurrentHeader(); head.Hash() == hash { 320 self.hc.SetCurrentHeader(self.GetHeader(head.ParentHash, head.Number.Uint64()-1)) 321 } 322 } 323 } 324 325 //Postchainevents迭代链插入生成的事件,并 326 //将它们发布到事件提要中。 327 func (self *LightChain) postChainEvents(events []interface{}) { 328 for _, event := range events { 329 switch ev := event.(type) { 330 case core.ChainEvent: 331 if self.CurrentHeader().Hash() == ev.Hash { 332 self.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block}) 333 } 334 self.chainFeed.Send(ev) 335 case core.ChainSideEvent: 336 self.chainSideFeed.Send(ev) 337 } 338 } 339 } 340 341 //insert header chain尝试将给定的头链插入本地 342 //链,可能创建REORG。如果返回错误,它将返回 343 //失败头的索引号以及描述出错原因的错误。 344 // 345 //verify参数可用于微调非ce验证 346 //是否应该做。可选检查背后的原因是 347 //其中的头检索机制已经需要验证nonce,以及 348 //因为nonce可以被稀疏地验证,不需要检查每一个。 349 // 350 //对于光链,插入头链也创建和发布光 351 //必要时链接事件。 352 func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) { 353 start := time.Now() 354 if i, err := self.hc.ValidateHeaderChain(chain, checkFreq); err != nil { 355 return i, err 356 } 357 358 //确保一次只有一个线程操作链 359 self.chainmu.Lock() 360 defer self.chainmu.Unlock() 361 362 self.wg.Add(1) 363 defer self.wg.Done() 364 365 var events []interface{} 366 whFunc := func(header *types.Header) error { 367 status, err := self.hc.WriteHeader(header) 368 369 switch status { 370 case core.CanonStatTy: 371 log.Debug("Inserted new header", "number", header.Number, "hash", header.Hash()) 372 events = append(events, core.ChainEvent{Block: types.NewBlockWithHeader(header), Hash: header.Hash()}) 373 374 case core.SideStatTy: 375 log.Debug("Inserted forked header", "number", header.Number, "hash", header.Hash()) 376 events = append(events, core.ChainSideEvent{Block: types.NewBlockWithHeader(header)}) 377 } 378 return err 379 } 380 i, err := self.hc.InsertHeaderChain(chain, whFunc, start) 381 self.postChainEvents(events) 382 return i, err 383 } 384 385 //当前头检索规范链的当前头。这个 386 //从HeaderChain的内部缓存中检索头。 387 func (self *LightChain) CurrentHeader() *types.Header { 388 return self.hc.CurrentHeader() 389 } 390 391 //gettd从 392 //按哈希和数字排列的数据库,如果找到,则将其缓存。 393 func (self *LightChain) GetTd(hash common.Hash, number uint64) *big.Int { 394 return self.hc.GetTd(hash, number) 395 } 396 397 //getDByHash从 398 //通过哈希对数据库进行缓存(如果找到)。 399 func (self *LightChain) GetTdByHash(hash common.Hash) *big.Int { 400 return self.hc.GetTdByHash(hash) 401 } 402 403 //GetHeader按哈希和数字从数据库中检索块头, 404 //如果找到,则缓存它。 405 func (self *LightChain) GetHeader(hash common.Hash, number uint64) *types.Header { 406 return self.hc.GetHeader(hash, number) 407 } 408 409 //GetHeaderByHash通过哈希从数据库中检索块头,如果 410 //找到了。 411 func (self *LightChain) GetHeaderByHash(hash common.Hash) *types.Header { 412 return self.hc.GetHeaderByHash(hash) 413 } 414 415 //hasheader检查数据库中是否存在块头,缓存 416 //如果存在的话。 417 func (bc *LightChain) HasHeader(hash common.Hash, number uint64) bool { 418 return bc.hc.HasHeader(hash, number) 419 } 420 421 //GetBlockHashesFromHash从给定的 422 //哈什,向创世纪街区走去。 423 func (self *LightChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []common.Hash { 424 return self.hc.GetBlockHashesFromHash(hash, max) 425 } 426 427 //getAncestor检索给定块的第n个祖先。它假定给定的块或 428 //它的近亲是典型的。maxnoncanonical指向向下计数器,限制 429 //到达规范链之前要单独检查的块数。 430 // 431 //注意:ancestor==0返回相同的块,1返回其父块,依此类推。 432 func (bc *LightChain) GetAncestor(hash common.Hash, number, ancestor uint64, maxNonCanonical *uint64) (common.Hash, uint64) { 433 bc.chainmu.RLock() 434 defer bc.chainmu.RUnlock() 435 436 return bc.hc.GetAncestor(hash, number, ancestor, maxNonCanonical) 437 } 438 439 //GetHeaderByNumber按编号从数据库中检索块头, 440 //如果找到,则缓存它(与其哈希关联)。 441 func (self *LightChain) GetHeaderByNumber(number uint64) *types.Header { 442 return self.hc.GetHeaderByNumber(number) 443 } 444 445 //GetHeaderByNumberODR从数据库或网络检索块头 446 //按数字,如果找到,则缓存它(与其哈希关联)。 447 func (self *LightChain) GetHeaderByNumberOdr(ctx context.Context, number uint64) (*types.Header, error) { 448 if header := self.hc.GetHeaderByNumber(number); header != nil { 449 return header, nil 450 } 451 return GetHeaderByNumber(ctx, self.odr, number) 452 } 453 454 //config检索头链的链配置。 455 func (self *LightChain) Config() *params.ChainConfig { return self.hc.Config() } 456 457 func (self *LightChain) SyncCht(ctx context.Context) bool { 458 //如果没有CHT索引器,请中止 459 if self.odr.ChtIndexer() == nil { 460 return false 461 } 462 //确保远程CHT头在我们前面 463 head := self.CurrentHeader().Number.Uint64() 464 sections, _, _ := self.odr.ChtIndexer().Sections() 465 466 latest := sections*self.indexerConfig.ChtSize - 1 467 if clique := self.hc.Config().Clique; clique != nil { 468 latest -= latest % clique.Epoch //集团的时代快照 469 } 470 if head >= latest { 471 return false 472 } 473 //检索最新的有用头并对其进行更新 474 if header, err := GetHeaderByNumber(ctx, self.odr, latest); header != nil && err == nil { 475 self.chainmu.Lock() 476 defer self.chainmu.Unlock() 477 478 //确保链条在检索时没有移动过最新的块。 479 if self.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() { 480 log.Info("Updated latest header based on CHT", "number", header.Number, "hash", header.Hash(), "age", common.PrettyAge(time.Unix(header.Time.Int64(), 0))) 481 self.hc.SetCurrentHeader(header) 482 } 483 return true 484 } 485 return false 486 } 487 488 //lockchain为读取而锁定链互斥体,以便可以 489 //在确保它们属于同一版本的链时检索 490 func (self *LightChain) LockChain() { 491 self.chainmu.RLock() 492 } 493 494 //解锁链解锁链互斥体 495 func (self *LightChain) UnlockChain() { 496 self.chainmu.RUnlock() 497 } 498 499 //subscribeChainevent注册chainEvent的订阅。 500 func (self *LightChain) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { 501 return self.scope.Track(self.chainFeed.Subscribe(ch)) 502 } 503 504 //subscribeChainHeadEvent注册chainHeadEvent的订阅。 505 func (self *LightChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { 506 return self.scope.Track(self.chainHeadFeed.Subscribe(ch)) 507 } 508 509 //subscribeChainSideEvent注册chainSideEvent的订阅。 510 func (self *LightChain) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { 511 return self.scope.Track(self.chainSideFeed.Subscribe(ch)) 512 } 513 514 //subscriptLogSevent实现了filters.backend的接口 515 //LightChain不发送日志事件,因此返回空订阅。 516 func (self *LightChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 517 return self.scope.Track(new(event.Feed).Subscribe(ch)) 518 } 519 520 //subscripreMovedLogSevent实现筛选器的接口。后端 521 //LightChain不发送core.removedLogSevent,因此返回空订阅。 522 func (self *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { 523 return self.scope.Track(new(event.Feed).Subscribe(ch)) 524 } 525