core: fix block canonical mark / content write race
This commit is contained in:
parent
f186b39018
commit
b99fe27f8b
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user