Downloader.findAncestorSpanSearch¶
| Source (upstream pre-purge) | Current | |
|---|---|---|
| File | eth/downloader/downloader.go |
downloader_pow.go |
| Symbol | Downloader.findAncestorSpanSearch |
Downloader.findAncestorSpanSearch |
| 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
3-way merge — purge → getc ← upstream¶
pre-purge≈ adapted (origin inferred by similarity)fork-only
// findAncestorSpanSearch searches for a common ancestor using a span search.
↗func (d *Downloader) findAncestorSpanSearch(p *peerConnection, mode SyncMode, remoteHeight, localHeight uint64, floor int64) (uint64, error) {
from, count, skip, max := calculateRequestSpan(remoteHeight, localHeight)
↗ p.log.Trace("Span searching for common ancestor", "count", count, "from", from, "skip", skip)
headers, hashes, err := d.fetchHeadersByNumber(p, uint64(from), count, skip, false)
if err != nil {
return 0, err
}
// Wait for the remote response to the head fetch
number, hash := uint64(0), common.Hash{}
↗ // Make sure the peer actually gave something valid
if len(headers) == 0 {
p.log.Warn("Empty head header set")
return 0, errEmptyHeaderSet
}
// Make sure the peer's reply conforms to the request
for i, header := range headers {
expectNumber := from + int64(i)*int64(skip+1)
if number := header.Number.Int64(); number != expectNumber {
p.log.Warn("Head headers broke chain ordering", "index", i, "requested", expectNumber, "received", number)
return 0, fmt.Errorf("%w: %v", errInvalidChain, errors.New("head headers broke chain ordering"))
}
}
// Check if a common ancestor was found
for i := len(headers) - 1; i >= 0; i-- {
// Skip any headers that underflow/overflow our requested set
if headers[i].Number.Int64() < from || headers[i].Number.Uint64() > max {
continue
}
// Otherwise check if we already know the header or not
h := hashes[i]
n := headers[i].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 {
number, hash = n, h
break
}
}
// If the head fetch already found an ancestor, return
if hash != (common.Hash{}) {
if int64(number) <= floor {
p.log.Warn("Ancestor below allowance", "number", number, "hash", hash, "allowance", floor)
return 0, errInvalidAncestor
}
p.log.Debug("Found common ancestor", "number", number, "hash", hash)
return number, nil
}
return 0, errNoAncestorFound
}
core-geth validation — +4 -5
| | | |---|---| | File | [`downloader.go`](https://github.com/etclabscore/core-geth/blob/v1.12.20/eth/downloader/downloader.go) | | Symbol | `Downloader.findAncestorSpanSearch` | | Ref | `v1.12.20` |--- a/core-geth/eth/downloader/downloader.go
+++ b/etc/eth/downloader/downloader_pow.go
@@ -1,3 +1,4 @@
+// findAncestorSpanSearch searches for a common ancestor using a span search.
func (d *Downloader) findAncestorSpanSearch(p *peerConnection, mode SyncMode, remoteHeight, localHeight uint64, floor int64) (uint64, error) {
from, count, skip, max := calculateRequestSpan(remoteHeight, localHeight)
@@ -34,14 +35,12 @@
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 {
number, hash = n, h