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 }