From 15b4fb59d897ef054f03928a6ee6254ad485cdd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ois=C3=ADn=20Kyne?= Date: Tue, 10 Mar 2026 23:08:24 +0000 Subject: [PATCH] Fix race condition --- core/qbft/qbft.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/core/qbft/qbft.go b/core/qbft/qbft.go index f1093f02a..fa7faf8e3 100644 --- a/core/qbft/qbft.go +++ b/core/qbft/qbft.go @@ -459,8 +459,22 @@ func compare[I any, V comparable, C any](ctx context.Context, d Definition[I, V, return inputValueSource, nil case inputValueSource = <-compareValue: case <-timerChan: - log.Warn(ctx, "", errors.New("timeout waiting for local data, used for comparing with leader's proposed data")) - return inputValueSource, errTimeout + // When the eager timer fires at an absolute deadline, d.Compare may have + // already completed (e.g. instantly when compareAttestations is disabled). + // Go's select picks randomly among ready channels, so check compareErr + // before declaring a timeout to avoid spurious round changes. + select { + case err := <-compareErr: + if err != nil { + log.Warn(ctx, errCompare.Error(), err) + return inputValueSource, errCompare + } + + return inputValueSource, nil + default: + log.Warn(ctx, "", errors.New("timeout waiting for local data, used for comparing with leader's proposed data")) + return inputValueSource, errTimeout + } } } }