github.com/immesys/bw2bc@v1.1.0/core/chain_manager.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package core implements the Ethereum consensus protocol. 18 package core 19 20 import ( 21 "errors" 22 "fmt" 23 "io" 24 "math/big" 25 "runtime" 26 "sync" 27 "sync/atomic" 28 "time" 29 30 "github.com/ethereum/go-ethereum/common" 31 "github.com/ethereum/go-ethereum/core/state" 32 "github.com/ethereum/go-ethereum/core/types" 33 "github.com/ethereum/go-ethereum/event" 34 "github.com/ethereum/go-ethereum/logger" 35 "github.com/ethereum/go-ethereum/logger/glog" 36 "github.com/ethereum/go-ethereum/metrics" 37 "github.com/ethereum/go-ethereum/pow" 38 "github.com/hashicorp/golang-lru" 39 ) 40 41 var ( 42 chainlogger = logger.NewLogger("CHAIN") 43 jsonlogger = logger.NewJsonLogger() 44 45 blockInsertTimer = metrics.NewTimer("chain/inserts") 46 47 ErrNoGenesis = errors.New("Genesis not found in chain") 48 ) 49 50 const ( 51 blockCacheLimit = 256 52 maxFutureBlocks = 256 53 maxTimeFutureBlocks = 30 54 checkpointLimit = 200 55 ) 56 57 type ChainManager struct { 58 //eth EthManager 59 chainDb common.Database 60 processor types.BlockProcessor 61 eventMux *event.TypeMux 62 genesisBlock *types.Block 63 // Last known total difficulty 64 mu sync.RWMutex 65 chainmu sync.RWMutex 66 tsmu sync.RWMutex 67 68 checkpoint int // checkpoint counts towards the new checkpoint 69 td *big.Int 70 currentBlock *types.Block 71 lastBlockHash common.Hash 72 currentGasLimit *big.Int 73 74 cache *lru.Cache // cache is the LRU caching 75 futureBlocks *lru.Cache // future blocks are blocks added for later processing 76 77 quit chan struct{} 78 running int32 // running must be called automically 79 // procInterrupt must be atomically called 80 procInterrupt int32 // interrupt signaler for block processing 81 wg sync.WaitGroup 82 83 pow pow.PoW 84 } 85 86 func NewChainManager(chainDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) { 87 cache, _ := lru.New(blockCacheLimit) 88 bc := &ChainManager{ 89 chainDb: chainDb, 90 eventMux: mux, 91 quit: make(chan struct{}), 92 cache: cache, 93 pow: pow, 94 } 95 96 bc.genesisBlock = bc.GetBlockByNumber(0) 97 if bc.genesisBlock == nil { 98 reader, err := NewDefaultGenesisReader() 99 if err != nil { 100 return nil, err 101 } 102 bc.genesisBlock, err = WriteGenesisBlock(chainDb, reader) 103 if err != nil { 104 return nil, err 105 } 106 glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block") 107 } 108 109 if err := bc.setLastState(); err != nil { 110 return nil, err 111 } 112 113 // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain 114 for hash, _ := range BadHashes { 115 if block := bc.GetBlock(hash); block != nil { 116 glog.V(logger.Error).Infof("Found bad hash. Reorganising chain to state %x\n", block.ParentHash().Bytes()[:4]) 117 block = bc.GetBlock(block.ParentHash()) 118 if block == nil { 119 glog.Fatal("Unable to complete. Parent block not found. Corrupted DB?") 120 } 121 bc.SetHead(block) 122 123 glog.V(logger.Error).Infoln("Chain reorg was successfull. Resuming normal operation") 124 } 125 } 126 127 // Take ownership of this particular state 128 129 bc.futureBlocks, _ = lru.New(maxFutureBlocks) 130 bc.makeCache() 131 132 go bc.update() 133 134 return bc, nil 135 } 136 137 func (bc *ChainManager) SetHead(head *types.Block) { 138 bc.mu.Lock() 139 defer bc.mu.Unlock() 140 141 for block := bc.currentBlock; block != nil && block.Hash() != head.Hash(); block = bc.GetBlock(block.ParentHash()) { 142 bc.removeBlock(block) 143 } 144 145 bc.cache, _ = lru.New(blockCacheLimit) 146 bc.currentBlock = head 147 bc.makeCache() 148 149 bc.setTotalDifficulty(head.Td) 150 bc.insert(head) 151 bc.setLastState() 152 } 153 154 func (self *ChainManager) Td() *big.Int { 155 self.mu.RLock() 156 defer self.mu.RUnlock() 157 158 return new(big.Int).Set(self.td) 159 } 160 161 func (self *ChainManager) GasLimit() *big.Int { 162 self.mu.RLock() 163 defer self.mu.RUnlock() 164 165 return self.currentBlock.GasLimit() 166 } 167 168 func (self *ChainManager) LastBlockHash() common.Hash { 169 self.mu.RLock() 170 defer self.mu.RUnlock() 171 172 return self.lastBlockHash 173 } 174 175 func (self *ChainManager) CurrentBlock() *types.Block { 176 self.mu.RLock() 177 defer self.mu.RUnlock() 178 179 return self.currentBlock 180 } 181 182 func (self *ChainManager) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) { 183 self.mu.RLock() 184 defer self.mu.RUnlock() 185 186 return new(big.Int).Set(self.td), self.currentBlock.Hash(), self.genesisBlock.Hash() 187 } 188 189 func (self *ChainManager) SetProcessor(proc types.BlockProcessor) { 190 self.processor = proc 191 } 192 193 func (self *ChainManager) State() *state.StateDB { 194 return state.New(self.CurrentBlock().Root(), self.chainDb) 195 } 196 197 func (bc *ChainManager) recover() bool { 198 data, _ := bc.chainDb.Get([]byte("checkpoint")) 199 if len(data) != 0 { 200 block := bc.GetBlock(common.BytesToHash(data)) 201 if block != nil { 202 err := bc.chainDb.Put([]byte("LastBlock"), block.Hash().Bytes()) 203 if err != nil { 204 glog.Fatalln("db write err:", err) 205 } 206 207 bc.currentBlock = block 208 bc.lastBlockHash = block.Hash() 209 return true 210 } 211 } 212 return false 213 } 214 215 func (bc *ChainManager) setLastState() error { 216 data, _ := bc.chainDb.Get([]byte("LastBlock")) 217 if len(data) != 0 { 218 block := bc.GetBlock(common.BytesToHash(data)) 219 if block != nil { 220 bc.currentBlock = block 221 bc.lastBlockHash = block.Hash() 222 } else { 223 glog.Infof("LastBlock (%x) not found. Recovering...\n", data) 224 if bc.recover() { 225 glog.Infof("Recover successful") 226 } else { 227 glog.Fatalf("Recover failed. Please report") 228 } 229 } 230 } else { 231 bc.Reset() 232 } 233 bc.td = bc.currentBlock.Td 234 bc.currentGasLimit = CalcGasLimit(bc.currentBlock) 235 236 if glog.V(logger.Info) { 237 glog.Infof("Last block (#%v) %x TD=%v\n", bc.currentBlock.Number(), bc.currentBlock.Hash(), bc.td) 238 } 239 240 return nil 241 } 242 243 func (bc *ChainManager) makeCache() { 244 bc.cache, _ = lru.New(blockCacheLimit) 245 // load in last `blockCacheLimit` - 1 blocks. Last block is the current. 246 bc.cache.Add(bc.genesisBlock.Hash(), bc.genesisBlock) 247 for _, block := range bc.GetBlocksFromHash(bc.currentBlock.Hash(), blockCacheLimit) { 248 bc.cache.Add(block.Hash(), block) 249 } 250 } 251 252 func (bc *ChainManager) Reset() { 253 bc.mu.Lock() 254 defer bc.mu.Unlock() 255 256 for block := bc.currentBlock; block != nil; block = bc.GetBlock(block.ParentHash()) { 257 bc.removeBlock(block) 258 } 259 260 bc.cache, _ = lru.New(blockCacheLimit) 261 262 // Prepare the genesis block 263 err := WriteBlock(bc.chainDb, bc.genesisBlock) 264 if err != nil { 265 glog.Fatalln("db err:", err) 266 } 267 268 bc.insert(bc.genesisBlock) 269 bc.currentBlock = bc.genesisBlock 270 bc.makeCache() 271 272 bc.setTotalDifficulty(common.Big("0")) 273 } 274 275 func (bc *ChainManager) removeBlock(block *types.Block) { 276 bc.chainDb.Delete(append(blockHashPre, block.Hash().Bytes()...)) 277 } 278 279 func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) { 280 bc.mu.Lock() 281 defer bc.mu.Unlock() 282 283 for block := bc.currentBlock; block != nil; block = bc.GetBlock(block.ParentHash()) { 284 bc.removeBlock(block) 285 } 286 287 // Prepare the genesis block 288 gb.Td = gb.Difficulty() 289 bc.genesisBlock = gb 290 291 err := WriteBlock(bc.chainDb, bc.genesisBlock) 292 if err != nil { 293 glog.Fatalln("db err:", err) 294 } 295 296 bc.insert(bc.genesisBlock) 297 bc.currentBlock = bc.genesisBlock 298 bc.makeCache() 299 bc.td = gb.Difficulty() 300 } 301 302 // Export writes the active chain to the given writer. 303 func (self *ChainManager) Export(w io.Writer) error { 304 if err := self.ExportN(w, uint64(0), self.currentBlock.NumberU64()); err != nil { 305 return err 306 } 307 return nil 308 } 309 310 // ExportN writes a subset of the active chain to the given writer. 311 func (self *ChainManager) ExportN(w io.Writer, first uint64, last uint64) error { 312 self.mu.RLock() 313 defer self.mu.RUnlock() 314 315 if first > last { 316 return fmt.Errorf("export failed: first (%d) is greater than last (%d)", first, last) 317 } 318 319 glog.V(logger.Info).Infof("exporting %d blocks...\n", last-first+1) 320 321 for nr := first; nr <= last; nr++ { 322 block := self.GetBlockByNumber(nr) 323 if block == nil { 324 return fmt.Errorf("export failed on #%d: not found", nr) 325 } 326 327 if err := block.EncodeRLP(w); err != nil { 328 return err 329 } 330 } 331 332 return nil 333 } 334 335 // insert injects a block into the current chain block chain. Note, this function 336 // assumes that the `mu` mutex is held! 337 func (bc *ChainManager) insert(block *types.Block) { 338 err := WriteHead(bc.chainDb, block) 339 if err != nil { 340 glog.Fatal("db write fail:", err) 341 } 342 343 bc.checkpoint++ 344 if bc.checkpoint > checkpointLimit { 345 err = bc.chainDb.Put([]byte("checkpoint"), block.Hash().Bytes()) 346 if err != nil { 347 glog.Fatal("db write fail:", err) 348 } 349 350 bc.checkpoint = 0 351 } 352 353 bc.currentBlock = block 354 bc.lastBlockHash = block.Hash() 355 } 356 357 // Accessors 358 func (bc *ChainManager) Genesis() *types.Block { 359 return bc.genesisBlock 360 } 361 362 // Block fetching methods 363 func (bc *ChainManager) HasBlock(hash common.Hash) bool { 364 if bc.cache.Contains(hash) { 365 return true 366 } 367 368 data, _ := bc.chainDb.Get(append(blockHashPre, hash[:]...)) 369 return len(data) != 0 370 } 371 372 func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) (chain []common.Hash) { 373 block := self.GetBlock(hash) 374 if block == nil { 375 return 376 } 377 // XXX Could be optimised by using a different database which only holds hashes (i.e., linked list) 378 for i := uint64(0); i < max; i++ { 379 block = self.GetBlock(block.ParentHash()) 380 if block == nil { 381 break 382 } 383 384 chain = append(chain, block.Hash()) 385 if block.Number().Cmp(common.Big0) <= 0 { 386 break 387 } 388 } 389 390 return 391 } 392 393 func (self *ChainManager) GetBlock(hash common.Hash) *types.Block { 394 if block, ok := self.cache.Get(hash); ok { 395 return block.(*types.Block) 396 } 397 398 block := GetBlockByHash(self.chainDb, hash) 399 if block == nil { 400 return nil 401 } 402 403 // Add the block to the cache 404 self.cache.Add(hash, (*types.Block)(block)) 405 406 return (*types.Block)(block) 407 } 408 409 func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { 410 self.mu.RLock() 411 defer self.mu.RUnlock() 412 413 return self.getBlockByNumber(num) 414 415 } 416 417 // GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors. 418 func (self *ChainManager) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) { 419 for i := 0; i < n; i++ { 420 block := self.GetBlock(hash) 421 if block == nil { 422 break 423 } 424 blocks = append(blocks, block) 425 hash = block.ParentHash() 426 } 427 return 428 } 429 430 // non blocking version 431 func (self *ChainManager) getBlockByNumber(num uint64) *types.Block { 432 return GetBlockByNumber(self.chainDb, num) 433 } 434 435 func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncles []*types.Header) { 436 for i := 0; block != nil && i < length; i++ { 437 uncles = append(uncles, block.Uncles()...) 438 block = self.GetBlock(block.ParentHash()) 439 } 440 441 return 442 } 443 444 // setTotalDifficulty updates the TD of the chain manager. Note, this function 445 // assumes that the `mu` mutex is held! 446 func (bc *ChainManager) setTotalDifficulty(td *big.Int) { 447 bc.td = new(big.Int).Set(td) 448 } 449 450 func (bc *ChainManager) Stop() { 451 if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) { 452 return 453 } 454 close(bc.quit) 455 atomic.StoreInt32(&bc.procInterrupt, 1) 456 457 bc.wg.Wait() 458 459 glog.V(logger.Info).Infoln("Chain manager stopped") 460 } 461 462 type queueEvent struct { 463 queue []interface{} 464 canonicalCount int 465 sideCount int 466 splitCount int 467 } 468 469 func (self *ChainManager) procFutureBlocks() { 470 blocks := make([]*types.Block, self.futureBlocks.Len()) 471 for i, hash := range self.futureBlocks.Keys() { 472 block, _ := self.futureBlocks.Get(hash) 473 blocks[i] = block.(*types.Block) 474 } 475 if len(blocks) > 0 { 476 types.BlockBy(types.Number).Sort(blocks) 477 self.InsertChain(blocks) 478 } 479 } 480 481 type writeStatus byte 482 483 const ( 484 NonStatTy writeStatus = iota 485 CanonStatTy 486 SplitStatTy 487 SideStatTy 488 ) 489 490 // WriteBlock writes the block to the chain (or pending queue) 491 func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status writeStatus, err error) { 492 self.wg.Add(1) 493 defer self.wg.Done() 494 495 cblock := self.currentBlock 496 // Compare the TD of the last known block in the canonical chain to make sure it's greater. 497 // At this point it's possible that a different chain (fork) becomes the new canonical chain. 498 if block.Td.Cmp(self.Td()) > 0 { 499 // chain fork 500 if block.ParentHash() != cblock.Hash() { 501 // during split we merge two different chains and create the new canonical chain 502 err := self.merge(cblock, block) 503 if err != nil { 504 return NonStatTy, err 505 } 506 507 status = SplitStatTy 508 } 509 510 self.mu.Lock() 511 self.setTotalDifficulty(block.Td) 512 self.insert(block) 513 self.mu.Unlock() 514 515 status = CanonStatTy 516 } else { 517 status = SideStatTy 518 } 519 520 err = WriteBlock(self.chainDb, block) 521 if err != nil { 522 glog.Fatalln("db err:", err) 523 } 524 // Delete from future blocks 525 self.futureBlocks.Remove(block.Hash()) 526 527 return 528 } 529 530 // InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned 531 // it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go). 532 func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { 533 self.wg.Add(1) 534 defer self.wg.Done() 535 536 self.chainmu.Lock() 537 defer self.chainmu.Unlock() 538 539 // A queued approach to delivering events. This is generally 540 // faster than direct delivery and requires much less mutex 541 // acquiring. 542 var ( 543 queue = make([]interface{}, len(chain)) 544 queueEvent = queueEvent{queue: queue} 545 stats struct{ queued, processed, ignored int } 546 tstart = time.Now() 547 548 nonceDone = make(chan nonceResult, len(chain)) 549 nonceQuit = make(chan struct{}) 550 nonceChecked = make([]bool, len(chain)) 551 ) 552 553 // Start the parallel nonce verifier. 554 go verifyNonces(self.pow, chain, nonceQuit, nonceDone) 555 defer close(nonceQuit) 556 557 txcount := 0 558 for i, block := range chain { 559 if atomic.LoadInt32(&self.procInterrupt) == 1 { 560 glog.V(logger.Debug).Infoln("Premature abort during chain processing") 561 break 562 } 563 564 bstart := time.Now() 565 // Wait for block i's nonce to be verified before processing 566 // its state transition. 567 for !nonceChecked[i] { 568 r := <-nonceDone 569 nonceChecked[r.i] = true 570 if !r.valid { 571 block := chain[r.i] 572 return r.i, &BlockNonceErr{Hash: block.Hash(), Number: block.Number(), Nonce: block.Nonce()} 573 } 574 } 575 576 if BadHashes[block.Hash()] { 577 err := fmt.Errorf("Found known bad hash in chain %x", block.Hash()) 578 blockErr(block, err) 579 return i, err 580 } 581 582 // Setting block.Td regardless of error (known for example) prevents errors down the line 583 // in the protocol handler 584 block.Td = new(big.Int).Set(CalcTD(block, self.GetBlock(block.ParentHash()))) 585 586 // Call in to the block processor and check for errors. It's likely that if one block fails 587 // all others will fail too (unless a known block is returned). 588 logs, receipts, err := self.processor.Process(block) 589 if err != nil { 590 if IsKnownBlockErr(err) { 591 stats.ignored++ 592 continue 593 } 594 595 if err == BlockFutureErr { 596 // Allow up to MaxFuture second in the future blocks. If this limit 597 // is exceeded the chain is discarded and processed at a later time 598 // if given. 599 max := big.NewInt(time.Now().Unix() + maxTimeFutureBlocks) 600 if block.Time().Cmp(max) == 1 { 601 return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max) 602 } 603 604 self.futureBlocks.Add(block.Hash(), block) 605 stats.queued++ 606 continue 607 } 608 609 if IsParentErr(err) && self.futureBlocks.Contains(block.ParentHash()) { 610 self.futureBlocks.Add(block.Hash(), block) 611 stats.queued++ 612 continue 613 } 614 615 blockErr(block, err) 616 617 go ReportBlock(block, err) 618 619 return i, err 620 } 621 622 txcount += len(block.Transactions()) 623 624 // write the block to the chain and get the status 625 status, err := self.WriteBlock(block, true) 626 if err != nil { 627 return i, err 628 } 629 switch status { 630 case CanonStatTy: 631 if glog.V(logger.Debug) { 632 glog.Infof("[%v] inserted block #%d (%d TXs %v G %d UNCs) (%x...). Took %v\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), block.GasUsed(), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart)) 633 } 634 queue[i] = ChainEvent{block, block.Hash(), logs} 635 queueEvent.canonicalCount++ 636 637 // This puts transactions in a extra db for rpc 638 PutTransactions(self.chainDb, block, block.Transactions()) 639 // store the receipts 640 PutReceipts(self.chainDb, receipts) 641 case SideStatTy: 642 if glog.V(logger.Detail) { 643 glog.Infof("inserted forked block #%d (TD=%v) (%d TXs %d UNCs) (%x...). Took %v\n", block.Number(), block.Difficulty(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart)) 644 } 645 queue[i] = ChainSideEvent{block, logs} 646 queueEvent.sideCount++ 647 case SplitStatTy: 648 queue[i] = ChainSplitEvent{block, logs} 649 queueEvent.splitCount++ 650 } 651 if err := PutBlockReceipts(self.chainDb, block, receipts); err != nil { 652 glog.V(logger.Warn).Infoln("error writing block receipts:", err) 653 } 654 655 stats.processed++ 656 } 657 658 if (stats.queued > 0 || stats.processed > 0 || stats.ignored > 0) && bool(glog.V(logger.Info)) { 659 tend := time.Since(tstart) 660 start, end := chain[0], chain[len(chain)-1] 661 glog.Infof("imported %d block(s) (%d queued %d ignored) including %d txs in %v. #%v [%x / %x]\n", stats.processed, stats.queued, stats.ignored, txcount, tend, end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4]) 662 } 663 664 go self.eventMux.Post(queueEvent) 665 666 return 0, nil 667 } 668 669 // diff takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them 670 // to be part of the new canonical chain. 671 func (self *ChainManager) diff(oldBlock, newBlock *types.Block) (types.Blocks, error) { 672 var ( 673 newChain types.Blocks 674 commonBlock *types.Block 675 oldStart = oldBlock 676 newStart = newBlock 677 ) 678 679 // first reduce whoever is higher bound 680 if oldBlock.NumberU64() > newBlock.NumberU64() { 681 // reduce old chain 682 for oldBlock = oldBlock; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = self.GetBlock(oldBlock.ParentHash()) { 683 } 684 } else { 685 // reduce new chain and append new chain blocks for inserting later on 686 for newBlock = newBlock; newBlock != nil && newBlock.NumberU64() != oldBlock.NumberU64(); newBlock = self.GetBlock(newBlock.ParentHash()) { 687 newChain = append(newChain, newBlock) 688 } 689 } 690 if oldBlock == nil { 691 return nil, fmt.Errorf("Invalid old chain") 692 } 693 if newBlock == nil { 694 return nil, fmt.Errorf("Invalid new chain") 695 } 696 697 numSplit := newBlock.Number() 698 for { 699 if oldBlock.Hash() == newBlock.Hash() { 700 commonBlock = oldBlock 701 break 702 } 703 newChain = append(newChain, newBlock) 704 705 oldBlock, newBlock = self.GetBlock(oldBlock.ParentHash()), self.GetBlock(newBlock.ParentHash()) 706 if oldBlock == nil { 707 return nil, fmt.Errorf("Invalid old chain") 708 } 709 if newBlock == nil { 710 return nil, fmt.Errorf("Invalid new chain") 711 } 712 } 713 714 if glog.V(logger.Debug) { 715 commonHash := commonBlock.Hash() 716 glog.Infof("Chain split detected @ %x. Reorganising chain from #%v %x to %x", commonHash[:4], numSplit, oldStart.Hash().Bytes()[:4], newStart.Hash().Bytes()[:4]) 717 } 718 719 return newChain, nil 720 } 721 722 // merge merges two different chain to the new canonical chain 723 func (self *ChainManager) merge(oldBlock, newBlock *types.Block) error { 724 newChain, err := self.diff(oldBlock, newBlock) 725 if err != nil { 726 return fmt.Errorf("chain reorg failed: %v", err) 727 } 728 729 // insert blocks. Order does not matter. Last block will be written in ImportChain itself which creates the new head properly 730 self.mu.Lock() 731 for _, block := range newChain { 732 // insert the block in the canonical way, re-writing history 733 self.insert(block) 734 // write canonical receipts and transactions 735 PutTransactions(self.chainDb, block, block.Transactions()) 736 PutReceipts(self.chainDb, GetBlockReceipts(self.chainDb, block.Hash())) 737 738 } 739 self.mu.Unlock() 740 741 return nil 742 } 743 744 func (self *ChainManager) update() { 745 events := self.eventMux.Subscribe(queueEvent{}) 746 futureTimer := time.Tick(5 * time.Second) 747 out: 748 for { 749 select { 750 case ev := <-events.Chan(): 751 switch ev := ev.(type) { 752 case queueEvent: 753 for _, event := range ev.queue { 754 switch event := event.(type) { 755 case ChainEvent: 756 // We need some control over the mining operation. Acquiring locks and waiting for the miner to create new block takes too long 757 // and in most cases isn't even necessary. 758 if self.lastBlockHash == event.Hash { 759 self.currentGasLimit = CalcGasLimit(event.Block) 760 self.eventMux.Post(ChainHeadEvent{event.Block}) 761 } 762 } 763 764 self.eventMux.Post(event) 765 } 766 } 767 case <-futureTimer: 768 self.procFutureBlocks() 769 case <-self.quit: 770 break out 771 } 772 } 773 } 774 775 func blockErr(block *types.Block, err error) { 776 h := block.Header() 777 glog.V(logger.Error).Infof("Bad block #%v (%x)\n", h.Number, h.Hash().Bytes()) 778 glog.V(logger.Error).Infoln(err) 779 glog.V(logger.Debug).Infoln(verifyNonces) 780 } 781 782 type nonceResult struct { 783 i int 784 valid bool 785 } 786 787 // block verifies nonces of the given blocks in parallel and returns 788 // an error if one of the blocks nonce verifications failed. 789 func verifyNonces(pow pow.PoW, blocks []*types.Block, quit <-chan struct{}, done chan<- nonceResult) { 790 // Spawn a few workers. They listen for blocks on the in channel 791 // and send results on done. The workers will exit in the 792 // background when in is closed. 793 var ( 794 in = make(chan int) 795 nworkers = runtime.GOMAXPROCS(0) 796 ) 797 defer close(in) 798 if len(blocks) < nworkers { 799 nworkers = len(blocks) 800 } 801 for i := 0; i < nworkers; i++ { 802 go func() { 803 for i := range in { 804 done <- nonceResult{i: i, valid: pow.Verify(blocks[i])} 805 } 806 }() 807 } 808 // Feed block indices to the workers. 809 for i := range blocks { 810 select { 811 case in <- i: 812 continue 813 case <-quit: 814 return 815 } 816 } 817 }