github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/hotstuff/model/timeout.go (about) 1 package model 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/onflow/crypto" 8 "github.com/rs/zerolog" 9 10 "github.com/onflow/flow-go/model/flow" 11 ) 12 13 // TimerInfo represents a local timeout for a view, and indicates the Pacemaker has not yet 14 // observed evidence to transition to the next view (QC or TC). When a timeout occurs for 15 // the first time in a view, we will broadcast a TimeoutObject and continue waiting for evidence 16 // to enter the next view, but we will no longer submit a vote for this view. A timeout may occur 17 // multiple times for the same round, which is an indication 18 // to re-broadcast our TimeoutObject for the view, to ensure liveness. 19 type TimerInfo struct { 20 // View is round at which timer was created. 21 View uint64 22 // StartTime represents time of entering the view. 23 StartTime time.Time 24 // Duration is how long we waited before timing out the view. 25 // It does not include subsequent timeouts (ie. all timeout events emitted for the same 26 // view will have the same Duration). 27 Duration time.Duration 28 } 29 30 // NewViewEvent indicates that a new view has started. While it has the same 31 // data model as `TimerInfo`, their semantics are different (hence we use 32 // different types): `TimerInfo` represents a continuous time interval. In 33 // contrast, NewViewEvent marks the specific point in time, when the timer 34 // is started. 35 type NewViewEvent TimerInfo 36 37 // TimeoutObject represents intent of replica to leave its current view with a timeout. This concept is very similar to 38 // HotStuff vote. Valid TimeoutObject is signed by staking key. 39 type TimeoutObject struct { 40 // View is the view number which is replica is timing out 41 View uint64 42 // NewestQC is the newest QC (by view) known to the creator of this TimeoutObject 43 NewestQC *flow.QuorumCertificate 44 // LastViewTC is the timeout certificate for previous view if NewestQC.View != View - 1, else nil 45 LastViewTC *flow.TimeoutCertificate 46 // SignerID is the identifier of replica that has signed this TimeoutObject 47 // SignerID must be the origin ID from networking layer, which cryptographically 48 // authenticates the message's sender. 49 SignerID flow.Identifier 50 // SigData is a BLS signature created by staking key signing View + NewestQC.View 51 // This signature is further aggregated in TimeoutCertificate. 52 SigData crypto.Signature 53 // TimeoutTick is the number of times the `timeout.Controller` has (re-)emitted the 54 // timeout for this view. When the timer for the view's original duration expires, a `TimeoutObject` 55 // with `TimeoutTick = 0` is broadcast. Subsequently, `timeout.Controller` re-broadcasts the 56 // `TimeoutObject` periodically based on some internal heuristic. Each time we attempt a re-broadcast, 57 // the `TimeoutTick` is incremented. Incrementing the field prevents de-duplicated within the network layer, 58 // which in turn guarantees quick delivery of the `TimeoutObject` after GST and facilitates recovery. 59 // This field is not part of timeout object ID. Thereby, two timeouts are identical if only they differ 60 // by their TimeoutTick value. 61 TimeoutTick uint64 62 } 63 64 // ID returns the TimeoutObject's identifier 65 func (t *TimeoutObject) ID() flow.Identifier { 66 body := struct { 67 View uint64 68 NewestQCID flow.Identifier 69 LastViewTCID flow.Identifier 70 SignerID flow.Identifier 71 SigData crypto.Signature 72 }{ 73 View: t.View, 74 NewestQCID: t.NewestQC.ID(), 75 LastViewTCID: t.LastViewTC.ID(), 76 SignerID: t.SignerID, 77 SigData: t.SigData, 78 } 79 return flow.MakeID(body) 80 } 81 82 func (t *TimeoutObject) String() string { 83 return fmt.Sprintf( 84 "View: %d, HighestQC.View: %d, LastViewTC: %v, TimeoutTick: %d", 85 t.View, 86 t.NewestQC.View, 87 t.LastViewTC, 88 t.TimeoutTick, 89 ) 90 } 91 92 // LogContext returns a `zerolog.Contex` including the most important properties of the TC: 93 // - view number that this TC is for 94 // - view and ID of the block that the included QC points to 95 // - number of times a re-broadcast of this timeout was attempted 96 // - [optional] if the TC also includes a TC for the prior view, i.e. `LastViewTC` ≠ nil: 97 // the new of `LastViewTC` and the view that `LastViewTC.NewestQC` is for 98 func (t *TimeoutObject) LogContext(logger zerolog.Logger) zerolog.Context { 99 logContext := logger.With(). 100 Uint64("timeout_newest_qc_view", t.NewestQC.View). 101 Hex("timeout_newest_qc_block_id", t.NewestQC.BlockID[:]). 102 Uint64("timeout_view", t.View). 103 Uint64("timeout_tick", t.TimeoutTick) 104 105 if t.LastViewTC != nil { 106 logContext. 107 Uint64("last_view_tc_view", t.LastViewTC.View). 108 Uint64("last_view_tc_newest_qc_view", t.LastViewTC.NewestQC.View) 109 } 110 return logContext 111 }