@@ -281,7 +281,7 @@ func (h *gpbftHost) Time() time.Time {
281281// The timestamp may be in the past, in which case the alarm will fire as soon as possible
282282// (but not synchronously).
283283func (h * gpbftHost ) SetAlarm (at time.Time ) {
284- h .log .Infof ("set alarm for %v" , at )
284+ h .log .Debugf ("set alarm for %v" , at )
285285 // we cannot reuse the timer because we don't know if it was read or not
286286 h .alertTimer .Stop ()
287287 h .alertTimer = time .NewTimer (time .Until (at ))
@@ -294,7 +294,8 @@ func (h *gpbftHost) SetAlarm(at time.Time) {
294294// based on the decision received (which may be in the past).
295295// E.g. this might be: finalised tipset timestamp + epoch duration + stabilisation delay.
296296func (h * gpbftHost ) ReceiveDecision (decision * gpbft.Justification ) time.Time {
297- h .log .Infof ("got decision, finalized head at epoch: %d" , decision .Vote .Value .Head ().Epoch )
297+ h .log .Infof ("got decision at instance %d, finalized head at epoch: %d" ,
298+ decision .Vote .Instance , decision .Vote .Value .Head ().Epoch )
298299 err := h .saveDecision (decision )
299300 if err != nil {
300301 h .log .Errorf ("error while saving decision: %+v" , err )
@@ -305,7 +306,44 @@ func (h *gpbftHost) ReceiveDecision(decision *gpbft.Justification) time.Time {
305306 return time .Now ().Add (h .manifest .ECDelay )
306307 }
307308
308- return ts .Timestamp ().Add (h .manifest .ECDelay )
309+ if decision .Vote .Value .HasSuffix () {
310+ // we decided on something new, use just the ECDelay
311+ return ts .Timestamp ().Add (h .manifest .ECDelay )
312+ }
313+
314+ // we decided on base, calculate how much we should back off
315+ // all of this should go into manifest but I think Alfonso dislikes me already :P
316+ const (
317+ minBackoff = 2.
318+ maxBackoff = 20. // 10m with 30s ECDelay
319+ )
320+ // the backoff is defined in multiples of ECDelay starting at the last finalized tipset
321+ // each additional base decision beyond that will incurr the maxBackoff
322+ var backoffTable = []float64 {2 , 2.3 , 2.69 , 3.197 , 3.8561 , 4.71293 , 4.71293 , 5.826809 , 7.2748517 , 9.15730721 } // 1.3^i+1 backoff, table for more flexibility
323+ //TODO move all the above to manifest
324+
325+ attempts := 0
326+ var backoffMultipler float64
327+ for instance := decision .Vote .Instance - 1 ; instance > h .manifest .InitialInstance ; instance -- {
328+ cert , err := h .client .certStore .Get (h .runningCtx , instance )
329+ if err != nil {
330+ h .log .Errorf ("error while getting instance %d from certstore: %+v" , instance , err )
331+ break
332+ }
333+ if ! cert .ECChain .HasSuffix () {
334+ attempts += 1
335+ }
336+ if attempts < len (backoffTable ) {
337+ backoffMultipler += min (backoffTable [attempts ], maxBackoff )
338+ } else {
339+ backoffMultipler += maxBackoff
340+ }
341+ }
342+
343+ backoff := time .Duration (float64 (h .manifest .ECDelay ) * backoffMultipler )
344+ h .log .Infof ("backing off for: %v" , backoff )
345+
346+ return ts .Timestamp ().Add (backoff )
309347}
310348
311349func (h * gpbftHost ) saveDecision (decision * gpbft.Justification ) error {
0 commit comments