emission_state.gno
5.13 Kb ยท 167 lines
1package gns
2
3import (
4 "chain/runtime"
5 "time"
6
7 "gno.land/p/nt/ufmt"
8)
9
10var emissionState *EmissionState
11
12func init() {
13 emissionState = NewEmissionState(0, 0)
14}
15
16// EmissionState manages emission state and halving data.
17// Tracks emission timing, status, and halving year information for 12-year schedule.
18type EmissionState struct {
19 createdHeight int64
20 startTimestamp int64
21 endTimestamp int64
22 halvingData *HalvingData
23}
24
25// isInitialized returns true if emission state has been initialized with valid height and timestamp.
26func (e *EmissionState) isInitialized() bool {
27 return e.createdHeight != 0 && e.startTimestamp != 0
28}
29
30// isActive returns true if emission is currently active at the given timestamp.
31// Returns false if not initialized or timestamp is outside emission period.
32func (e *EmissionState) isActive(timestamp int64) bool {
33 if !e.isInitialized() {
34 return false
35 }
36
37 if e.startTimestamp > timestamp {
38 return false
39 }
40
41 if e.endTimestamp < timestamp {
42 return false
43 }
44
45 return true
46}
47
48// isEnded returns true if emission has ended at the given timestamp.
49func (e *EmissionState) isEnded(timestamp int64) bool {
50 return e.endTimestamp < timestamp
51}
52
53// getCurrentYear returns the halving year (1-12) for the given timestamp, or 0 if outside emission period.
54func (e *EmissionState) getCurrentYear(timestamp int64) int64 {
55 if timestamp < e.startTimestamp {
56 return 0
57 }
58
59 if timestamp > e.endTimestamp {
60 return 0
61 }
62
63 year := (timestamp - e.startTimestamp) / SECONDS_IN_YEAR
64 return year + 1
65}
66
67// getCreatedHeight returns the blockchain height when emission started.
68func (e *EmissionState) getCreatedHeight() int64 {
69 return e.createdHeight
70}
71
72// getStartTimestamp returns the timestamp when emission started.
73func (e *EmissionState) getStartTimestamp() int64 {
74 return e.startTimestamp
75}
76
77// getEndTimestamp returns the timestamp when emission ends.
78func (e *EmissionState) getEndTimestamp() int64 {
79 return e.endTimestamp
80}
81
82// getHalvingData returns the halving data containing emission schedule details.
83func (e *EmissionState) getHalvingData() *HalvingData {
84 return e.halvingData
85}
86
87// getHalvingYearStartTimestamp returns the start timestamp for the specified halving year.
88func (e *EmissionState) getHalvingYearStartTimestamp(year int64) int64 {
89 return e.halvingData.getStartTimestamp(year)
90}
91
92// getHalvingYearEndTimestamp returns the end timestamp for the specified halving year.
93func (e *EmissionState) getHalvingYearEndTimestamp(year int64) int64 {
94 return e.halvingData.getEndTimestamp(year)
95}
96
97// getHalvingYearAmountPerSecond returns the emission rate per second for the specified halving year.
98func (e *EmissionState) getHalvingYearAmountPerSecond(year int64) int64 {
99 return e.halvingData.getAmountPerSecond(year)
100}
101
102// getHalvingYearAccumulatedAmount returns the accumulated emission amount for the specified halving year.
103func (e *EmissionState) getHalvingYearAccumulatedAmount(year int64) int64 {
104 return e.halvingData.getAccumAmount(year)
105}
106
107// getHalvingYearLeftAmount returns the remaining emission amount for the specified halving year.
108func (e *EmissionState) getHalvingYearLeftAmount(year int64) int64 {
109 return e.halvingData.getLeftAmount(year)
110}
111
112// addHalvingYearAccumulatedAmount adds to the accumulated emission amount for the specified halving year.
113// Returns error if year is invalid (0 or outside 1-12 range).
114func (e *EmissionState) addHalvingYearAccumulatedAmount(year int64, amount int64) error {
115 if year == 0 {
116 return makeErrorWithDetails(errInvalidYear, ufmt.Sprintf("year: %d", year))
117 }
118
119 accumulatedAmount := e.halvingData.getAccumAmount(year)
120 accumulatedAmount = safeAddInt64(accumulatedAmount, amount)
121
122 return e.halvingData.setAccumAmount(year, accumulatedAmount)
123}
124
125// subHalvingYearLeftAmount subtracts from the remaining emission amount for the specified halving year.
126// Returns error if year is invalid (0 or outside 1-12 range).
127func (e *EmissionState) subHalvingYearLeftAmount(year int64, amount int64) error {
128 if year == 0 {
129 return makeErrorWithDetails(errInvalidYear, ufmt.Sprintf("year: %d", year))
130 }
131
132 leftAmount := e.halvingData.getLeftAmount(year)
133 leftAmount = safeSubInt64(leftAmount, amount)
134
135 return e.halvingData.setLeftAmount(year, leftAmount)
136}
137
138func (e *EmissionState) Clone() *EmissionState {
139 return &EmissionState{
140 createdHeight: e.createdHeight,
141 startTimestamp: e.startTimestamp,
142 endTimestamp: e.endTimestamp,
143 halvingData: e.halvingData.Clone(),
144 }
145}
146
147// NewEmissionState creates a new EmissionState with specified start height and timestamp.
148// Calculates emission end time based on 12-year schedule and initializes halving data.
149func NewEmissionState(createdHeight int64, startTimestamp int64) *EmissionState {
150 emissionEndTime := safeAddInt64(startTimestamp, SECONDS_IN_YEAR*HALVING_END_YEAR-1)
151
152 return &EmissionState{
153 createdHeight: createdHeight,
154 startTimestamp: startTimestamp,
155 endTimestamp: emissionEndTime,
156 halvingData: NewHalvingData(startTimestamp),
157 }
158}
159
160// getEmissionState returns the singleton emission state instance.
161func getEmissionState() *EmissionState {
162 if emissionState == nil {
163 emissionState = NewEmissionState(runtime.ChainHeight(), time.Now().Unix())
164 }
165
166 return emissionState
167}