diff --git a/node/cmd/node/main.go b/node/cmd/node/main.go index 9296c4ed7..e8abe3b4b 100644 --- a/node/cmd/node/main.go +++ b/node/cmd/node/main.go @@ -377,7 +377,7 @@ func startMetricsServer(addr string, logger tmlog.Logger) { } mux := http.NewServeMux() mux.Handle("/metrics", promhttp.Handler()) - srv := &http.Server{Addr: addr, Handler: mux} + srv := &http.Server{Addr: addr, Handler: mux, ReadHeaderTimeout: 10 * time.Second} go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Error("metrics server", "addr", addr, "err", err) diff --git a/node/derivation/derivation.go b/node/derivation/derivation.go index 068f255f5..f7e8ef2a2 100644 --- a/node/derivation/derivation.go +++ b/node/derivation/derivation.go @@ -878,7 +878,7 @@ func (d *Derivation) withReactorsQuiesced(ctx context.Context, batchIndex uint64 return err } defer func() { - // Use background context so a cancelled parent ctx doesn't + // Use background context so a canceled parent ctx doesn't // prevent reactor restart. height := preWrite if cur, readErr := d.l2Client.BlockNumber(context.Background()); readErr == nil { diff --git a/node/hakeeper/block_fsm.go b/node/hakeeper/block_fsm.go index 2a97ee212..d299df5c4 100644 --- a/node/hakeeper/block_fsm.go +++ b/node/hakeeper/block_fsm.go @@ -153,7 +153,7 @@ func (f *BlockFSM) Snapshot() (raft.FSMSnapshot, error) { // Reads the 8-byte appliedHeight from the snapshot. Does NOT call onApplied -- // geth state must be recovered independently (Fullnode P2P sync). func (f *BlockFSM) Restore(rc io.ReadCloser) error { - defer rc.Close() + defer func() { _ = rc.Close() }() data, err := io.ReadAll(rc) if err != nil { @@ -191,7 +191,7 @@ func (s *blockSnapshot) Persist(sink raft.SnapshotSink) error { var buf [8]byte binary.BigEndian.PutUint64(buf[:], s.height) if _, err := sink.Write(buf[:]); err != nil { - sink.Cancel() + _ = sink.Cancel() return fmt.Errorf("blockSnapshot.Persist: write failed: %w", err) } return sink.Close() diff --git a/node/hakeeper/ha_service.go b/node/hakeeper/ha_service.go index 5c1002859..fd3953a52 100644 --- a/node/hakeeper/ha_service.go +++ b/node/hakeeper/ha_service.go @@ -30,13 +30,13 @@ const ( // HAService implements the SequencerHA interface from tendermint/sequencer. // It also satisfies rpc.ConsensusAdapter so it can be passed directly to the RPC server. type HAService struct { - logger tmlog.Logger - cfg *Config + logger tmlog.Logger + cfg *Config advertisedAddr string // resolved once in New(), used throughout - fsm *BlockFSM - rpcServer *hakeeperrpc.Server + fsm *BlockFSM + rpcServer *hakeeperrpc.Server - // Raft internals (initialised in Start) + // Raft internals (initialized in Start) r *raft.Raft transport *raft.NetworkTransport @@ -69,7 +69,7 @@ func (h *HAService) SetOnBlockApplied(fn func(*types.BlockV2) error) { // ── SequencerHA interface ──────────────────────────────────────────────────── -// Start initialises Raft and the management RPC server. +// Start initializes Raft and the management RPC server. // Called by StateV2.OnStart() at upgrade height. func (h *HAService) Start() error { if err := h.initRaft(); err != nil { @@ -271,7 +271,7 @@ func (h *HAService) Addr() string { return h.advertisedAddr } // initRaft creates the Raft instance. Called once from Start(). // On failure, all opened resources are cleaned up via a single deferred closure. func (h *HAService) initRaft() (retErr error) { - if err := os.MkdirAll(h.cfg.StorageDir, 0o755); err != nil { + if err := os.MkdirAll(h.cfg.StorageDir, 0o750); err != nil { return fmt.Errorf("mkdir %q: %w", h.cfg.StorageDir, err) } @@ -287,13 +287,13 @@ func (h *HAService) initRaft() (retErr error) { r.Shutdown() } if transport != nil { - transport.Close() + _ = transport.Close() } if stableStore != nil { - stableStore.Close() + _ = stableStore.Close() } if logStore != nil { - logStore.Close() + _ = logStore.Close() } } }() @@ -364,7 +364,7 @@ func (h *HAService) initRaft() (retErr error) { h.r = r h.transport = transport - h.logger.Info("hakeeper: raft initialised", "bind", bindAddr) + h.logger.Info("hakeeper: raft initialized", "bind", bindAddr) return nil } diff --git a/node/hakeeper/rpc/backend.go b/node/hakeeper/rpc/backend.go index 1c9736ae0..bb1be40b8 100644 --- a/node/hakeeper/rpc/backend.go +++ b/node/hakeeper/rpc/backend.go @@ -7,6 +7,14 @@ import ( ) // APIBackend implements API, delegating to a ConsensusAdapter. +// +// Every method takes a context.Context to satisfy the go-ethereum JSON-RPC +// server's handler signature, but intentionally does not propagate it. The +// ConsensusAdapter wraps hashicorp/raft, whose membership and leadership +// operations are synchronous and not context-cancellable; those calls already +// enforce their own bounded deadline (raftTimeout) at the adapter layer, so +// there is nothing a caller-supplied ctx could cancel mid-operation. This is +// deliberate, not an oversight — do not "fix" it by threading ctx through. type APIBackend struct { log log.Logger cons ConsensusAdapter diff --git a/node/hakeeper/rpc/server.go b/node/hakeeper/rpc/server.go index 90cc3bc33..3cea4ee9b 100644 --- a/node/hakeeper/rpc/server.go +++ b/node/hakeeper/rpc/server.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "sync" + "time" ethrpc "github.com/morph-l2/go-ethereum/rpc" "github.com/pkg/errors" @@ -40,8 +41,9 @@ func New(log log.Logger, listenAddr string, listenPort int, cons ConsensusAdapte addr := fmt.Sprintf("%s:%d", listenAddr, listenPort) httpSrv := &http.Server{ - Addr: addr, - Handler: mux, + Addr: addr, + Handler: mux, + ReadHeaderTimeout: 10 * time.Second, } return &Server{ diff --git a/node/l1sequencer/enclave_signer.go b/node/l1sequencer/enclave_signer.go index e83a70fca..53d575440 100644 --- a/node/l1sequencer/enclave_signer.go +++ b/node/l1sequencer/enclave_signer.go @@ -165,7 +165,7 @@ func (s *EnclaveSigner) probe() error { if err := conn.SetDeadline(time.Now().Add(requestTimeout)); err != nil { return fmt.Errorf("set deadline: %w", err) } - defer conn.SetDeadline(time.Time{}) // clear on exit so signOnce can manage its own deadline + defer func() { _ = conn.SetDeadline(time.Time{}) }() // clear on exit so signOnce can manage its own deadline if _, err := conn.Write([]byte{opGetPubkey}); err != nil { return fmt.Errorf("write GetPubkey: %w", err) @@ -220,7 +220,7 @@ func (s *EnclaveSigner) signOnce(conn net.Conn, data []byte) ([]byte, error) { if err := conn.SetDeadline(time.Now().Add(requestTimeout)); err != nil { return nil, err } - defer conn.SetDeadline(time.Time{}) + defer func() { _ = conn.SetDeadline(time.Time{}) }() req := make([]byte, 1+hashLen) req[0] = opSign diff --git a/node/l1sequencer/signer.go b/node/l1sequencer/signer.go index 4ad851304..e99726e7a 100644 --- a/node/l1sequencer/signer.go +++ b/node/l1sequencer/signer.go @@ -53,4 +53,3 @@ func (s *LocalSigner) Sign(data []byte) ([]byte, error) { func (s *LocalSigner) Address() common.Address { return s.address } - diff --git a/node/l1sequencer/verifier.go b/node/l1sequencer/verifier.go index b12be781d..f7df7fd95 100644 --- a/node/l1sequencer/verifier.go +++ b/node/l1sequencer/verifier.go @@ -34,7 +34,7 @@ type sequencerCursor struct { // History is loaded from L1 at construction and refreshed every 5 minutes. // All L1 reads use the finalized block tag to avoid ingesting reorged data. type SequencerVerifier struct { - mu sync.Mutex + mu sync.Mutex history []bindings.L1SequencerHistoryRecord cursor sequencerCursor @@ -127,7 +127,7 @@ func (c *SequencerVerifier) syncHistory() error { return nil } -// refreshLoop polls L1 until ctx is cancelled. +// refreshLoop polls L1 until ctx is canceled. // Uses exponential backoff (10s -> 20s -> ... -> 5min) while history is empty, // then switches to the normal 5-minute interval once loaded. func (c *SequencerVerifier) refreshLoop(ctx context.Context) { diff --git a/ops/docker-sequencer-test/Dockerfile.l2-node-test b/ops/docker-sequencer-test/Dockerfile.l2-node-test index 04414cc53..4358089fe 100644 --- a/ops/docker-sequencer-test/Dockerfile.l2-node-test +++ b/ops/docker-sequencer-test/Dockerfile.l2-node-test @@ -16,7 +16,6 @@ COPY ./morph/node/go.mod ./morph/node/go.sum /polyrepo/morph/node/ COPY ./morph/common/go.mod ./morph/common/go.sum /polyrepo/morph/common/ COPY ./morph/bindings/go.mod ./morph/bindings/go.sum /polyrepo/morph/bindings/ COPY ./morph/contracts/go.mod ./morph/contracts/go.sum /polyrepo/morph/contracts/ -COPY ./morph/oracle/go.mod ./morph/oracle/go.sum /polyrepo/morph/oracle/ COPY ./morph/tx-submitter/go.mod ./morph/tx-submitter/go.sum /polyrepo/morph/tx-submitter/ COPY ./morph/ops/l2-genesis/go.mod ./morph/ops/l2-genesis/go.sum /polyrepo/morph/ops/l2-genesis/ COPY ./morph/ops/tools/go.mod ./morph/ops/tools/go.sum /polyrepo/morph/ops/tools/ diff --git a/ops/docker-sequencer-test/Dockerfile.tx-submitter-test b/ops/docker-sequencer-test/Dockerfile.tx-submitter-test index c38575bd5..09bdf7873 100644 --- a/ops/docker-sequencer-test/Dockerfile.tx-submitter-test +++ b/ops/docker-sequencer-test/Dockerfile.tx-submitter-test @@ -11,7 +11,6 @@ COPY ./morph/node/go.mod ./morph/node/go.sum /polyrepo/morph/node/ COPY ./morph/common/go.mod ./morph/common/go.sum /polyrepo/morph/common/ COPY ./morph/bindings/go.mod ./morph/bindings/go.sum /polyrepo/morph/bindings/ COPY ./morph/contracts/go.mod ./morph/contracts/go.sum /polyrepo/morph/contracts/ -COPY ./morph/oracle/go.mod ./morph/oracle/go.sum /polyrepo/morph/oracle/ COPY ./morph/tx-submitter/go.mod ./morph/tx-submitter/go.sum /polyrepo/morph/tx-submitter/ COPY ./morph/ops/l2-genesis/go.mod ./morph/ops/l2-genesis/go.sum /polyrepo/morph/ops/l2-genesis/ COPY ./morph/ops/tools/go.mod ./morph/ops/tools/go.sum /polyrepo/morph/ops/tools/ diff --git a/ops/docker-sequencer-test/run-test.sh b/ops/docker-sequencer-test/run-test.sh index e36e0b572..68484129f 100755 --- a/ops/docker-sequencer-test/run-test.sh +++ b/ops/docker-sequencer-test/run-test.sh @@ -340,7 +340,7 @@ start_l2_test() { # Start L2 execution nodes log_info "Starting L2 execution nodes..." - $COMPOSE_CMD up -d morph-el-0 morph-el-1 morph-el-2 morph-el-3 sentry-geth-0 + $COMPOSE_CMD up -d morph-el-0 morph-el-1 morph-el-2 morph-el-3 sentry-el-0 sleep 5