From 4f75049ea0f41fca52635df6b3594cb8b4f2e34e Mon Sep 17 00:00:00 2001 From: Jonny Rhea <5555162+jrhea@users.noreply.github.com> Date: Tue, 3 Mar 2026 21:58:51 -0600 Subject: [PATCH] miner: avoid unnecessary work after payload resolution (#33943) In `buildPayload()`, the background goroutine uses a `select` to wait on the recommit timer, the stop channel, and the end timer. When both `timer.C` and `payload.stop` are ready simultaneously, Go's `select` picks a case non-deterministically. This means the loop can enter the `timer.C` case and perform an unnecessary `generateWork` call even after the payload has been resolved. Add a non-blocking check of `payload.stop` at the top of the `timer.C` case to exit immediately when the payload has already been delivered. --- miner/payload_building.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/miner/payload_building.go b/miner/payload_building.go index 2398e675af..8bd9552338 100644 --- a/miner/payload_building.go +++ b/miner/payload_building.go @@ -260,6 +260,17 @@ func (miner *Miner) buildPayload(args *BuildPayloadArgs, witness bool) (*Payload for { select { case <-timer.C: + // When block building takes close to the full recommit interval, + // the timer fires near-instantly on the next iteration. If the + // payload was resolved during that build, both timer.C and + // payload.stop are ready and Go's select picks one at random. + // Check payload.stop first to avoid an unnecessary generateWork. + select { + case <-payload.stop: + log.Info("Stopping work on payload", "id", payload.id, "reason", "delivery") + return + default: + } start := time.Now() r := miner.generateWork(fullParams, witness) if r.err == nil {