diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 990838d431..8ee4a6417a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -29,7 +29,7 @@ jobs: - uses: golangci/golangci-lint-action@v9.2.0 with: version: latest - args: --timeout 10m + args: --timeout 10m ./... github-token: ${{ secrets.github_token }} if: env.GIT_DIFF diff --git a/.golangci.yml b/.golangci.yml index b5185a5af5..4df3a98fd6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,18 +1,57 @@ version: "2" run: modules-download-mode: readonly + timeout: 10m + tests: true build-tags: - evm - e2e - docker linters: enable: + - asciicheck + - bidichk + - bodyclose + - contextcheck + - copyloopvar + - durationcheck + - errname - errorlint + - govet + - ineffassign + - makezero - gosec - misspell + - nilerr + - noctx + - prealloc + - predeclared + - reassign - revive + - rowserrcheck + - sqlclosecheck + - staticcheck - unconvert + - unused + - usestdlibvars + - wastedassign settings: + errcheck: + check-type-assertions: true + check-blank: true + govet: + enable-all: true + disable: + - fieldalignment + - shadow + gocritic: + enabled-tags: + - diagnostic + - style + - performance + disabled-checks: + - hugeParam + - rangeValCopy gosec: excludes: - G115 @@ -21,7 +60,7 @@ linters: - name: package-comments disabled: true - name: duplicated-imports - severity: warning + severity: error - name: exported arguments: - disableStutteringCheck @@ -32,10 +71,28 @@ linters: - common-false-positives - legacy - std-error-handling + rules: + - path: _test\.go + linters: + - prealloc + - noctx paths: - third_party$ - builtin$ - examples$ + disable: + - containedctx + - errcheck + - gocritic + - nolintlint + - testifylint + - thelper + - tparallel + - unparam + - wrapcheck +issues: + max-issues-per-linter: 0 + max-same-issues: 0 formatters: enable: - gci diff --git a/.just/lint.just b/.just/lint.just index 6075d8d819..ad43688df0 100644 --- a/.just/lint.just +++ b/.just/lint.just @@ -2,7 +2,7 @@ [group('lint')] lint: vet @echo "--> Running golangci-lint" - @golangci-lint run + @golangci-lint run ./... @echo "--> Running markdownlint" @markdownlint --config .markdownlint.yaml '**/*.md' @echo "--> Running hadolint" @@ -18,7 +18,7 @@ lint: vet [group('lint')] lint-fix: @echo "--> Formatting go" - @golangci-lint run --fix + @golangci-lint run --fix ./... @echo "--> Formatting markdownlint" @markdownlint --config .markdownlint.yaml --ignore './changelog.md' '**/*.md' -f diff --git a/block/internal/da/async_block_retriever_test.go b/block/internal/da/async_block_retriever_test.go index 2791dc5457..dcfbce84d1 100644 --- a/block/internal/da/async_block_retriever_test.go +++ b/block/internal/da/async_block_retriever_test.go @@ -266,5 +266,6 @@ func TestBlockData_SerializationEmpty(t *testing.T) { } assert.Equal(t, uint64(100), decoded.Height) + assert.Equal(t, time.Unix(0, 0).UTC(), decoded.Timestamp) assert.Equal(t, 0, len(decoded.Blobs)) } diff --git a/block/internal/executing/executor.go b/block/internal/executing/executor.go index 473d18306c..c139210066 100644 --- a/block/internal/executing/executor.go +++ b/block/internal/executing/executor.go @@ -381,7 +381,6 @@ func (e *Executor) executionLoop() { } else { delay = time.Until(currentState.LastBlockTime.Add(e.config.Node.BlockTime.Duration)) } - if delay > 0 { e.logger.Info().Dur("delay", delay).Msg("waiting to start block production") select { @@ -591,7 +590,7 @@ func (e *Executor) ProduceBlock(ctx context.Context) error { LastSubmittedDaHeaderHeight: e.cache.GetLastSubmittedHeaderHeight(), LastSubmittedDaDataHeight: e.cache.GetLastSubmittedDataHeight(), } - if err := e.raftNode.Broadcast(e.ctx, raftState); err != nil { + if err := e.raftNode.Broadcast(ctx, raftState); err != nil { return fmt.Errorf("failed to propose block to raft: %w", err) } e.logger.Debug().Uint64("height", newHeight).Msg("proposed block to raft") @@ -617,12 +616,12 @@ func (e *Executor) ProduceBlock(ctx context.Context) error { // IMPORTANT: Header MUST be broadcast before data — the P2P layer validates // incoming data against the current and previous header, so out-of-order // delivery would cause validation failures on peers. - if err := e.headerBroadcaster.WriteToStoreAndBroadcast(e.ctx, &types.P2PSignedHeader{ + if err := e.headerBroadcaster.WriteToStoreAndBroadcast(ctx, &types.P2PSignedHeader{ SignedHeader: header, }); err != nil { e.logger.Error().Err(err).Msg("failed to broadcast header") } - if err := e.dataBroadcaster.WriteToStoreAndBroadcast(e.ctx, &types.P2PData{ + if err := e.dataBroadcaster.WriteToStoreAndBroadcast(ctx, &types.P2PData{ Data: data, }); err != nil { e.logger.Error().Err(err).Msg("failed to broadcast data") @@ -637,7 +636,7 @@ func (e *Executor) ProduceBlock(ctx context.Context) error { // For based sequencer, advance safe/finalized since it comes from DA. if e.config.Node.BasedSequencer { - if err := e.exec.SetFinal(e.ctx, newHeight); err != nil { + if err := e.exec.SetFinal(ctx, newHeight); err != nil { e.sendCriticalError(fmt.Errorf("failed to set final height in based sequencer mode: %w", err)) return fmt.Errorf("failed to set final height in based sequencer mode: %w", err) } diff --git a/block/internal/submitting/da_submitter.go b/block/internal/submitting/da_submitter.go index 31c2681c91..4720d7788f 100644 --- a/block/internal/submitting/da_submitter.go +++ b/block/internal/submitting/da_submitter.go @@ -90,15 +90,15 @@ func (rs *retryState) Next(reason retryReason, pol retryPolicy) { } // clamp constrains a duration between min and max bounds -func clamp(v, min, max time.Duration) time.Duration { - if min > max { - min, max = max, min +func clamp(v, minTime, maxTime time.Duration) time.Duration { + if minTime > maxTime { + minTime, maxTime = maxTime, minTime } - if v < min { - return min + if v < minTime { + return minTime } - if v > max { - return max + if v > maxTime { + return maxTime } return v } diff --git a/block/internal/submitting/da_submitter_test.go b/block/internal/submitting/da_submitter_test.go index cb00b36da8..e92d085a80 100644 --- a/block/internal/submitting/da_submitter_test.go +++ b/block/internal/submitting/da_submitter_test.go @@ -145,7 +145,6 @@ func TestDASubmitter_SubmitHeaders_Success(t *testing.T) { // Create test signer addr, pub, signer := createTestSigner(t) - gen.ProposerAddress = addr // Create test headers header1 := &types.SignedHeader{ diff --git a/block/internal/syncing/syncer.go b/block/internal/syncing/syncer.go index 500c231179..848ae9825a 100644 --- a/block/internal/syncing/syncer.go +++ b/block/internal/syncing/syncer.go @@ -164,7 +164,8 @@ func (s *Syncer) SetBlockSyncer(bs BlockSyncer) { // Start begins the syncing component func (s *Syncer) Start(ctx context.Context) error { - s.ctx, s.cancel = context.WithCancel(ctx) + ctx, cancel := context.WithCancel(ctx) + s.ctx, s.cancel = ctx, cancel if err := s.initializeState(); err != nil { return fmt.Errorf("failed to initialize syncer state: %w", err) @@ -178,14 +179,14 @@ func (s *Syncer) Start(ctx context.Context) error { s.fiRetriever = da.NewForcedInclusionRetriever(s.daClient, s.logger, s.config, s.genesis.DAStartHeight, s.genesis.DAEpochForcedInclusion) s.p2pHandler = NewP2PHandler(s.headerStore, s.dataStore, s.cache, s.genesis, s.logger) - if currentHeight, err := s.store.Height(s.ctx); err != nil { + if currentHeight, err := s.store.Height(ctx); err != nil { s.logger.Error().Err(err).Msg("failed to set initial processed height for p2p handler") } else { s.p2pHandler.SetProcessedHeight(currentHeight) } if s.raftRetriever != nil { - if err := s.raftRetriever.Start(s.ctx); err != nil { + if err := s.raftRetriever.Start(ctx); err != nil { return fmt.Errorf("start raft retriever: %w", err) } } @@ -195,10 +196,10 @@ func (s *Syncer) Start(ctx context.Context) error { } // Start main processing loop - s.wg.Go(s.processLoop) + s.wg.Go(func() { s.processLoop(ctx) }) // Start dedicated workers for DA, and pending processing - s.startSyncWorkers() + s.startSyncWorkers(ctx) s.logger.Info().Msg("syncer started") return nil @@ -342,37 +343,37 @@ func (s *Syncer) initializeState() error { } // processLoop is the main coordination loop for processing events -func (s *Syncer) processLoop() { +func (s *Syncer) processLoop(ctx context.Context) { s.logger.Info().Msg("starting process loop") defer s.logger.Info().Msg("process loop stopped") for { select { - case <-s.ctx.Done(): + case <-ctx.Done(): return case heightEvent, ok := <-s.heightInCh: if ok { - s.processHeightEvent(s.ctx, &heightEvent) + s.processHeightEvent(ctx, &heightEvent) } } } } -func (s *Syncer) startSyncWorkers() { +func (s *Syncer) startSyncWorkers(ctx context.Context) { s.wg.Add(3) - go s.daWorkerLoop() - go s.pendingWorkerLoop() - go s.p2pWorkerLoop() + go s.daWorkerLoop(ctx) + go s.pendingWorkerLoop(ctx) + go s.p2pWorkerLoop(ctx) } -func (s *Syncer) daWorkerLoop() { +func (s *Syncer) daWorkerLoop(ctx context.Context) { defer s.wg.Done() s.logger.Info().Msg("starting DA worker") defer s.logger.Info().Msg("DA worker stopped") for { - err := s.fetchDAUntilCaughtUp() + err := s.fetchDAUntilCaughtUp(ctx) var backoff time.Duration if err == nil { @@ -388,7 +389,7 @@ func (s *Syncer) daWorkerLoop() { } select { - case <-s.ctx.Done(): + case <-ctx.Done(): return case <-time.After(backoff): } @@ -401,11 +402,11 @@ func (s *Syncer) HasReachedDAHead() bool { return s.daHeadReached.Load() } -func (s *Syncer) fetchDAUntilCaughtUp() error { +func (s *Syncer) fetchDAUntilCaughtUp(ctx context.Context) error { for { select { - case <-s.ctx.Done(): - return s.ctx.Err() + case <-ctx.Done(): + return ctx.Err() default: } @@ -423,7 +424,7 @@ func (s *Syncer) fetchDAUntilCaughtUp() error { daHeight = max(s.daRetrieverHeight.Load(), s.cache.DaHeight()) } - events, err := s.daRetriever.RetrieveFromDA(s.ctx, daHeight) + events, err := s.daRetriever.RetrieveFromDA(ctx, daHeight) if err != nil { switch { case errors.Is(err, datypes.ErrBlobNotFound): @@ -445,7 +446,7 @@ func (s *Syncer) fetchDAUntilCaughtUp() error { // Process DA events for _, event := range events { - if err := s.pipeEvent(s.ctx, event); err != nil { + if err := s.pipeEvent(ctx, event); err != nil { return err } } @@ -466,7 +467,7 @@ func (s *Syncer) fetchDAUntilCaughtUp() error { } } -func (s *Syncer) pendingWorkerLoop() { +func (s *Syncer) pendingWorkerLoop(ctx context.Context) { defer s.wg.Done() s.logger.Info().Msg("starting pending worker") @@ -477,15 +478,15 @@ func (s *Syncer) pendingWorkerLoop() { for { select { - case <-s.ctx.Done(): + case <-ctx.Done(): return case <-ticker.C: - s.processPendingEvents() + s.processPendingEvents(ctx) } } } -func (s *Syncer) p2pWorkerLoop() { +func (s *Syncer) p2pWorkerLoop(ctx context.Context) { defer s.wg.Done() logger := s.logger.With().Str("worker", "p2p").Logger() @@ -494,22 +495,22 @@ func (s *Syncer) p2pWorkerLoop() { for { select { - case <-s.ctx.Done(): + case <-ctx.Done(): return default: } - currentHeight, err := s.store.Height(s.ctx) + currentHeight, err := s.store.Height(ctx) if err != nil { logger.Error().Err(err).Msg("failed to get current height for P2P worker") - if !s.sleepOrDone(50 * time.Millisecond) { + if !s.sleepOrDone(ctx, 50*time.Millisecond) { return } continue } targetHeight := currentHeight + 1 - waitCtx, cancel := context.WithCancel(s.ctx) + waitCtx, cancel := context.WithCancel(ctx) s.setP2PWaitState(targetHeight, cancel) err = s.p2pHandler.ProcessHeight(waitCtx, targetHeight, s.heightInCh) @@ -524,13 +525,13 @@ func (s *Syncer) p2pWorkerLoop() { logger.Warn().Err(err).Uint64("height", targetHeight).Msg("P2P handler failed to process height") } - if !s.sleepOrDone(50 * time.Millisecond) { + if !s.sleepOrDone(ctx, 50*time.Millisecond) { return } continue } - if err := s.waitForStoreHeight(targetHeight); err != nil { + if err := s.waitForStoreHeight(ctx, targetHeight); err != nil { if errors.Is(err, context.Canceled) { return } @@ -879,7 +880,7 @@ func (s *Syncer) ValidateBlock(_ context.Context, currState types.State, data *t // Set custom verifier for aggregator node signature header.SetCustomVerifierForSyncNode(s.options.SyncNodeSignatureBytesProvider) - if err := header.ValidateBasicWithData(data); err != nil { + if err := header.ValidateBasicWithData(data); err != nil { //nolint:contextcheck // validation API does not accept context return fmt.Errorf("invalid header: %w", err) } @@ -1077,8 +1078,8 @@ func (s *Syncer) sendCriticalError(err error) { // processPendingEvents fetches and processes pending events from cache // optimistically fetches the next events from cache until no matching heights are found -func (s *Syncer) processPendingEvents() { - currentHeight, err := s.store.Height(s.ctx) +func (s *Syncer) processPendingEvents(ctx context.Context) { + currentHeight, err := s.store.Height(ctx) if err != nil { s.logger.Error().Err(err).Msg("failed to get current height for pending events") return @@ -1103,7 +1104,7 @@ func (s *Syncer) processPendingEvents() { case s.heightInCh <- heightEvent: // Event was successfully sent and already removed by GetNextPendingEvent s.logger.Debug().Uint64("height", nextHeight).Msg("sent pending event to processing") - case <-s.ctx.Done(): + case <-ctx.Done(): s.cache.SetPendingEvent(nextHeight, event) return default: @@ -1115,9 +1116,9 @@ func (s *Syncer) processPendingEvents() { } } -func (s *Syncer) waitForStoreHeight(target uint64) error { +func (s *Syncer) waitForStoreHeight(ctx context.Context, target uint64) error { for { - currentHeight, err := s.store.Height(s.ctx) + currentHeight, err := s.store.Height(ctx) if err != nil { return err } @@ -1126,20 +1127,20 @@ func (s *Syncer) waitForStoreHeight(target uint64) error { return nil } - if !s.sleepOrDone(10 * time.Millisecond) { - if s.ctx.Err() != nil { - return s.ctx.Err() + if !s.sleepOrDone(ctx, 10*time.Millisecond) { + if ctx.Err() != nil { + return ctx.Err() } } } } -func (s *Syncer) sleepOrDone(duration time.Duration) bool { +func (s *Syncer) sleepOrDone(ctx context.Context, duration time.Duration) bool { timer := time.NewTimer(duration) defer timer.Stop() select { - case <-s.ctx.Done(): + case <-ctx.Done(): return false case <-timer.C: return true @@ -1226,10 +1227,7 @@ func (s *Syncer) RecoverFromRaft(ctx context.Context, raftState *raft.RaftBlockS s.logger.Debug().Err(err).Msg("no state in store, using genesis defaults for recovery") currentState = types.State{ ChainID: s.genesis.ChainID, - InitialHeight: s.genesis.InitialHeight, LastBlockHeight: s.genesis.InitialHeight - 1, - LastBlockTime: s.genesis.StartTime, - DAHeight: s.genesis.DAStartHeight, } } } diff --git a/block/internal/syncing/syncer_backoff_test.go b/block/internal/syncing/syncer_backoff_test.go index d6c6689f29..c2bed9385d 100644 --- a/block/internal/syncing/syncer_backoff_test.go +++ b/block/internal/syncing/syncer_backoff_test.go @@ -121,7 +121,7 @@ func TestSyncer_BackoffOnDAError(t *testing.T) { } // Run sync loop - syncer.startSyncWorkers() + syncer.startSyncWorkers(ctx) <-ctx.Done() syncer.wg.Wait() @@ -220,10 +220,10 @@ func TestSyncer_BackoffResetOnSuccess(t *testing.T) { Return(nil, datypes.ErrBlobNotFound).Once() // Start process loop to handle events - go syncer.processLoop() + go syncer.processLoop(ctx) // Run workers - syncer.startSyncWorkers() + syncer.startSyncWorkers(ctx) <-ctx.Done() syncer.wg.Wait() @@ -293,8 +293,8 @@ func TestSyncer_BackoffBehaviorIntegration(t *testing.T) { }). Return(nil, datypes.ErrBlobNotFound).Once() - go syncer.processLoop() - syncer.startSyncWorkers() + go syncer.processLoop(ctx) + syncer.startSyncWorkers(ctx) <-ctx.Done() syncer.wg.Wait() diff --git a/block/internal/syncing/syncer_benchmark_test.go b/block/internal/syncing/syncer_benchmark_test.go index 330afc2e53..6ca482c05b 100644 --- a/block/internal/syncing/syncer_benchmark_test.go +++ b/block/internal/syncing/syncer_benchmark_test.go @@ -43,8 +43,8 @@ func BenchmarkSyncerIO(b *testing.B) { fixt := newBenchFixture(b, spec.heights, spec.shuffledTx, spec.daDelay, spec.execDelay, true) // run both loops - go fixt.s.processLoop() - fixt.s.startSyncWorkers() + go fixt.s.processLoop(fixt.s.ctx) + fixt.s.startSyncWorkers(fixt.s.ctx) require.Eventually(b, func() bool { processedHeight, _ := fixt.s.store.Height(b.Context()) diff --git a/block/internal/syncing/syncer_test.go b/block/internal/syncing/syncer_test.go index a998af8f4e..cb15c108e6 100644 --- a/block/internal/syncing/syncer_test.go +++ b/block/internal/syncing/syncer_test.go @@ -309,7 +309,7 @@ func TestSyncer_processPendingEvents(t *testing.T) { cm.SetPendingEvent(1, evt1) cm.SetPendingEvent(2, evt2) - s.processPendingEvents() + s.processPendingEvents(s.ctx) // should have forwarded height 2 and removed both select { @@ -416,8 +416,8 @@ func TestSyncLoopPersistState(t *testing.T) { }). Return(nil, datypes.ErrHeightFromFuture) - go syncerInst1.processLoop() - syncerInst1.startSyncWorkers() + go syncerInst1.processLoop(ctx) + syncerInst1.startSyncWorkers(ctx) syncerInst1.wg.Wait() requireEmptyChan(t, errorCh) @@ -480,7 +480,7 @@ func TestSyncLoopPersistState(t *testing.T) { // when it starts, it should fetch from the last height it stopped at t.Log("sync workers on instance2 started") - syncerInst2.startSyncWorkers() + syncerInst2.startSyncWorkers(ctx) syncerInst2.wg.Wait() t.Log("sync workers exited") diff --git a/node/failover.go b/node/failover.go index cc4e3b3ef1..f6e0c8d9fb 100644 --- a/node/failover.go +++ b/node/failover.go @@ -180,9 +180,9 @@ func setupFailoverState( } func (f *failoverState) Run(pCtx context.Context) (multiErr error) { - stopService := func(stoppable func(context.Context) error, name string) { + stopService := func(stoppable func(context.Context) error, name string) { //nolint:contextcheck // shutdown uses context.Background intentionally // parent context is cancelled already, so we need to create a new one - shutdownCtx, done := context.WithTimeout(context.Background(), 3*time.Second) + shutdownCtx, done := context.WithTimeout(context.Background(), 3*time.Second) //nolint:contextcheck // intentional: need fresh context for graceful shutdown after cancellation defer done() if err := stoppable(shutdownCtx); err != nil && !errors.Is(err, context.Canceled) { @@ -192,7 +192,7 @@ func (f *failoverState) Run(pCtx context.Context) (multiErr error) { cCtx, cancel := context.WithCancel(pCtx) defer cancel() wg, ctx := errgroup.WithContext(cCtx) - wg.Go(func() (rerr error) { + wg.Go(func() (rerr error) { //nolint:contextcheck // block components stop API does not accept context defer func() { if err := f.bc.Stop(); err != nil && !errors.Is(err, context.Canceled) { rerr = errors.Join(rerr, fmt.Errorf("stopping block components: %w", err)) @@ -233,7 +233,7 @@ func (f *failoverState) Run(pCtx context.Context) (multiErr error) { } wg.Go(func() error { - defer func() { + defer func() { //nolint:contextcheck // shutdown uses context.Background intentionally shutdownCtx, done := context.WithTimeout(context.Background(), 3*time.Second) defer done() _ = f.rpcServer.Shutdown(shutdownCtx) diff --git a/node/full.go b/node/full.go index 692ce67c5b..1ae9a62962 100644 --- a/node/full.go +++ b/node/full.go @@ -307,7 +307,7 @@ func (n *FullNode) Run(parentCtx context.Context) error { n.Logger.Info().Msg("halting full node and its sub services...") // Use a timeout context to ensure shutdown doesn't hang - shutdownCtx, cancel := context.WithTimeout(context.Background(), 9*time.Second) + shutdownCtx, cancel := context.WithTimeout(context.Background(), 9*time.Second) //nolint:contextcheck // intentional: need fresh context for graceful shutdown after cancellation defer cancel() var shutdownMultiErr error // Variable to accumulate multiple errors @@ -323,7 +323,7 @@ func (n *FullNode) Run(parentCtx context.Context) error { // Shutdown Prometheus Server if n.prometheusSrv != nil { - err := n.prometheusSrv.Shutdown(shutdownCtx) + err := n.prometheusSrv.Shutdown(shutdownCtx) //nolint:contextcheck // shutdownCtx is intentionally from context.Background // http.ErrServerClosed is expected on graceful shutdown if err != nil && !errors.Is(err, http.ErrServerClosed) { shutdownMultiErr = errors.Join(shutdownMultiErr, fmt.Errorf("shutting down Prometheus server: %w", err)) @@ -334,7 +334,7 @@ func (n *FullNode) Run(parentCtx context.Context) error { // Shutdown Pprof Server if n.pprofSrv != nil { - err := n.pprofSrv.Shutdown(shutdownCtx) + err := n.pprofSrv.Shutdown(shutdownCtx) //nolint:contextcheck // shutdownCtx is intentionally from context.Background if err != nil && !errors.Is(err, http.ErrServerClosed) { shutdownMultiErr = errors.Join(shutdownMultiErr, fmt.Errorf("shutting down pprof server: %w", err)) } else { diff --git a/node/full_node_test.go b/node/full_node_test.go index ec33f2156b..23c2626f40 100644 --- a/node/full_node_test.go +++ b/node/full_node_test.go @@ -40,7 +40,9 @@ func TestStartInstrumentationServer(t *testing.T) { time.Sleep(100 * time.Millisecond) - resp, err := http.Get(fmt.Sprintf("http://%s/metrics", config.Instrumentation.PrometheusListenAddr)) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s/metrics", config.Instrumentation.PrometheusListenAddr), nil) + require.NoError(err, "Failed to create Prometheus metrics request") + resp, err := http.DefaultClient.Do(req) //nolint:gosec // test-only request to local instrumentation endpoint require.NoError(err, "Failed to get Prometheus metrics") defer func() { err := resp.Body.Close() @@ -53,7 +55,9 @@ func TestStartInstrumentationServer(t *testing.T) { require.NoError(err) assert.Contains(string(body), "# HELP", "Prometheus metrics body should contain HELP lines") - resp, err = http.Get(fmt.Sprintf("http://%s/debug/pprof/", config.Instrumentation.PprofListenAddr)) + req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s/debug/pprof/", config.Instrumentation.PprofListenAddr), nil) + require.NoError(err, "Failed to create pprof request") + resp, err = http.DefaultClient.Do(req) //nolint:gosec // test-only request to local instrumentation endpoint require.NoError(err, "Failed to get Pprof index") defer func() { err := resp.Body.Close() @@ -66,7 +70,7 @@ func TestStartInstrumentationServer(t *testing.T) { require.NoError(err) assert.Contains(string(body), "Types of profiles available", "Pprof index body should contain expected text") - shutdownCtx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + shutdownCtx, cancel := context.WithTimeout(t.Context(), 1*time.Second) defer cancel() if prometheusSrv != nil { diff --git a/node/light.go b/node/light.go index 7aeb9038b6..dd1c3d61d1 100644 --- a/node/light.go +++ b/node/light.go @@ -134,13 +134,13 @@ func (ln *LightNode) Run(parentCtx context.Context) error { ln.Logger.Info().Msg("halting light node and its sub services...") - shutdownCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + shutdownCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second) //nolint:contextcheck // intentional: need fresh context for graceful shutdown after cancellation defer cancel() var multiErr error // Stop Header Sync Service - err = ln.hSyncService.Stop(shutdownCtx) + err = ln.hSyncService.Stop(shutdownCtx) //nolint:contextcheck // shutdownCtx is intentionally from context.Background if err != nil { if !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) { multiErr = errors.Join(multiErr, fmt.Errorf("stopping header sync service: %w", err)) @@ -151,7 +151,7 @@ func (ln *LightNode) Run(parentCtx context.Context) error { // Shutdown RPC Server if ln.rpcServer != nil { - err = ln.rpcServer.Shutdown(shutdownCtx) + err = ln.rpcServer.Shutdown(shutdownCtx) //nolint:contextcheck // shutdownCtx is intentionally from context.Background if err != nil && !errors.Is(err, http.ErrServerClosed) { multiErr = errors.Join(multiErr, fmt.Errorf("shutting down RPC server: %w", err)) } else { diff --git a/pkg/cmd/run_node_test.go b/pkg/cmd/run_node_test.go index cf7d9672b3..1ed1a7e189 100644 --- a/pkg/cmd/run_node_test.go +++ b/pkg/cmd/run_node_test.go @@ -648,9 +648,10 @@ func TestStartNodeErrors(t *testing.T) { } // Log level no longer needed with Nop logger - runFunc := func() { + runFunc := func(ctx context.Context) { currentTestLogger := zerolog.Nop() - err := StartNode(currentTestLogger, cmd, executor, sequencer, nodeKey, ds, nodeConfig, testGenesis, node.NodeOptions{}) + cmd.SetContext(ctx) + err := StartNode(currentTestLogger, cmd, executor, sequencer, nodeKey, ds, nodeConfig, testGenesis, node.NodeOptions{}) //nolint:contextcheck // test invokes command entrypoint directly if tc.expectedError != "" { assert.ErrorContains(t, err, tc.expectedError) } else { @@ -663,11 +664,11 @@ func TestStartNodeErrors(t *testing.T) { } if tc.expectPanic { - assert.Panics(t, runFunc) + assert.Panics(t, func() { runFunc(baseCtx) }) } else { - assert.NotPanics(t, runFunc) + assert.NotPanics(t, func() { runFunc(baseCtx) }) checkLogger := zerolog.Nop() - err := StartNode(checkLogger, cmd, executor, sequencer, nodeKey, ds, nodeConfig, testGenesis, node.NodeOptions{}) + err := StartNode(checkLogger, cmd, executor, sequencer, nodeKey, ds, nodeConfig, testGenesis, node.NodeOptions{}) //nolint:contextcheck // test invokes command entrypoint directly if tc.expectedError != "" { assert.ErrorContains(t, err, tc.expectedError) } @@ -700,7 +701,7 @@ func newRunNodeCmd( Use: "start", Aliases: []string{"node", "run"}, Short: "Run the rollkit node", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { //nolint:contextcheck // cobra RunE signature is fixed return StartNode(zerolog.Nop(), cmd, executor, sequencer, nodeKey, datastore, nodeConfig, testGenesis, node.NodeOptions{}) }, } diff --git a/pkg/p2p/client.go b/pkg/p2p/client.go index 4288f749f9..e8fc6eabe1 100644 --- a/pkg/p2p/client.go +++ b/pkg/p2p/client.go @@ -415,9 +415,10 @@ func (c *Client) GetPeers() ([]peer.AddrInfo, error) { } func (c *Client) GetNetworkInfo() (NetworkInfo, error) { - var addrs []string + hostAddrs := c.host.Addrs() + addrs := make([]string, 0, len(hostAddrs)) peerIDSuffix := "/p2p/" + c.host.ID().String() - for _, a := range c.host.Addrs() { + for _, a := range hostAddrs { addr := a.String() // Only append peer ID if not already present if !strings.HasSuffix(addr, peerIDSuffix) { diff --git a/pkg/p2p/client_test.go b/pkg/p2p/client_test.go index 0f8f9850e7..e3ac6f1fab 100644 --- a/pkg/p2p/client_test.go +++ b/pkg/p2p/client_test.go @@ -286,7 +286,6 @@ func TestClientInfoMethods(t *testing.T) { tempDir := t.TempDir() ClientInitFiles(t, tempDir) conf := config.DefaultConfig() - conf.RootDir = tempDir mn := mocknet.New() defer mn.Close() diff --git a/pkg/rpc/server/da_visualization_non_aggregator_test.go b/pkg/rpc/server/da_visualization_non_aggregator_test.go index 2094684893..0d157deb6a 100644 --- a/pkg/rpc/server/da_visualization_non_aggregator_test.go +++ b/pkg/rpc/server/da_visualization_non_aggregator_test.go @@ -33,7 +33,7 @@ func TestNonAggregatorHandleDASubmissions(t *testing.T) { server := NewDAVisualizationServer(da, logger, false) // Create test request - req, err := http.NewRequest("GET", "/da/submissions", nil) + req, err := http.NewRequest(http.MethodGet, "/da/submissions", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -63,7 +63,7 @@ func TestNonAggregatorHandleDAStats(t *testing.T) { server := NewDAVisualizationServer(da, logger, false) // Create test request - req, err := http.NewRequest("GET", "/da/stats", nil) + req, err := http.NewRequest(http.MethodGet, "/da/stats", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -89,7 +89,7 @@ func TestNonAggregatorHandleDAHealth(t *testing.T) { server := NewDAVisualizationServer(da, logger, false) // Create test request - req, err := http.NewRequest("GET", "/da/health", nil) + req, err := http.NewRequest(http.MethodGet, "/da/health", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -115,7 +115,7 @@ func TestNonAggregatorHandleDAVisualizationHTML(t *testing.T) { // Create a non-aggregator server server := NewDAVisualizationServer(da, logger, false) - req, err := http.NewRequest("GET", "/da", nil) + req, err := http.NewRequest(http.MethodGet, "/da", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -144,7 +144,7 @@ func TestAggregatorWithNoSubmissionsHTML(t *testing.T) { // Create an aggregator server but don't add any submissions server := NewDAVisualizationServer(da, logger, true) - req, err := http.NewRequest("GET", "/da", nil) + req, err := http.NewRequest(http.MethodGet, "/da", nil) require.NoError(t, err) rr := httptest.NewRecorder() diff --git a/pkg/rpc/server/da_visualization_test.go b/pkg/rpc/server/da_visualization_test.go index 9be3ba4c88..e2bb6c0ea4 100644 --- a/pkg/rpc/server/da_visualization_test.go +++ b/pkg/rpc/server/da_visualization_test.go @@ -133,7 +133,7 @@ func TestHandleDASubmissions(t *testing.T) { }, } server.RecordSubmission(result, 0.5, 1, []byte{}) - req, err := http.NewRequest("GET", "/da/submissions", nil) + req, err := http.NewRequest(http.MethodGet, "/da/submissions", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -163,7 +163,7 @@ func TestHandleDABlobDetailsMissingID(t *testing.T) { logger := zerolog.New(nil) server := NewDAVisualizationServer(da, logger, true) - req, err := http.NewRequest("GET", "/da/blob", nil) + req, err := http.NewRequest(http.MethodGet, "/da/blob", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -178,7 +178,7 @@ func TestHandleDABlobDetailsInvalidID(t *testing.T) { logger := zerolog.New(nil) server := NewDAVisualizationServer(da, logger, true) - req, err := http.NewRequest("GET", "/da/blob?id=invalid-hex", nil) + req, err := http.NewRequest(http.MethodGet, "/da/blob?id=invalid-hex", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -205,7 +205,7 @@ func TestHandleDAVisualizationHTML(t *testing.T) { } server.RecordSubmission(result, 0.5, 1, []byte{}) - req, err := http.NewRequest("GET", "/da", nil) + req, err := http.NewRequest(http.MethodGet, "/da", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -265,7 +265,7 @@ func TestRegisterCustomHTTPEndpointsDAVisualization(t *testing.T) { RegisterCustomHTTPEndpoints(mux, nil, nil, config.DefaultConfig(), nil, nopLogger, nil) // Test /da endpoint - req, err := http.NewRequest("GET", "/da", nil) + req, err := http.NewRequest(http.MethodGet, "/da", nil) require.NoError(t, err) rr := httptest.NewRecorder() @@ -275,7 +275,7 @@ func TestRegisterCustomHTTPEndpointsDAVisualization(t *testing.T) { assert.Equal(t, "text/html", rr.Header().Get("Content-Type")) // Test /da/submissions endpoint - req, err = http.NewRequest("GET", "/da/submissions", nil) + req, err = http.NewRequest(http.MethodGet, "/da/submissions", nil) require.NoError(t, err) rr = httptest.NewRecorder() @@ -285,7 +285,7 @@ func TestRegisterCustomHTTPEndpointsDAVisualization(t *testing.T) { assert.Equal(t, "application/json", rr.Header().Get("Content-Type")) // Test /da/blob endpoint (missing ID should return 400) - req, err = http.NewRequest("GET", "/da/blob", nil) + req, err = http.NewRequest(http.MethodGet, "/da/blob", nil) require.NoError(t, err) rr = httptest.NewRecorder() @@ -306,7 +306,7 @@ func TestRegisterCustomHTTPEndpointsWithoutServer(t *testing.T) { endpoints := []string{"/da", "/da/submissions", "/da/blob"} for _, endpoint := range endpoints { - req, err := http.NewRequest("GET", endpoint, nil) + req, err := http.NewRequest(http.MethodGet, endpoint, nil) require.NoError(t, err) rr := httptest.NewRecorder() diff --git a/pkg/rpc/server/http_test.go b/pkg/rpc/server/http_test.go index dc241a65af..4fa2e92e17 100644 --- a/pkg/rpc/server/http_test.go +++ b/pkg/rpc/server/http_test.go @@ -29,7 +29,9 @@ func TestRegisterCustomHTTPEndpoints(t *testing.T) { testServer := httptest.NewServer(mux) defer testServer.Close() - resp, err := http.Get(testServer.URL + "/health/live") + req, err := http.NewRequest(http.MethodGet, testServer.URL+"/health/live", nil) + assert.NoError(t, err) + resp, err := http.DefaultClient.Do(req) //nolint:gosec // test-only request to httptest server assert.NoError(t, err) defer resp.Body.Close() @@ -44,7 +46,6 @@ func TestRegisterCustomHTTPEndpoints(t *testing.T) { } func TestHealthReady_aggregatorBlockDelay(t *testing.T) { - ctx := t.Context() logger := zerolog.Nop() type spec struct { @@ -119,7 +120,7 @@ func TestHealthReady_aggregatorBlockDelay(t *testing.T) { ts := httptest.NewServer(mux) t.Cleanup(ts.Close) - req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL+"/health/ready", nil) + req, err := http.NewRequest(http.MethodGet, ts.URL+"/health/ready", nil) require.NoError(t, err) resp, err := http.DefaultClient.Do(req) //nolint:gosec // ok to use default client in tests require.NoError(t, err) diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index ddd50b550e..73d03059be 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -28,6 +28,13 @@ import ( pb "github.com/evstack/ev-node/types/pb/evnode/v1" ) +func mustGETRequest(t *testing.T, url string) *http.Request { + t.Helper() + req, err := http.NewRequest(http.MethodGet, url, nil) + require.NoError(t, err) + return req +} + func TestGetBlock(t *testing.T) { // Create a mock store mockStore := mocks.NewMockStore(t) @@ -422,7 +429,7 @@ func TestHealthLiveEndpoint(t *testing.T) { server := httptest.NewServer(handler) defer server.Close() - resp, err := http.Get(server.URL + "/health/live") + resp, err := http.DefaultClient.Do(mustGETRequest(t, server.URL+"/health/live")) //nolint:gosec // test-only request to httptest server require.NoError(t, err) defer resp.Body.Close() @@ -447,7 +454,7 @@ func TestHealthLiveEndpoint(t *testing.T) { server := httptest.NewServer(handler) defer server.Close() - resp, err := http.Get(server.URL + "/health/live") + resp, err := http.DefaultClient.Do(mustGETRequest(t, server.URL+"/health/live")) //nolint:gosec // test-only request to httptest server require.NoError(t, err) defer resp.Body.Close() @@ -472,7 +479,7 @@ func TestHealthLiveEndpoint(t *testing.T) { server := httptest.NewServer(handler) defer server.Close() - resp, err := http.Get(server.URL + "/health/live") + resp, err := http.DefaultClient.Do(mustGETRequest(t, server.URL+"/health/live")) //nolint:gosec // test-only request to httptest server require.NoError(t, err) defer resp.Body.Close() @@ -548,7 +555,7 @@ func TestHealthReadyEndpoint(t *testing.T) { server := httptest.NewServer(handler) defer server.Close() - resp, err := http.Get(server.URL + "/health/ready") + resp, err := http.DefaultClient.Do(mustGETRequest(t, server.URL+"/health/ready")) //nolint:gosec // test-only request to httptest server require.NoError(t, err) defer resp.Body.Close() require.Equal(t, tc.expectedCode, resp.StatusCode) @@ -589,7 +596,7 @@ func TestHealthReadyEndpoint(t *testing.T) { server := httptest.NewServer(handler) defer server.Close() - resp, err := http.Get(server.URL + "/health/ready") + resp, err := http.DefaultClient.Do(mustGETRequest(t, server.URL+"/health/ready")) //nolint:gosec // test-only request to httptest server require.NoError(t, err) defer resp.Body.Close() require.Equal(t, http.StatusOK, resp.StatusCode) @@ -619,7 +626,7 @@ func TestHealthReadyEndpoint(t *testing.T) { server := httptest.NewServer(handler) defer server.Close() - resp, err := http.Get(server.URL + "/health/ready") + resp, err := http.DefaultClient.Do(mustGETRequest(t, server.URL+"/health/ready")) //nolint:gosec // test-only request to httptest server require.NoError(t, err) defer resp.Body.Close() require.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) diff --git a/pkg/store/store_adapter_test.go b/pkg/store/store_adapter_test.go index c0427ddbf0..ce1420c7e3 100644 --- a/pkg/store/store_adapter_test.go +++ b/pkg/store/store_adapter_test.go @@ -568,7 +568,7 @@ func TestStoreAdapter_ConcurrentAppendAndRead(t *testing.T) { go func() { defer wg.Done() for i := range itemsPerWriter * numWriters { - _ = adapter.Height() + _ = adapter.Height() //nolint:contextcheck // external interface does not accept context _, _ = adapter.Head(ctx) _ = adapter.HasAt(ctx, uint64(i+1)) } diff --git a/pkg/telemetry/tracing.go b/pkg/telemetry/tracing.go index 06e3f04ad6..520c84f520 100644 --- a/pkg/telemetry/tracing.go +++ b/pkg/telemetry/tracing.go @@ -66,12 +66,12 @@ func InitTracing(ctx context.Context, cfg *config.InstrumentationConfig, logger return tp.Shutdown, nil } -func clamp(x, min, max float64) float64 { - if x < min { - return min +func clamp(x, minFloat, maxFloat float64) float64 { + if x < minFloat { + return minFloat } - if x > max { - return max + if x > maxFloat { + return maxFloat } return x } diff --git a/scripts/test.go b/scripts/test.go index 43f921ce26..29f35e6811 100644 --- a/scripts/test.go +++ b/scripts/test.go @@ -29,8 +29,8 @@ func main() { // For this example, we'll run tests in all directories with go.mod. fmt.Printf("--> Running tests in: %s\n", modDir) - cmd := exec.Command("go", "test", "./...", "-cover") - cmd.Dir = modDir // Set the working directory for the command + cmd := exec.Command("go", "test", "./...", "-cover") //nolint:noctx // intentionally runs module-local test command + cmd.Dir = modDir // Set the working directory for the command cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/test/e2e/failover_e2e_test.go b/test/e2e/failover_e2e_test.go index 1f92723a6c..36120fc523 100644 --- a/test/e2e/failover_e2e_test.go +++ b/test/e2e/failover_e2e_test.go @@ -219,20 +219,15 @@ func TestLeaseFailoverE2E(t *testing.T) { return err == nil }, time.Second, 100*time.Millisecond) - lastDABlockNewLeader = queryLastDAHeight(t, env.SequencerJWT, env.Endpoints.GetDAAddress()) - genesisHeight := state.InitialHeight verifyNoDoubleSigning(t, clusterNodes, genesisHeight, state.LastBlockHeight) - // wait for the next DA block to ensure all blocks are propagated - require.Eventually(t, func() bool { - before := lastDABlockNewLeader - lastDABlockNewLeader = queryLastDAHeight(t, env.SequencerJWT, env.Endpoints.GetDAAddress()) - return before < lastDABlockNewLeader - }, 2*must(time.ParseDuration(DefaultDABlockTime)), 100*time.Millisecond) - + // wait for the DA submitter to catch up — poll until all blocks are on DA t.Log("+++ Verifying no DA gaps...") - verifyDABlocks(t, 1, lastDABlockNewLeader, env.SequencerJWT, env.Endpoints.GetDAAddress(), genesisHeight, state.LastBlockHeight) + require.EventuallyWithT(t, func(collect *assert.CollectT) { + lastDA := queryLastDAHeight(t, env.SequencerJWT, env.Endpoints.GetDAAddress()) + verifyDABlocksCollect(collect, 1, lastDA, env.SequencerJWT, env.Endpoints.GetDAAddress(), genesisHeight, state.LastBlockHeight) + }, 3*must(time.ParseDuration(DefaultDABlockTime)), 500*time.Millisecond) // Cleanup processes clusterNodes.killAll() @@ -508,22 +503,16 @@ func TestHASequencerRollingRestartE2E(t *testing.T) { return err == nil }, time.Second, 100*time.Millisecond) - lastDABlock := queryLastDAHeight(t, env.SequencerJWT, env.Endpoints.GetDAAddress()) - genesisHeight := state.InitialHeight verifyNoDoubleSigning(t, clusterNodes, genesisHeight, state.LastBlockHeight) t.Log("+++ No double-signing detected ✓") - // Wait for the next DA block to ensure all blocks are propagated - require.Eventually(t, func() bool { - before := lastDABlock - lastDABlock = queryLastDAHeight(t, env.SequencerJWT, env.Endpoints.GetDAAddress()) - return before < lastDABlock - }, 2*must(time.ParseDuration(DefaultDABlockTime)), 100*time.Millisecond) - - // Verify no DA gaps + // Wait for the DA submitter to catch up — poll until all blocks are on DA t.Log("+++ Verifying no DA gaps...") - verifyDABlocks(t, 1, lastDABlock, env.SequencerJWT, env.Endpoints.GetDAAddress(), genesisHeight, state.LastBlockHeight) + require.EventuallyWithT(t, func(collect *assert.CollectT) { + lastDA := queryLastDAHeight(t, env.SequencerJWT, env.Endpoints.GetDAAddress()) + verifyDABlocksCollect(collect, 1, lastDA, env.SequencerJWT, env.Endpoints.GetDAAddress(), genesisHeight, state.LastBlockHeight) + }, 3*must(time.ParseDuration(DefaultDABlockTime)), 500*time.Millisecond) t.Log("+++ No DA gaps detected ✓") // Cleanup processes @@ -611,6 +600,80 @@ func verifyDABlocks(t *testing.T, daStartHeight, lastDABlock uint64, jwtSecret s } } +// verifyDABlocksCollect is like verifyDABlocks but uses assert.CollectT so it can be retried +// inside require.EventuallyWithT. +func verifyDABlocksCollect(collect *assert.CollectT, daStartHeight, lastDABlock uint64, jwtSecret string, daAddress string, genesisHeight, lastEVBlock uint64) { + ctx := context.Background() + blobClient, err := blobrpc.NewClient(ctx, daAddress, jwtSecret, "") + if !assert.NoError(collect, err) { + return + } + defer blobClient.Close() + + ns, err := libshare.NewNamespaceFromBytes(coreda.NamespaceFromString(DefaultDANamespace).Bytes()) + if !assert.NoError(collect, err) { + return + } + evHeightsToEvBlockParts := make(map[uint64]int) + deduplicationCache := make(map[string]uint64) + + for daHeight := daStartHeight; daHeight <= lastDABlock; daHeight++ { + blobs, err := blobClient.Blob.GetAll(ctx, daHeight, []libshare.Namespace{ns}) + if err != nil { + if strings.Contains(err.Error(), "blob: not found") { + continue + } + assert.NoError(collect, err, "height %d/%d", daHeight, lastDABlock) + return + } + if len(blobs) == 0 { + continue + } + + for _, blob := range blobs { + if evHeight, hash, blobType := extractBlockHeightRaw(blob.Data()); evHeight != 0 { + _ = blobType + if height, ok := deduplicationCache[hash.String()]; ok { + assert.Equal(collect, evHeight, height) + continue + } + assert.GreaterOrEqual(collect, evHeight, genesisHeight) + deduplicationCache[hash.String()] = evHeight + evHeightsToEvBlockParts[evHeight]++ + } + } + } + + for h := genesisHeight; h <= lastEVBlock; h++ { + assert.NotEmpty(collect, evHeightsToEvBlockParts[h], "missing block on DA for height %d/%d", h, lastEVBlock) + assert.Less(collect, evHeightsToEvBlockParts[h], 3, "duplicate block on DA for height %d/%d", h, lastEVBlock) + } +} + +// extractBlockHeightRaw is like extractBlockHeight but doesn't require *testing.T. +func extractBlockHeightRaw(blob []byte) (uint64, types.Hash, string) { + if len(blob) == 0 { + return 0, nil, "" + } + var headerPb pb.SignedHeader + if err := proto.Unmarshal(blob, &headerPb); err == nil { + var signedHeader types.SignedHeader + if err := signedHeader.FromProto(&headerPb); err == nil { + if err := signedHeader.Header.ValidateBasic(); err == nil { + return signedHeader.Height(), signedHeader.Hash(), "header" + } + } + } + + var signedData types.SignedData + if err := signedData.UnmarshalBinary(blob); err == nil { + if signedData.Metadata != nil { + return signedData.Height(), signedData.Hash(), "data" + } + } + return 0, nil, "" +} + // extractBlockHeight attempts to decode a blob as SignedHeader or SignedData and extract the block height func extractBlockHeight(t *testing.T, blob []byte) (uint64, types.Hash, string) { t.Helper() diff --git a/tools/blob-decoder/main.go b/tools/blob-decoder/main.go index 20ad5b92c9..da2322f1df 100644 --- a/tools/blob-decoder/main.go +++ b/tools/blob-decoder/main.go @@ -81,7 +81,7 @@ func corsMiddleware(next http.Handler) http.Handler { w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") - if r.Method == "OPTIONS" { + if r.Method == http.MethodOptions { w.WriteHeader(http.StatusOK) return } @@ -99,7 +99,7 @@ func handleIndex(w http.ResponseWriter, r *http.Request) { } func handleDecode(w http.ResponseWriter, r *http.Request) { - if r.Method != "POST" { + if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } diff --git a/tools/local-da/rpc.go b/tools/local-da/rpc.go index 6f681d6538..c8a3c97bee 100644 --- a/tools/local-da/rpc.go +++ b/tools/local-da/rpc.go @@ -111,8 +111,8 @@ func (s *blobServer) GetProof(_ context.Context, _ uint64, _ libshare.Namespace, } // Included reports whether a commitment is present at a given height/namespace. -func (s *blobServer) Included(_ context.Context, height uint64, namespace libshare.Namespace, _ *jsonrpc.Proof, commitment jsonrpc.Commitment) (bool, error) { - _, err := s.Get(context.Background(), height, namespace, commitment) +func (s *blobServer) Included(ctx context.Context, height uint64, namespace libshare.Namespace, _ *jsonrpc.Proof, commitment jsonrpc.Commitment) (bool, error) { + _, err := s.Get(ctx, height, namespace, commitment) if err != nil { if errors.Is(err, datypes.ErrBlobNotFound) { return false, nil