core: fix block canonical mark / content write race
This commit is contained in:
		| @@ -601,7 +601,7 @@ func (self *BlockChain) writeHeader(header *types.Header) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| // InsertHeaderChain will attempt to insert the given header chain in to the | // InsertHeaderChain will attempt to insert the given header chain in to the | ||||||
| // local chain, possibly creating a dork. If an error is returned,  it will | // local chain, possibly creating a fork. If an error is returned,  it will | ||||||
| // return the index number of the failing header as well an error describing | // return the index number of the failing header as well an error describing | ||||||
| // what went wrong. | // what went wrong. | ||||||
| // | // | ||||||
| @@ -686,37 +686,31 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status writeStatus, err | |||||||
| 	} | 	} | ||||||
| 	td := new(big.Int).Add(block.Difficulty(), ptd) | 	td := new(big.Int).Add(block.Difficulty(), ptd) | ||||||
|  |  | ||||||
| 	self.mu.RLock() | 	// Make sure no inconsistent state is leaked during insertion | ||||||
| 	cblock := self.currentBlock | 	self.mu.Lock() | ||||||
| 	self.mu.RUnlock() | 	defer self.mu.Unlock() | ||||||
|  |  | ||||||
| 	// Compare the TD of the last known block in the canonical chain to make sure it's greater. | 	// If the total difficulty is higher than our known, add it to the canonical chain | ||||||
| 	// At this point it's possible that a different chain (fork) becomes the new canonical chain. |  | ||||||
| 	if td.Cmp(self.GetTd(self.currentBlock.Hash())) > 0 { | 	if td.Cmp(self.GetTd(self.currentBlock.Hash())) > 0 { | ||||||
| 		// chain fork | 		// Reorganize the chain if the parent is not the head block | ||||||
| 		if block.ParentHash() != cblock.Hash() { | 		if block.ParentHash() != self.currentBlock.Hash() { | ||||||
| 			// during split we merge two different chains and create the new canonical chain | 			if err := self.reorg(self.currentBlock, block); err != nil { | ||||||
| 			err := self.reorg(cblock, block) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return NonStatTy, err | 				return NonStatTy, err | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		status = CanonStatTy | 		// Insert the block as the new head of the chain | ||||||
|  |  | ||||||
| 		self.mu.Lock() |  | ||||||
| 		self.insert(block) | 		self.insert(block) | ||||||
| 		self.mu.Unlock() | 		status = CanonStatTy | ||||||
| 	} else { | 	} else { | ||||||
| 		status = SideStatTy | 		status = SideStatTy | ||||||
| 	} | 	} | ||||||
|  | 	// Irrelevant of the canonical status, write the block itself to the database | ||||||
| 	if err := WriteTd(self.chainDb, block.Hash(), td); err != nil { | 	if err := WriteTd(self.chainDb, block.Hash(), td); err != nil { | ||||||
| 		glog.Fatalf("failed to write block total difficulty: %v", err) | 		glog.Fatalf("failed to write block total difficulty: %v", err) | ||||||
| 	} | 	} | ||||||
| 	if err := WriteBlock(self.chainDb, block); err != nil { | 	if err := WriteBlock(self.chainDb, block); err != nil { | ||||||
| 		glog.Fatalf("filed to write block contents: %v", err) | 		glog.Fatalf("filed to write block contents: %v", err) | ||||||
| 	} | 	} | ||||||
| 	// Delete from future blocks |  | ||||||
| 	self.futureBlocks.Remove(block.Hash()) | 	self.futureBlocks.Remove(block.Hash()) | ||||||
|  |  | ||||||
| 	return | 	return | ||||||
| @@ -860,9 +854,6 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) { | |||||||
| // to be part of the new canonical chain and accumulates potential missing transactions and post an | // to be part of the new canonical chain and accumulates potential missing transactions and post an | ||||||
| // event about them | // event about them | ||||||
| func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error { | func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error { | ||||||
| 	self.mu.Lock() |  | ||||||
| 	defer self.mu.Unlock() |  | ||||||
|  |  | ||||||
| 	var ( | 	var ( | ||||||
| 		newChain    types.Blocks | 		newChain    types.Blocks | ||||||
| 		commonBlock *types.Block | 		commonBlock *types.Block | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user