Downloader.findAncestorBinarySearch¶
| Source (upstream pre-purge) | Current | |
|---|---|---|
| File | eth/downloader/downloader.go |
downloader_pow.go |
| Symbol | Downloader.findAncestorBinarySearch |
Downloader.findAncestorBinarySearch |
| Ref | 45baf2111~1 |
etc/v1.17.3-full-node |
d.lightchain replaced with d.blockchain — semantically identical since BlockChain embeds LightChain; LightSync removed upstream in #29711 — see Downloader.findAncestorSpanSearch
3-way merge — purge → getc ← upstream¶
pre-purge≈ adapted (origin inferred by similarity)fork-only
// findAncestorBinarySearch searches for a common ancestor using binary search.
↗func (d *Downloader) findAncestorBinarySearch(p *peerConnection, mode SyncMode, remoteHeight uint64, floor int64) (uint64, error) {
hash := common.Hash{}
↗ // Ancestor not found, we need to binary search over our chain
start, end := uint64(0), remoteHeight
if floor > 0 {
start = uint64(floor)
}
p.log.Trace("Binary searching for common ancestor", "start", start, "end", end)
↗ for start+1 < end {
// Split our chain interval in two, and request the hash to cross check
check := (start + end) / 2
↗ headers, hashes, err := d.fetchHeadersByNumber(p, check, 1, 0, false)
if err != nil {
return 0, err
}
// Make sure the peer actually gave something valid
if len(headers) != 1 {
p.log.Warn("Multiple headers for single request", "headers", len(headers))
return 0, fmt.Errorf("%w: multiple headers (%d) for single request", errBadPeer, len(headers))
}
// Modify the search interval based on the response
h := hashes[0]
n := headers[0].Number.Uint64()
↗ var known bool
switch mode {
≈ case ethconfig.FullSync:
↗ known = d.blockchain.HasBlock(h, n)
≈ case ethconfig.SnapSync:
↗ known = d.blockchain.HasFastBlock(h, n)
default:
≈ known = d.blockchain.HasHeader(h, n)
↗ }
if !known {
end = check
continue
}
≈ header := d.blockchain.GetHeaderByHash(h) // Independent of sync mode, header surely exists
↗ if header.Number.Uint64() != check {
p.log.Warn("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check)
return 0, fmt.Errorf("%w: non-requested header (%d)", errBadPeer, header.Number)
}
start = check
hash = h
}
// Ensure valid ancestry and return
if int64(start) <= floor {
p.log.Warn("Ancestor below allowance", "number", start, "hash", hash, "allowance", floor)
return 0, errInvalidAncestor
}
p.log.Debug("Found common ancestor", "number", start, "hash", hash)
return start, nil
}
core-geth validation — +5 -6
| | | |---|---| | File | [`downloader.go`](https://github.com/etclabscore/core-geth/blob/v1.12.20/eth/downloader/downloader.go) | | Symbol | `Downloader.findAncestorBinarySearch` | | Ref | `v1.12.20` |--- a/core-geth/eth/downloader/downloader.go
+++ b/etc/eth/downloader/downloader_pow.go
@@ -1,3 +1,4 @@
+// findAncestorBinarySearch searches for a common ancestor using binary search.
func (d *Downloader) findAncestorBinarySearch(p *peerConnection, mode SyncMode, remoteHeight uint64, floor int64) (uint64, error) {
hash := common.Hash{}
@@ -27,20 +28,18 @@
var known bool
switch mode {
- case FullSync:
+ case ethconfig.FullSync:
known = d.blockchain.HasBlock(h, n)
- case SnapSync:
+ case ethconfig.SnapSync:
known = d.blockchain.HasFastBlock(h, n)
- case LightSync:
- known = d.lightchain.HasHeader(h, n)
default:
- log.Crit("unknown sync mode", "mode", mode)
+ known = d.blockchain.HasHeader(h, n)
}
if !known {
end = check
continue
}
- header := d.lightchain.GetHeaderByHash(h) // Independent of sync mode, header surely exists
+ header := d.blockchain.GetHeaderByHash(h) // Independent of sync mode, header surely exists
if header.Number.Uint64() != check {
p.log.Warn("Received non requested header", "number", header.Number, "hash", header.Hash(), "request", check)
return 0, fmt.Errorf("%w: non-requested header (%d)", errBadPeer, header.Number)