@@ -13,6 +13,7 @@ import (
13
13
"github.com/facebookgo/clock"
14
14
fsm "github.com/iotexproject/go-fsm"
15
15
"github.com/iotexproject/go-pkgs/crypto"
16
+ "github.com/iotexproject/go-pkgs/hash"
16
17
"github.com/pkg/errors"
17
18
"github.com/prometheus/client_golang/prometheus"
18
19
"go.uber.org/zap"
@@ -405,6 +406,37 @@ func (ctx *rollDPoSCtx) Proposal() (interface{}, error) {
405
406
return ctx .mintNewBlock (privateKey )
406
407
}
407
408
409
+ func (ctx * rollDPoSCtx ) prepareNextProposal (prevHeight uint64 , prevHash hash.Hash256 ) error {
410
+ var (
411
+ height = prevHeight + 1
412
+ interval = ctx .BlockInterval (height )
413
+ startTime = ctx .round .StartTime ().Add (interval )
414
+ err error
415
+ )
416
+ fork , err := ctx .chain .Fork (prevHash )
417
+ if err != nil {
418
+ return errors .Wrapf (err , "failed to check fork at block %d, hash %x" , prevHeight , prevHash [:])
419
+ }
420
+ roundCalc := ctx .roundCalc .Fork (fork )
421
+ // check if the current node is the next proposer
422
+ nextProposer := roundCalc .Proposer (height , interval , startTime )
423
+ idx := slices .Index (ctx .encodedAddrs , nextProposer )
424
+ if idx < 0 {
425
+ return nil
426
+ }
427
+ privateKey := ctx .priKeys [idx ]
428
+ ctx .logger ().Debug ("prepare next proposal" , log .Hex ("prevHash" , prevHash [:]), zap .Uint64 ("height" , ctx .round .height + 1 ), zap .Time ("timestamp" , startTime ), zap .String ("nextproposer" , nextProposer ))
429
+ go func () {
430
+ blk , err := fork .MintNewBlock (startTime , privateKey , prevHash )
431
+ if err != nil {
432
+ ctx .logger ().Error ("failed to mint new block" , zap .Error (err ))
433
+ return
434
+ }
435
+ ctx .logger ().Debug ("prepared a new block" , zap .Uint64 ("height" , blk .Height ()), zap .Time ("timestamp" , blk .Timestamp ()))
436
+ }()
437
+ return nil
438
+ }
439
+
408
440
func (ctx * rollDPoSCtx ) WaitUntilRoundStart () time.Duration {
409
441
ctx .mutex .RLock ()
410
442
defer ctx .mutex .RUnlock ()
@@ -454,9 +486,16 @@ func (ctx *rollDPoSCtx) NewProposalEndorsement(msg interface{}) (interface{}, er
454
486
if err := ctx .round .AddBlock (proposal .block ); err != nil {
455
487
return nil , err
456
488
}
489
+ if err := ctx .prepareNextProposal (proposal .block .Height (), blkHash ); err != nil {
490
+ ctx .loggerWithStats ().Warn ("failed to prepare next proposal" , zap .Error (err ), zap .Uint64 ("prevHeight" , proposal .block .Height ()))
491
+ }
457
492
ctx .loggerWithStats ().Debug ("accept block proposal" , log .Hex ("block" , blockHash ))
458
493
} else if ctx .round .IsLocked () {
459
494
blockHash = ctx .round .HashOfBlockInLock ()
495
+ } else {
496
+ if err := ctx .prepareNextProposal (ctx .round .Height ()- 1 , ctx .round .PrevHash ()); err != nil {
497
+ ctx .loggerWithStats ().Warn ("failed to prepare next proposal" , zap .Error (err ), zap .Uint64 ("prevHeight" , ctx .round .Height ()- 1 ))
498
+ }
460
499
}
461
500
// TODO: prepare next block if the current node will be a proposer
462
501
0 commit comments