@@ -10,6 +10,7 @@ import (
1010 "runtime/debug"
1111 "sort"
1212 "sync"
13+ "sync/atomic"
1314 "time"
1415
1516 "github.com/cometbft/cometbft/privval"
@@ -145,9 +146,10 @@ type State struct {
145146 nSteps int
146147
147148 // some functions can be overwritten for testing
148- decideProposal func (height int64 , round int32 )
149- doPrevote func (height int64 , round int32 )
150- setProposal func (proposal * types.Proposal ) error
149+ decideProposal func (height int64 , round int32 )
150+ doPrevote func (height int64 , round int32 )
151+ setProposal func (proposal * types.Proposal ) error
152+ StartedPrecommitSleep atomic.Bool
151153
152154 // closed when we finish shutting down
153155 done chan struct {}
@@ -1627,9 +1629,22 @@ func (cs *State) enterPrecommit(height int64, round int32) {
16271629 return
16281630 }
16291631
1630- if ready , waitTime := cs .isReadyToPrecommit (); ! ready {
1631- logger .Trace ("rescheduling precommit" , "delay(ms)" , waitTime .Milliseconds ())
1632- cs .scheduleTimeout (waitTime , height , round , cstypes .RoundStepPrevoteWait )
1632+ if cs .StartedPrecommitSleep .CompareAndSwap (false , true ) {
1633+ waitTime := cs .precommitDelay ()
1634+ logger .Debug ("delaying precommit" , "delay" , waitTime )
1635+ cs .unlockAll ()
1636+ t := time .NewTimer (waitTime )
1637+ select {
1638+ case <- cs .Quit ():
1639+ cs .lockAll ()
1640+ return
1641+ case <- t .C :
1642+ }
1643+ cs .lockAll ()
1644+ cs .StartedPrecommitSleep .Store (false )
1645+ } else {
1646+ logger .Debug ("already entered precommit delay" )
1647+ // if any other routine tries to enter precommit, we just return
16331648 return
16341649 }
16351650
@@ -2110,20 +2125,20 @@ func (cs *State) recordMetrics(height int64, block *types.Block) {
21102125// KMSSigningDelay is a constant representing a delay used primarily to adjust for KMS signing latencies.
21112126const KMSSigningDelay = 200 * time .Millisecond
21122127
2113- // isReadyToPrecommit calculates if the process has waited at least a certain number of seconds
2128+ // precommitDelay calculates if the process has waited at least a certain number of seconds
21142129// from their start time before they can vote
21152130// If the application's DelayedPrecommitTimeout is set to 0, no precommit wait is done.
2116- func (cs * State ) isReadyToPrecommit () ( bool , time.Duration ) {
2131+ func (cs * State ) precommitDelay () time.Duration {
21172132 if cs .state .Timeouts .DelayedPrecommitTimeout == 0 {
21182133 // setting 0 as a special case not to reschedule the pre-commit
2119- return true , 0
2134+ return 0
21202135 }
21212136 precommitVoteTime := cs .rs .StartTime .Add (cs .state .Timeouts .DelayedPrecommitTimeout )
21222137 waitTime := time .Until (precommitVoteTime )
21232138 if _ , ok := cs .privValidator .(* privval.SignerClient ); ok {
21242139 waitTime = waitTime - KMSSigningDelay
21252140 }
2126- return waitTime <= 0 , waitTime
2141+ return waitTime
21272142}
21282143
21292144//-----------------------------------------------------------------------------
0 commit comments