@@ -402,13 +402,30 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head
402402 number := header .Number .Uint64 ()
403403 now := uint64 (time .Now ().Unix ())
404404
405- // Allow early blocks if Bhilai HF is enabled
406- if c .config .IsBhilai (header .Number ) {
405+ if c .config .IsRio (header .Number ) {
406+ // Rio HF introduced flexible blocktime (can be set larger than consensus without approval).
407+ // Using strict CalcProducerDelay would reject valid blocks, so we just ensure announcement
408+ // time comes after parent time to allow for flexible blocktime.
409+ var parent * types.Header
410+
411+ if len (parents ) > 0 {
412+ parent = parents [len (parents )- 1 ]
413+ } else {
414+ parent = chain .GetHeader (header .ParentHash , number - 1 )
415+ }
416+ if parent == nil || now < parent .Time {
417+ log .Error ("Block announced too early post rio" , "number" , number , "headerTime" , header .Time , "now" , now )
418+ return consensus .ErrFutureBlock
419+ }
420+ } else if c .config .IsBhilai (header .Number ) {
421+ // Allow early blocks if Bhilai HF is enabled
407422 // Don't waste time checking blocks from the future but allow a buffer of block time for
408423 // early block announcements. Note that this is a loose check and would allow early blocks
409424 // from non-primary producer. Such blocks will be rejected later when we know the succession
410425 // number of the signer in the current sprint.
411- if header .Time - c .config .CalculatePeriod (number ) > now {
426+ // Uses CalcProducerDelay instead of block period to account for producer delay on sprint start blocks.
427+ // We assume succession 0 (primary producer) to not be much restrictive for early block announcements.
428+ if header .Time - CalcProducerDelay (number , 0 , c .config ) > now {
412429 log .Error ("Block announced too early post bhilai" , "number" , number , "headerTime" , header .Time , "now" , now )
413430 return consensus .ErrFutureBlock
414431 }
@@ -476,7 +493,18 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head
476493 return err
477494 }
478495
479- c .recentVerifiedHeaders .Set (header .Hash (), header , ttlcache .DefaultTTL )
496+ // Calculate TTL for the header cache entry
497+ // If the header time is in the future (early announced block), add extra time to TTL
498+ cacheTTL := veblopBlockTimeout
499+ nowTime := time .Now ()
500+ headerTime := time .Unix (int64 (header .Time ), 0 )
501+ if headerTime .After (nowTime ) {
502+ // Add the time from now until header time as extra to the base timeout
503+ extraTime := headerTime .Sub (nowTime )
504+ cacheTTL = veblopBlockTimeout + extraTime
505+ }
506+
507+ c .recentVerifiedHeaders .Set (header .Hash (), header , cacheTTL )
480508 return nil
481509}
482510
@@ -928,7 +956,7 @@ func IsBlockEarly(parent *types.Header, header *types.Header, number uint64, suc
928956
929957// Prepare implements consensus.Engine, preparing all the consensus fields of the
930958// header for running the transactions on top.
931- func (c * Bor ) Prepare (chain consensus.ChainHeaderReader , header * types.Header ) error {
959+ func (c * Bor ) Prepare (chain consensus.ChainHeaderReader , header * types.Header , waitOnPrepare bool ) error {
932960 // If the block isn't a checkpoint, cast a random vote (good enough for now)
933961 header .Coinbase = common.Address {}
934962 header .Nonce = types.BlockNonce {}
@@ -1026,6 +1054,8 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
10261054 return fmt .Errorf ("the floor of custom mining block time (%v) is less than the consensus block time: %v < %v" , c .blockTime , c .blockTime .Seconds (), c .config .CalculatePeriod (number ))
10271055 }
10281056
1057+ var delay time.Duration
1058+
10291059 if c .blockTime > 0 && c .config .IsRio (header .Number ) {
10301060 // Only enable custom block time for Rio and later
10311061
@@ -1043,14 +1073,16 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
10431073 actualNewBlockTime := parentActualBlockTime .Add (c .blockTime )
10441074 header .Time = uint64 (actualNewBlockTime .Unix ())
10451075 header .ActualTime = actualNewBlockTime
1076+ delay = time .Until (parentActualBlockTime )
10461077 } else {
10471078 header .Time = parent .Time + CalcProducerDelay (number , succession , c .config )
1079+ delay = time .Until (time .Unix (int64 (parent .Time ), 0 ))
10481080 }
10491081
10501082 now := time .Now ()
10511083 if header .Time < uint64 (now .Unix ()) {
10521084 additionalBlockTime := time .Duration (c .config .CalculatePeriod (number )) * time .Second
1053- if c .blockTime > 0 {
1085+ if c .blockTime > 0 && c . config . IsRio ( header . Number ) {
10541086 additionalBlockTime = c .blockTime
10551087 }
10561088 header .Time = uint64 (now .Add (additionalBlockTime ).Unix ())
@@ -1059,6 +1091,22 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
10591091 }
10601092 }
10611093
1094+ // Wait before start the block production if needed (previsously this wait was on Seal)
1095+ if c .config .IsBhilai (header .Number ) && waitOnPrepare {
1096+ var successionNumber int
1097+ // if signer is not empty (RPC nodes have empty signer)
1098+ if currentSigner .signer != (common.Address {}) {
1099+ var err error
1100+ successionNumber , err = snap .GetSignerSuccessionNumber (currentSigner .signer )
1101+ if err != nil {
1102+ return err
1103+ }
1104+ if successionNumber == 0 {
1105+ <- time .After (delay )
1106+ }
1107+ }
1108+ }
1109+
10621110 return nil
10631111}
10641112
@@ -1323,14 +1371,8 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, witnes
13231371 var delay time.Duration
13241372
13251373 // Sweet, the protocol permits us to sign the block, wait for our time
1326- if c .config .IsBhilai (header .Number ) {
1327- delay = time .Until (header .GetActualTime ()) // Wait until we reach header time for non-primary validators
1328- // Disable early block announcement
1329- // if successionNumber == 0 {
1330- // // For primary producers, set the delay to `header.Time - block time` instead of `header.Time`
1331- // // for early block announcement instead of waiting for full block time.
1332- // delay = time.Until(time.Unix(int64(header.Time-c.config.CalculatePeriod(number)), 0))
1333- // }
1374+ if c .config .IsBhilai (header .Number ) && successionNumber == 0 {
1375+ delay = 0 // delay was moved to Prepare for bhilai and later
13341376 } else {
13351377 delay = time .Until (header .GetActualTime ()) // Wait until we reach header time
13361378 }
0 commit comments