diff --git a/core/headerchain.go b/core/headerchain.go index eee3e08f9a..e6ddf93ad5 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -487,6 +487,10 @@ func (hc *HeaderChain) loadLastState() error { // properly and it doesn't crash the nodes hc.currentHeader.Store(hc.genesisHeader) } + } else { + // Recover the current header + log.Warn("Recovering Current Header") + hc.SetCurrentHeader(hc.RecoverCurrentHeader()) } heads := make([]*types.Header, 0) @@ -669,6 +673,30 @@ func (hc *HeaderChain) GetHeaderOrCandidate(hash common.Hash, number uint64) *ty return header } +// RecoverCurrentHeader retrieves the current head header of the canonical chain. The +// header is retrieved from the HeaderChain's internal cache +func (hc *HeaderChain) RecoverCurrentHeader() *types.Header { + // Start logarithmic ascent to find the upper bound + high := uint64(1) + for hc.GetHeaderByNumber(high) != nil { + high *= 2 + } + // Run binary search to find the max header + low := high / 2 + for low <= high { + mid := (low + high) / 2 + if hc.GetHeaderByNumber(mid) != nil { + low = mid + 1 + } else { + high = mid - 1 + } + } + header := hc.GetHeaderByNumber(high) + log.Info("Header Recovered: ", "hash", header.Hash().String()) + + return header +} + // GetHeaderOrCandidateByHash retrieves a block header from the database by hash, caching it if // found. func (hc *HeaderChain) GetHeaderOrCandidateByHash(hash common.Hash) *types.Header {