chain: improve reorg-during-rescan handling for bitcoind
This commit is contained in:
parent
321c2fac2b
commit
6b6ed89d87
1 changed files with 40 additions and 32 deletions
|
@ -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")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue