Skip to content

Commit

Permalink
simplify trimming
Browse files Browse the repository at this point in the history
  • Loading branch information
dhaidashenko committed Feb 23, 2024
1 parent faf61d9 commit 89a75b3
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 43 deletions.
10 changes: 5 additions & 5 deletions core/chains/evm/headtracker/head_saver.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (hs *headSaver) Save(ctx context.Context, head *evmtypes.Head) error {
}

func (hs *headSaver) Load(ctx context.Context, latestFinalized *evmtypes.Head) (chain *evmtypes.Head, err error) {
minBlockNumber := hs.calculateDeepestToKeep(latestFinalized.BlockNumber())
minBlockNumber := hs.calculateMinBlockToKeep(latestFinalized.BlockNumber())
heads, err := hs.orm.LatestHeads(ctx, minBlockNumber)
if err != nil {
return nil, err
Expand All @@ -54,7 +54,7 @@ func (hs *headSaver) Load(ctx context.Context, latestFinalized *evmtypes.Head) (
return hs.heads.LatestHead(), nil
}

func (hs *headSaver) calculateDeepestToKeep(latestFinalized int64) int64 {
func (hs *headSaver) calculateMinBlockToKeep(latestFinalized int64) int64 {
return latestFinalized - int64(hs.htConfig.HistoryDepth())
}

Expand All @@ -78,12 +78,12 @@ func (hs *headSaver) Chain(hash common.Hash) *evmtypes.Head {
}

func (hs *headSaver) MarkFinalized(ctx context.Context, finalized *evmtypes.Head) error {
deepestToKeep := hs.calculateDeepestToKeep(finalized.BlockNumber())
if !hs.heads.MarkFinalized(finalized.BlockHash(), deepestToKeep) {
minBlockToKeep := hs.calculateMinBlockToKeep(finalized.BlockNumber())
if !hs.heads.MarkFinalized(finalized.BlockHash(), minBlockToKeep) {
return fmt.Errorf("failed to find %s block in the canonical chain to mark it as finalized", finalized)
}

return hs.orm.TrimOldHeads(ctx, deepestToKeep)
return hs.orm.TrimOldHeads(ctx, minBlockToKeep)
}

var NullSaver httypes.HeadSaver = &nullSaver{}
Expand Down
56 changes: 18 additions & 38 deletions core/chains/evm/headtracker/heads.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ type Heads interface {
AddHeads(newHeads ...*evmtypes.Head)
// Count returns number of heads in the collection.
Count() int
// MarkFinalized - finds `finalized` in the LatestHead and marks it and all direct ancestors as finalized
MarkFinalized(finalized common.Hash, deepestToKeep int64) bool
// MarkFinalized - finds `finalized` in the LatestHead and marks it and all direct ancestors as finalized.
// Trims old blocks whose height is smaller than minBlockToKeep
MarkFinalized(finalized common.Hash, minBlockToKeep int64) bool
}

type heads struct {
Expand Down Expand Up @@ -63,8 +64,8 @@ func (h *heads) Count() int {
}

// MarkFinalized - marks block with has equal to finalized and all it's direct ancestors as finalized.
// Trims old blocks whose height is smaller than deepestToKeep
func (h *heads) MarkFinalized(finalized common.Hash, deepestToKeep int64) bool {
// Trims old blocks whose height is smaller than minBlockToKeep
func (h *heads) MarkFinalized(finalized common.Hash, minBlockToKeep int64) bool {
h.mu.Lock()
defer h.mu.Unlock()

Expand All @@ -73,7 +74,7 @@ func (h *heads) MarkFinalized(finalized common.Hash, deepestToKeep int64) bool {
}

// deep copy to avoid race
h.heads = deepCopy(h.heads)
h.heads = deepCopy(h.heads, minBlockToKeep)

head := h.heads[0]
foundFinalized := false
Expand All @@ -88,40 +89,10 @@ func (h *heads) MarkFinalized(finalized common.Hash, deepestToKeep int64) bool {
head = head.Parent
}

// trim blocks that are too deep
h.trimRedundantBlocks(deepestToKeep)

return foundFinalized
}

// trimRedundantBlocks - trims all the blocks whose blockNumber < deepestToKeep
// Not thread safe. Must be called on fresh copy of h.heads
func (h *heads) trimRedundantBlocks(deepestToKeep int64) {
if len(h.heads) == 0 {
return
}

deepestBlock := h.heads[0].HeadAtHeight(deepestToKeep)
if deepestBlock == nil {
return
}

for i, head := range h.heads {
// ensure that uncle chains and canonical chain do not go deeper than deepestToKeep
if deepestBlock.Parent == head.Parent {
head.Parent = nil
}
// trim slice
if head == deepestBlock {
h.heads = h.heads[:i+1]
return
}
}

panic("invariant violation: expected deepestToKeep to present in the heads slice since we've seen it before")
}

func deepCopy(oldHeads []*evmtypes.Head) []*evmtypes.Head {
func deepCopy(oldHeads []*evmtypes.Head, minBlockToKeep int64) []*evmtypes.Head {
headsMap := make(map[common.Hash]*evmtypes.Head, len(oldHeads))
for _, head := range oldHeads {
if head.Hash == head.ParentHash {
Expand Down Expand Up @@ -155,11 +126,20 @@ func deepCopy(oldHeads []*evmtypes.Head) []*evmtypes.Head {
return heads[i].Number > heads[j].Number
})

// yeah, we could have used binarySearch here, but the code was much longer and more complex and did not
// solve any performance issues
for i := range heads {
if heads[i].BlockNumber() < minBlockToKeep {
heads = heads[:i]
break
}
}

// assign parents
for i := 0; i < len(heads)-1; i++ {
head := heads[i]
parent, exists := headsMap[head.ParentHash]
if exists {
if exists && parent.BlockNumber() >= minBlockToKeep {
head.Parent = parent
}
}
Expand All @@ -172,5 +152,5 @@ func (h *heads) AddHeads(newHeads ...*evmtypes.Head) {
defer h.mu.Unlock()

// deep copy to avoid race
h.heads = deepCopy(append(h.heads, newHeads...))
h.heads = deepCopy(append(h.heads, newHeads...), 0)
}

0 comments on commit 89a75b3

Please sign in to comment.