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
}
}()