Skip to content

ETCEngine.VerifyHeaders (parallel)

Source (upstream pre-purge) Current
File consensus/ethash/consensus.go engine.go
Symbol Ethash.VerifyHeaders ETCEngine.VerifyHeaders
Ref dde2da0ef~1 etc/v1.17.3-full-node

Parallel header verification using GOMAXPROCS workers. Upstream removed parallelism post-merge (PoS verification is trivial). Restored from pre-purge ethash.VerifyHeaders for PoW full sync performance.

3-way merge — purge → getc ← upstream

pre-purgecommon≈ adapted (origin inferred by similarity)fork-only
// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
// concurrently. Adapted from pre-purge ethash.VerifyHeaders (dde2da0ef~1)
// which spawns GOMAXPROCS workers for parallel verification.
func (e *ETCEngine) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) {
if len(headers) == 0 {
abort, results := make(chan struct{}), make(chan error)
return abort, results
}
// Spawn as many workers as allowed threads
workers := runtime.GOMAXPROCS(0)
if len(headers) < workers {
workers = len(headers)
}
// Create a task channel and spawn the verifiers
var (
inputs = make(chan int)
done = make(chan int, workers)
errors = make([]error, len(headers))
abort = make(chan struct{})
unixNow = time.Now().Unix()
)
for i := 0; i < workers; i++ {
go func() {
for index := range inputs {
errors[index] = e.verifyHeaderWorker(chain, headers, index, unixNow)
done <- index
}
}()
}
errorsOut := make(chan error, len(headers))
go func() {
defer close(inputs)
var (
in, out = 0, 0
checked = make([]bool, len(headers))
inputs = inputs
)
for {
select {
case inputs <- in:
if in++; in == len(headers) {
// Reached end of headers. Stop sending to workers.
inputs = nil
}
case index := <-done:
for checked[index] = true; checked[out]; out++ {
errorsOut <- errors[out]
if out == len(headers)-1 {
return
}
}
case <-abort:
return
}
}
}()
return abort, errorsOut
}
core-geth validation — +6 -11 | | | |---|---| | File | [`consensus.go`](https://github.com/etclabscore/core-geth/blob/v1.12.20/consensus/ethash/consensus.go) | | Symbol | `Ethash.VerifyHeaders` | | Ref | `v1.12.20` |
--- a/core-geth/consensus/ethash/consensus.go
+++ b/etc/consensus/etc/engine.go
@@ -1,16 +1,11 @@
 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
-// concurrently. The method returns a quit channel to abort the operations and
-// a results channel to retrieve the async verifications.
-func (ethash *Ethash) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
-   // If we're running a full engine faking, accept any input as valid
-   if ethash.config.PowMode == ModeFullFake || len(headers) == 0 {
-       abort, results := make(chan struct{}), make(chan error, len(headers))
-       for i := 0; i < len(headers); i++ {
-           results <- nil
-       }
+// concurrently. Adapted from pre-purge ethash.VerifyHeaders (dde2da0ef~1)
+// which spawns GOMAXPROCS workers for parallel verification.
+func (e *ETCEngine) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) (chan<- struct{}, <-chan error) {
+   if len(headers) == 0 {
+       abort, results := make(chan struct{}), make(chan error)
        return abort, results
    }
-
    // Spawn as many workers as allowed threads
    workers := runtime.GOMAXPROCS(0)
    if len(headers) < workers {
@@ -28,7 +23,7 @@
    for i := 0; i < workers; i++ {
        go func() {
            for index := range inputs {
-               errors[index] = ethash.verifyHeaderWorker(chain, headers, seals, index, unixNow)
+               errors[index] = e.verifyHeaderWorker(chain, headers, index, unixNow)
                done <- index
            }
        }()

← Consensus & Ethash