Optimize merge block detection with sort.Search

This commit is contained in:
sivaratrisrinivas 2025-03-12 18:45:57 -05:00
parent cbd75d107a
commit ad8884cac5

View file

@ -23,6 +23,7 @@ import (
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"slices" "slices"
"sort"
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
@ -1433,36 +1434,30 @@ func findMergeBlock(ctx *cli.Context, db ethdb.Database) (uint64, error) {
// If no hardcoded value was used or found, detect the merge block // If no hardcoded value was used or found, detect the merge block
if !found { if !found {
// Binary search to find the merge block // Use sort.Search to find the merge block
var low uint64 = 0 log.Info("Searching for merge block using sort.Search", "head", *headNumber)
var high uint64 = *headNumber
log.Info("Searching for merge block using binary search", "head", *headNumber) // Convert the result of sort.Search (int) to uint64
mergeBlock = uint64(sort.Search(int(*headNumber), func(index int) bool {
for low <= high { header := rawdb.ReadHeader(db, rawdb.ReadCanonicalHash(db, uint64(index)), uint64(index))
mid := (low + high) / 2
header := rawdb.ReadHeader(db, rawdb.ReadCanonicalHash(db, mid), mid)
if header == nil { if header == nil {
return 0, fmt.Errorf("header %d not found", mid) panic(fmt.Sprintf("header %d not found", index))
} }
return header.Difficulty.Sign() == 0
}))
if header.Difficulty.Sign() == 0 { // Check if we found a valid merge block
// This is a post-merge block, look earlier if mergeBlock < uint64(*headNumber) {
high = mid - 1 header := rawdb.ReadHeader(db, rawdb.ReadCanonicalHash(db, mergeBlock), mergeBlock)
mergeBlock = mid if header != nil && header.Difficulty.Sign() == 0 {
found = true found = true
} else { log.Info("Found merge block", "number", mergeBlock)
// This is a pre-merge block, look later
low = mid + 1
} }
} }
if !found { if !found {
return 0, fmt.Errorf("merge block not found, chain may not have transitioned to PoS yet") return 0, fmt.Errorf("merge block not found, chain may not have transitioned to PoS yet")
} }
// The merge block is the first block with zero difficulty
log.Info("Found merge block", "number", mergeBlock)
} }
return mergeBlock, nil return mergeBlock, nil