@@ -39,6 +39,9 @@ type BFT struct {
3939 Controller // reference to the Controller for callbacks like producing and validating the proposal via the plugin or gossiping commit message
4040 ResetBFT chan ResetBFT // trigger that resets the BFT due to a new Target block or a new Canopy block
4141 syncing * atomic.Bool // if chain for this committee is currently catching up to latest height
42+ phase atomic.Int32 // atomic mirror of View.Phase for external readers
43+ round atomic.Uint64 // atomic mirror of View.Round for external readers
44+ deadlineMs atomic.Int64 // atomic proposal vote mode deadline in unix milliseconds for external readers
4245
4346 PhaseTimer * time.Timer // ensures the node waits for a configured duration (Round x phaseTimeout) to allow for full voter participation
4447
@@ -59,7 +62,7 @@ func New(c lib.Config, valKey crypto.PrivateKeyI, rootHeight, height uint64, con
5962 vdfTargetTime := time .Duration (float64 (c .BlockTimeMS ())* BlockTimeToVDFTargetCoefficient ) * time .Millisecond
6063 vdf = lib .NewVDFService (vdfTargetTime , l )
6164 }
62- return & BFT {
65+ b := & BFT {
6366 View : & lib.View {
6467 Height : height ,
6568 RootHeight : rootHeight ,
@@ -85,7 +88,27 @@ func New(c lib.Config, valKey crypto.PrivateKeyI, rootHeight, height uint64, con
8588 Metrics : m ,
8689 HighVDF : new (crypto.VDF ),
8790 VDFCache : []* Message {},
88- }, nil
91+ }
92+ b .round .Store (b .Round )
93+ return b , nil
94+ }
95+
96+ // CurrentPhase() returns the current consensus phase using an atomic mirror for external readers
97+ func (b * BFT ) CurrentPhase () Phase {
98+ if b == nil {
99+ return lib .Phase_ELECTION
100+ }
101+ return Phase (b .phase .Load ())
102+ }
103+
104+ // CurrentRound() returns the current consensus round using an atomic mirror for external readers
105+ func (b * BFT ) CurrentRound () uint64 {
106+ return b .round .Load ()
107+ }
108+
109+ // ProposalVoteDeadlineUnixMilli() returns the unix millisecond deadline for approve-list proposal voting
110+ func (b * BFT ) ProposalVoteDeadlineUnixMilli () int64 {
111+ return b .deadlineMs .Load ()
89112}
90113
91114// Start() initiates the HotStuff BFT service.
@@ -142,6 +165,7 @@ func (b *BFT) Start() {
142165 b .NewHeight (false )
143166 b .SetWaitTimers (time .Duration (b .Config .NewHeightTimeoutMs )* time .Millisecond , processTime )
144167 b .BFTStartTime = time .Now ()
168+ b .deadlineMs .Store (b .BFTStartTime .Add (time .Duration (b .Config .BlockTimeMS ()* 3 ) * time .Millisecond ).UnixMilli ())
145169 } else {
146170 b .log .Info ("Reset BFT (NEW_COMMITTEE)" )
147171 //if b.LoadIsOwnRoot() {
@@ -532,6 +556,7 @@ func (b *BFT) RoundInterrupt() {
532556 b .Config .RoundInterruptTimeoutMS = b .msLeftInRound ()
533557 b .log .Warnf ("Starting next round in %.2f secs" , (time .Duration (b .Config .RoundInterruptTimeoutMS ) * time .Millisecond ).Seconds ())
534558 b .Phase = RoundInterrupt
559+ b .phase .Store (int32 (b .Phase ))
535560 b .BlockResult = nil
536561 b .VDFCache = []* Message {}
537562 b .ResetFSM ()
@@ -575,6 +600,7 @@ func (b *BFT) Pacemaker() {
575600 if pacemakerRound > b .Round {
576601 b .log .Infof ("Pacemaker peers set round: %d" , pacemakerRound )
577602 b .Round = pacemakerRound
603+ b .round .Store (b .Round )
578604 }
579605}
580606
@@ -628,6 +654,7 @@ func (b *BFT) NewRound(newHeight bool) {
628654 // defensive: clear byzantine evidence
629655 b .ByzantineEvidence = & ByzantineEvidence {DSE : DoubleSignEvidences {}}
630656 }
657+ b .round .Store (b .Round )
631658 b .RefreshRootChainInfo ()
632659 // reset ProposerKey, Proposal, and Sortition data
633660 b .ProposerKey = nil
@@ -666,6 +693,7 @@ func (b *BFT) NewHeight(keepLocks ...bool) {
666693 b .NewRound (true )
667694 // set phase to Election
668695 b .Phase = Election
696+ b .phase .Store (int32 (b .Phase ))
669697 // if resetting due to new Canopy Block and Validator Set then KeepLocks
670698 // - protecting any who may have committed against attacks like malicious proposers from withholding
671699 // COMMIT_MSG and sending it after the next block is produces
@@ -716,6 +744,7 @@ func (b *BFT) SetTimerForNextPhase(processTime time.Duration) {
716744 case Pacemaker :
717745 b .Phase = Election
718746 }
747+ b .phase .Store (int32 (b .Phase ))
719748 b .SetWaitTimers (waitTime , processTime )
720749}
721750
0 commit comments