diff --git a/beacon-chain/sync/batch_verifier.go b/beacon-chain/sync/batch_verifier.go index f9979f0a8e..e5e4926d5b 100644 --- a/beacon-chain/sync/batch_verifier.go +++ b/beacon-chain/sync/batch_verifier.go @@ -163,11 +163,15 @@ func (s *Service) validateWithKzgBatchVerifier(ctx context.Context, dataColumns resChan := make(chan error, 1) verificationSet := &kzgVerifier{dataColumns: dataColumns, resChan: resChan} - s.kzgChan <- verificationSet - ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() + select { + case s.kzgChan <- verificationSet: + case <-ctx.Done(): + return pubsub.ValidationIgnore, ctx.Err() + } + select { case <-ctx.Done(): return pubsub.ValidationIgnore, ctx.Err() // parent context canceled, give up diff --git a/beacon-chain/sync/kzg_batch_verifier_test.go b/beacon-chain/sync/kzg_batch_verifier_test.go index 80ce24fe6f..97cbe48808 100644 --- a/beacon-chain/sync/kzg_batch_verifier_test.go +++ b/beacon-chain/sync/kzg_batch_verifier_test.go @@ -304,6 +304,36 @@ func TestValidateWithKzgBatchVerifier_DeadlockOnTimeout(t *testing.T) { } } +func TestValidateWithKzgBatchVerifier_ContextCanceledBeforeSend(t *testing.T) { + cancelledCtx, cancel := context.WithCancel(t.Context()) + cancel() + + service := &Service{ + ctx: context.Background(), + kzgChan: make(chan *kzgVerifier), + } + + done := make(chan struct{}) + go func() { + result, err := service.validateWithKzgBatchVerifier(cancelledCtx, nil) + require.Equal(t, pubsub.ValidationIgnore, result) + require.ErrorIs(t, err, context.Canceled) + close(done) + }() + + select { + case <-done: + case <-time.After(500 * time.Millisecond): + t.Fatal("validateWithKzgBatchVerifier did not return after context cancellation") + } + + select { + case <-service.kzgChan: + t.Fatal("verificationSet was sent to kzgChan despite canceled context") + default: + } +} + func createValidTestDataColumns(t *testing.T, count int) []blocks.RODataColumn { _, roSidecars, _ := util.GenerateTestFuluBlockWithSidecars(t, count) if len(roSidecars) >= count { diff --git a/changelog/avoid_kzg_send_after_context_cancel.md b/changelog/avoid_kzg_send_after_context_cancel.md new file mode 100644 index 0000000000..ac5d5549e5 --- /dev/null +++ b/changelog/avoid_kzg_send_after_context_cancel.md @@ -0,0 +1,3 @@ +### Fixed + +- Prevent blocked sends to the KZG batch verifier when the caller context is already canceled, avoiding useless queueing and potential hangs.