Skip to content

Commit b52870f

Browse files
committed
xhash/asert: cache anchor hash to re-init achor cache in case of deep reorgs
1 parent 2aa979f commit b52870f

File tree

2 files changed

+45
-23
lines changed

2 files changed

+45
-23
lines changed

consensus/xhash/consensus.go

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -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())

consensus/xhash/xhash.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535

3636
"github.com/edsrzf/mmap-go"
3737
"github.com/hashicorp/golang-lru/simplelru"
38+
"github.com/microstack-tech/parallax/common"
3839
"github.com/microstack-tech/parallax/consensus"
3940
"github.com/microstack-tech/parallax/log"
4041
"github.com/microstack-tech/parallax/metrics"
@@ -449,6 +450,7 @@ type XHash struct {
449450
asertAnchorHeight int64
450451
asertAnchorParentTime int64
451452
asertAnchorTarget *big.Int
453+
asertAnchorHash common.Hash
452454
}
453455

454456
// New creates a full sized XHash PoW scheme and starts a background thread for

0 commit comments

Comments
 (0)