Merge pull request #1243 from Roasbeef/init-block-index-consistency
blockchain: in initChainState mark ancestors of best tip as valid if …
This commit is contained in:
commit
0f95fff561
2 changed files with 59 additions and 9 deletions
|
@ -1085,6 +1085,17 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error
|
|||
func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, flags BehaviorFlags) (bool, error) {
|
||||
fastAdd := flags&BFFastAdd == BFFastAdd
|
||||
|
||||
flushIndexState := func() {
|
||||
// Intentionally ignore errors writing updated node status to DB. If
|
||||
// it fails to write, it's not the end of the world. If the block is
|
||||
// valid, we flush in connectBlock and if the block is invalid, the
|
||||
// worst that can happen is we revalidate the block after a restart.
|
||||
if writeErr := b.index.flushToDB(); writeErr != nil {
|
||||
log.Warnf("Error flushing block index changes to disk: %v",
|
||||
writeErr)
|
||||
}
|
||||
}
|
||||
|
||||
// We are extending the main (best) chain with a new block. This is the
|
||||
// most common case.
|
||||
parentHash := &block.MsgBlock().Header.PrevBlock
|
||||
|
@ -1108,14 +1119,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla
|
|||
return false, err
|
||||
}
|
||||
|
||||
// Intentionally ignore errors writing updated node status to DB. If
|
||||
// it fails to write, it's not the end of the world. If the block is
|
||||
// valid, we flush in connectBlock and if the block is invalid, the
|
||||
// worst that can happen is we revalidate the block after a restart.
|
||||
if writeErr := b.index.flushToDB(); writeErr != nil {
|
||||
log.Warnf("Error flushing block index changes to disk: %v",
|
||||
writeErr)
|
||||
}
|
||||
flushIndexState()
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
@ -1140,9 +1144,28 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla
|
|||
// Connect the block to the main chain.
|
||||
err := b.connectBlock(node, block, view, stxos)
|
||||
if err != nil {
|
||||
// If we got hit with a rule error, then we'll mark
|
||||
// that status of the block as invalid and flush the
|
||||
// index state to disk before returning with the error.
|
||||
if _, ok := err.(RuleError); ok {
|
||||
b.index.SetStatusFlags(
|
||||
node, statusValidateFailed,
|
||||
)
|
||||
}
|
||||
|
||||
flushIndexState()
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
// If this is fast add, or this block node isn't yet marked as
|
||||
// valid, then we'll update its status and flush the state to
|
||||
// disk again.
|
||||
if fastAdd || !b.index.NodeStatus(node).KnownValid() {
|
||||
b.index.SetStatusFlags(node, statusValid)
|
||||
flushIndexState()
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
if fastAdd {
|
||||
|
|
|
@ -1128,7 +1128,7 @@ func (b *BlockChain) initChainState() error {
|
|||
}
|
||||
|
||||
// Attempt to load the chain state from the database.
|
||||
return b.db.View(func(dbTx database.Tx) error {
|
||||
err = b.db.View(func(dbTx database.Tx) error {
|
||||
// Fetch the stored chain state from the database metadata.
|
||||
// When it doesn't exist, it means the database hasn't been
|
||||
// initialized for use with chain yet, so break out now to allow
|
||||
|
@ -1221,6 +1221,25 @@ func (b *BlockChain) initChainState() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// As a final consistency check, we'll run through all the
|
||||
// nodes which are ancestors of the current chain tip, and mark
|
||||
// them as valid if they aren't already marked as such. This
|
||||
// is a safe assumption as all the block before the current tip
|
||||
// are valid by definition.
|
||||
for iterNode := tip; iterNode != nil; iterNode = iterNode.parent {
|
||||
// If this isn't already marked as valid in the index, then
|
||||
// we'll mark it as valid now to ensure consistency once
|
||||
// we're up and running.
|
||||
if !iterNode.status.KnownValid() {
|
||||
log.Infof("Block %v (height=%v) ancestor of "+
|
||||
"chain tip not marked as valid, "+
|
||||
"upgrading to valid for consistency",
|
||||
iterNode.hash, iterNode.height)
|
||||
|
||||
b.index.SetStatusFlags(iterNode, statusValid)
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the state related to the best block.
|
||||
blockSize := uint64(len(blockBytes))
|
||||
blockWeight := uint64(GetBlockWeight(btcutil.NewBlock(&block)))
|
||||
|
@ -1230,6 +1249,14 @@ func (b *BlockChain) initChainState() error {
|
|||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// As we might have updated the index after it was loaded, we'll
|
||||
// attempt to flush the index to the DB. This will only result in a
|
||||
// write if the elements are dirty, so it'll usually be a noop.
|
||||
return b.index.flushToDB()
|
||||
}
|
||||
|
||||
// deserializeBlockRow parses a value in the block index bucket into a block
|
||||
|
|
Loading…
Reference in a new issue