From ba7a0e2565217441e2e3ba9a6950aa2a6b1a6128 Mon Sep 17 00:00:00 2001 From: ozpool Date: Mon, 29 Jun 2026 11:33:05 +0530 Subject: [PATCH] internal/ethapi, eth: simplify CL gate to a single clContacted flag Drop the clExpected flag and MarkCLExpected setter: every full node attaches the Engine API, so a CL is always expected and ConsensusReady only needs to track whether the CL has driven the node at least once. Also remove internal/ethapi/syncing_test.go, which only exercised the trivial gate branch through a hand-rolled mock. --- eth/backend.go | 12 +++--- eth/catalyst/api.go | 1 - internal/ethapi/syncing_test.go | 75 --------------------------------- 3 files changed, 5 insertions(+), 83 deletions(-) delete mode 100644 internal/ethapi/syncing_test.go diff --git a/eth/backend.go b/eth/backend.go index 78aeb6dd0e..dcb8bc8417 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -125,20 +125,18 @@ type Ethereum struct { shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully - clExpected atomic.Bool // Set when catalyst.Register attaches the Engine API clContacted atomic.Bool // Set on first Engine API call (newPayload / FCU) } -// MarkCLExpected and MarkCLContacted are setters for the two clXxx flags; -// catalyst calls them from its package and so cannot reach the fields directly. -func (s *Ethereum) MarkCLExpected() { s.clExpected.Store(true) } +// MarkCLContacted records that the consensus client has driven this node at +// least once; catalyst calls it from its package and so cannot reach the field +// directly. func (s *Ethereum) MarkCLContacted() { s.clContacted.Store(true) } // ConsensusReady reports whether eth_syncing should be allowed to return false. -// On nodes without an Engine API, always true. On nodes that expect a CL, true -// only after the CL has driven the node at least once. +// True once the consensus client has driven the node at least once. func (s *Ethereum) ConsensusReady() bool { - return !s.clExpected.Load() || s.clContacted.Load() + return s.clContacted.Load() } // New creates a new Ethereum object (including the initialisation of the common Ethereum object), diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 87ff503fb1..f2c58d400d 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -49,7 +49,6 @@ import ( // Register adds the engine API and related APIs to the full node. func Register(stack *node.Node, backend *eth.Ethereum) error { - backend.MarkCLExpected() stack.RegisterAPIs([]rpc.API{ newTestingAPI(backend), { diff --git a/internal/ethapi/syncing_test.go b/internal/ethapi/syncing_test.go deleted file mode 100644 index 27f188163d..0000000000 --- a/internal/ethapi/syncing_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2026 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package ethapi - -import ( - "context" - "testing" - - "github.com/ethereum/go-ethereum" -) - -type syncingBackend struct { - Backend - progress ethereum.SyncProgress - ready bool -} - -func (b *syncingBackend) SyncProgress(_ context.Context) ethereum.SyncProgress { return b.progress } -func (b *syncingBackend) ConsensusReady() bool { return b.ready } - -// Issue #33687: a Done downloader but no CL handshake yet must report syncing. -func TestSyncingBeforeCLContact(t *testing.T) { - api := NewEthereumAPI(&syncingBackend{progress: ethereum.SyncProgress{}, ready: false}) - res, err := api.Syncing(context.Background()) - if err != nil { - t.Fatalf("Syncing returned error: %v", err) - } - if v, ok := res.(bool); ok && !v { - t.Fatal("expected truthy syncing payload before CL handshake, got false") - } -} - -func TestSyncingAfterCLContact(t *testing.T) { - api := NewEthereumAPI(&syncingBackend{progress: ethereum.SyncProgress{}, ready: true}) - res, err := api.Syncing(context.Background()) - if err != nil { - t.Fatalf("Syncing returned error: %v", err) - } - if v, ok := res.(bool); !ok || v { - t.Fatalf("expected false after CL handshake when sync is done, got %v", res) - } -} - -// Active sync stays truthy regardless of the CL gate. -func TestSyncingActiveSyncIgnoresCLGate(t *testing.T) { - api := NewEthereumAPI(&syncingBackend{ - progress: ethereum.SyncProgress{ - StartingBlock: 100, - CurrentBlock: 150, - HighestBlock: 200, - }, - ready: false, - }) - res, err := api.Syncing(context.Background()) - if err != nil { - t.Fatalf("Syncing returned error: %v", err) - } - if _, ok := res.(map[string]interface{}); !ok { - t.Fatalf("expected progress map during active sync, got %T", res) - } -}