chain: improve reorg-during-rescan handling for bitcoind

This commit is contained in:
Alex 2018-03-09 20:37:17 -07:00 committed by Olaoluwa Osuntokun
parent 321c2fac2b
commit 6b6ed89d87

View file

@ -828,47 +828,55 @@ func (c *BitcoindClient) rescan(hash *chainhash.Hash) error {
} }
} }
if block.Header.PrevBlock.String() != lastHeader.Hash { for block.Header.PrevBlock.String() != lastHeader.Hash {
// We've been reorganized, maybe. We now walk backwards // If we're in this for loop, it looks like we've been
// to a known block. If we go back past the passed // reorganized. We now walk backwards to the common
// block, we return an error. The initialization logic // ancestor between the best chain and the known chain.
// of the wallet should prevent that from happening. //
for j := i - 1; j > firstHeader.Height; j-- { // First, we signal a disconnected block to rewind the
hash, err = c.GetBlockHash(int64(j)) // rescan state.
if err != nil { c.onBlockDisconnected(lastHash, lastHeader.Height,
return err time.Unix(lastHeader.Time, 0))
}
// If we've found a matching hash, we can move // Next, we get the previous block of the best chain.
// forward from there. hash, err = c.GetBlockHash(int64(i - 1))
if hash.String() == lastHeader.Hash { if err != nil {
i = j + 1 return err
block, err = c.GetBlock(hash) }
block, err = c.GetBlock(hash)
if err != nil {
return err
}
// Then, we get the previous header for the known chain.
if headers.Back() != nil {
// If it's already in the headers list, we can
// just get it from there and remove the
// current hash).
headers.Remove(headers.Back())
if headers.Back() != nil {
lastHeader = headers.Back().
Value.(*btcjson.
GetBlockHeaderVerboseResult)
lastHash, err = chainhash.
NewHashFromStr(lastHeader.Hash)
if err != nil { if err != nil {
return err return err
} }
break
} }
} else {
// Rewind the rescan state. // Otherwise, we get it from bitcoind.
c.onBlockDisconnected(lastHash,
lastHeader.Height,
time.Unix(lastHeader.Time, 0))
headers.Remove(headers.Back())
lastHeader = headers.Back().Value.(*btcjson.
GetBlockHeaderVerboseResult)
lastHash, err = chainhash.NewHashFromStr( lastHash, err = chainhash.NewHashFromStr(
lastHeader.Hash) lastHeader.PreviousHash)
if err != nil {
return err
}
lastHeader, err = c.GetBlockHeaderVerbose(
lastHash)
if err != nil { if err != nil {
return err return err
} }
}
// Check again and make sure we're at the start of the
// reorg.
if block.Header.PrevBlock.String() != lastHeader.Hash {
return errors.New("reorg during rescan went " +
"too far back")
} }
} }