github.com/aergoio/aergo@v1.3.1/consensus/impl/dpos/slot/slot.go (about)

     1  package slot
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/aergoio/aergo/consensus/impl/dpos/bp"
     7  )
     8  
     9  var (
    10  	// blockIntervalMs is the block genration interval in milli-seconds.
    11  	blockIntervalMs int64
    12  	// bpMinTimeLimitMs is the minimum block generation time limit in milli-sconds.
    13  	bpMinTimeLimitMs int64
    14  	// bpMaxTimeLimitMs is the maximum block generation time limit in milli-seconds.
    15  	bpMaxTimeLimitMs int64
    16  )
    17  
    18  // Slot is a DPoS slot implmentation.
    19  type Slot struct {
    20  	timeNs    int64 // nanosecond
    21  	timeMs    int64 // millisecond
    22  	prevIndex int64
    23  	nextIndex int64
    24  }
    25  
    26  // Init initilizes various slot parameters
    27  func Init(blockIntervalSec int64) {
    28  	blockIntervalMs = blockIntervalSec * 1000
    29  	bpMinTimeLimitMs = blockIntervalMs / 4
    30  	bpMaxTimeLimitMs = blockIntervalMs / 2
    31  }
    32  
    33  // Now returns a Slot corresponding to the current local time.
    34  func Now() *Slot {
    35  	return Time(time.Now())
    36  }
    37  
    38  // NewFromUnixNano returns a Slot corresponding to a UNIX time value (ns).
    39  func NewFromUnixNano(ns int64) *Slot {
    40  	return fromUnixNs(ns)
    41  }
    42  
    43  // UnixNano returns UNIX time in ns.
    44  func (s *Slot) UnixNano() int64 {
    45  	return s.timeNs
    46  }
    47  
    48  // Time returns a Slot corresponting to the given time.
    49  func Time(t time.Time) *Slot {
    50  	return fromUnixNs(t.UnixNano())
    51  }
    52  
    53  func fromUnixNs(ns int64) *Slot {
    54  	ms := nsToMs(ns)
    55  	return &Slot{
    56  		timeNs:    ns,
    57  		timeMs:    ms,
    58  		prevIndex: msToPrevIndex(ms),
    59  		nextIndex: msToNextIndex(ms),
    60  	}
    61  }
    62  
    63  // IsValidNow reports whether s is still valid at the time when it's
    64  // called.
    65  func (s *Slot) IsValidNow() bool {
    66  	if s.nextIndex == Now().nextIndex {
    67  		return true
    68  	}
    69  	return false
    70  }
    71  
    72  // IsFuture reports whether s
    73  func (s *Slot) IsFuture() bool {
    74  	// Assume that the slot is future if the index difference >= 2.
    75  	if s.nextIndex >= Now().nextIndex+2 {
    76  		return true
    77  	}
    78  	return false
    79  }
    80  
    81  // Equal reports whether s1 has the same index as s2 or not.
    82  func Equal(s1, s2 *Slot) bool {
    83  	if s1 == nil || s2 == nil {
    84  		return false
    85  	}
    86  	return s1.nextIndex == s2.nextIndex
    87  }
    88  
    89  // LessEqual reports whehter s1.nextIndex is less than or equal to s2.nextIndex
    90  func LessEqual(s1, s2 *Slot) bool {
    91  	if s1 == nil || s2 == nil {
    92  		return false
    93  	}
    94  	return s1.nextIndex <= s2.nextIndex
    95  }
    96  
    97  // IsNextTo reports whether s1 corrensponds to the slot next to s2.
    98  func IsNextTo(s1, s2 *Slot) bool {
    99  	if s1 == nil || s2 == nil {
   100  		return false
   101  	}
   102  	return s1.prevIndex == s2.nextIndex
   103  }
   104  
   105  // IsFor reports whether s correponds to myBpIdx (block producer index).
   106  func (s *Slot) IsFor(bpIdx bp.Index, bpCount uint16) bool {
   107  	return s.NextBpIndex(bpCount) == int64(bpIdx)
   108  }
   109  
   110  // GetBpTimeout returns the time available for block production.
   111  func (s *Slot) GetBpTimeout() int64 {
   112  	rTime := s.RemainingTimeMS()
   113  
   114  	if rTime >= bpMaxTimeLimitMs {
   115  		return bpMaxTimeLimitMs
   116  	}
   117  
   118  	return rTime
   119  }
   120  
   121  // RemainingTimeMS returns the remaining duration until the next block
   122  // generation time.
   123  func (s *Slot) RemainingTimeMS() int64 {
   124  	return s.nextIndex*blockIntervalMs - nsToMs(time.Now().UnixNano())
   125  }
   126  
   127  // TimesUp reports whether the reminaing time <= BpMinTimeLimitMs
   128  func (s Slot) TimesUp() bool {
   129  	return s.RemainingTimeMS() <= bpMinTimeLimitMs
   130  }
   131  
   132  // NextBpIndex returns BP index for s.nextIndex.
   133  func (s *Slot) NextBpIndex(bpCount uint16) int64 {
   134  	return s.nextIndex % int64(bpCount)
   135  }
   136  
   137  func msToPrevIndex(ms int64) int64 {
   138  	return msToIndex(ms)
   139  }
   140  
   141  func msToNextIndex(ms int64) int64 {
   142  	return msToIndex(ms + blockIntervalMs)
   143  }
   144  
   145  func msToIndex(ms int64) int64 {
   146  	return (ms - 1) / blockIntervalMs
   147  }
   148  
   149  func nsToMs(ns int64) int64 {
   150  	return ns / 1000000
   151  }
   152  
   153  func msToSec(ms int64) int64 {
   154  	return ms / 1000
   155  }