@@ -248,6 +248,42 @@ func (xhash *XHash) verifyHeader(chain consensus.ChainHeaderReader, header, pare
248248 return nil
249249}
250250
251+ // initASERTAnchor (re)computes the ASERT anchor parameters from the current
252+ // chain view at the given anchor height. Caller must hold xhash.asertMu.
253+ func (xhash * XHash ) initASERTAnchor (
254+ chain consensus.ChainHeaderReader ,
255+ asertAnchorHeight uint64 ,
256+ parent * types.Header ,
257+ ) {
258+ anchorHeader := chain .GetHeaderByNumber (asertAnchorHeight )
259+ if anchorHeader == nil && parent .Number .Uint64 () > asertAnchorHeight {
260+ // Fallback: walk backwards from parent
261+ h := parent
262+ for h != nil && h .Number .Uint64 () > asertAnchorHeight {
263+ h = chain .GetHeader (h .ParentHash , h .Number .Uint64 ()- 1 )
264+ }
265+ anchorHeader = h
266+ }
267+
268+ if anchorHeader == nil || anchorHeader .Number .Uint64 () != asertAnchorHeight {
269+ panic (fmt .Sprintf (
270+ "ASERT: could not locate anchor at height %d (parentHeight=%d)" ,
271+ asertAnchorHeight , parent .Number .Uint64 (),
272+ ))
273+ }
274+
275+ anchorParent := chain .GetHeader (anchorHeader .ParentHash , anchorHeader .Number .Uint64 ()- 1 )
276+ if anchorParent == nil {
277+ panic ("ASERT: missing anchor parent header" )
278+ }
279+
280+ xhash .asertAnchorHeight = int64 (anchorHeader .Number .Uint64 ())
281+ xhash .asertAnchorParentTime = int64 (anchorParent .Time )
282+ xhash .asertAnchorTarget = difficultyToTarget (anchorHeader .Difficulty )
283+ xhash .asertAnchorHash = anchorHeader .Hash ()
284+ xhash .asertAnchorInit = true
285+ }
286+
251287// CalcDifficulty is the difficulty adjustment algorithm. It returns
252288// the difficulty that a new block should have when created at time
253289// given the parent block's time and difficulty.
@@ -268,32 +304,16 @@ func (xhash *XHash) CalcDifficulty(chain consensus.ChainHeaderReader, time uint6
268304 asertActivationHeight := xcfg .AsertActivationHeight
269305 asertAnchorHeight := asertActivationHeight - 1
270306
271- // Lazily populate anchor cache on first ASERT block
272307 if ! xhash .asertAnchorInit {
308+ // First ASERT use: init anchor from current chain view
309+ xhash .initASERTAnchor (chain , asertAnchorHeight , parent )
310+ } else {
311+ // Detect deep reorgs that changed the header at the anchor height.
273312 anchorHeader := chain .GetHeaderByNumber (asertAnchorHeight )
274- if anchorHeader == nil && parent .Number .Uint64 () > asertAnchorHeight {
275- // Fallback: walk backwards from parent
276- h := parent
277- for h != nil && h .Number .Uint64 () > asertAnchorHeight {
278- h = chain .GetHeader (h .ParentHash , h .Number .Uint64 ()- 1 )
279- }
280- anchorHeader = h
281- }
282-
283- if anchorHeader == nil || anchorHeader .Number .Uint64 () != asertAnchorHeight {
284- panic (fmt .Sprintf ("ASERT: could not locate anchor at height %d (nextHeight=%d, parentHeight=%d)" ,
285- asertAnchorHeight , nextHeight , parent .Number .Uint64 ()))
286- }
287-
288- anchorParent := chain .GetHeader (anchorHeader .ParentHash , anchorHeader .Number .Uint64 ()- 1 )
289- if anchorParent == nil {
290- panic ("ASERT: missing anchor parent header" )
313+ if anchorHeader == nil || anchorHeader .Hash () != xhash .asertAnchorHash {
314+ // Chain history at anchor height changed. Re init anchor from this view.
315+ xhash .initASERTAnchor (chain , asertAnchorHeight , parent )
291316 }
292-
293- xhash .asertAnchorHeight = int64 (anchorHeader .Number .Uint64 ())
294- xhash .asertAnchorParentTime = int64 (anchorParent .Time )
295- xhash .asertAnchorTarget = difficultyToTarget (anchorHeader .Difficulty )
296- xhash .asertAnchorInit = true
297317 }
298318
299319 evalHeight := int64 (parent .Number .Uint64 ())
0 commit comments