store.gno
19.10 Kb · 584 lines
1package staker
2
3import (
4 "errors"
5
6 "gno.land/p/gnoswap/store/v1"
7 "gno.land/p/gnoswap/utils/v1"
8 bptree "gno.land/p/nt/bptree/v0"
9 ufmt "gno.land/p/nt/ufmt/v0"
10)
11
12// Storage key constants
13const (
14 // Basic configuration
15 StoreKeyUnDelegationLockupPeriod = "unDelegationLockupPeriod"
16 StoreKeyTotalDelegatedAmount = "totalDelegatedAmount"
17 StoreKeyTotalLockedAmount = "totalLockedAmount"
18
19 // Counters
20 StoreKeyDelegationNextID = "delegationNextID"
21
22 // Complex data structures
23 StoreKeyDelegations = "delegations" // BPTree of delegations
24 StoreKeyTotalDelegationHistory = "totalDelegationHistory" // UintTree: timestamp -> int64 (cumulative total)
25 StoreKeyUserDelegationHistory = "userDelegationHistory" // BPTree: address -> *UintTree[timestamp -> int64]
26
27 // Manager states
28 StoreKeyEmissionRewardManager = "emissionRewardManager"
29 StoreKeyProtocolFeeRewardManager = "protocolFeeRewardManager"
30 StoreKeyDelegationManager = "delegationManager"
31 StoreKeyLaunchpadProjectDeposits = "launchpadProjectDeposits"
32)
33
34// govStakerStore is the concrete implementation of IGovStakerStore
35type govStakerStore struct {
36 kvStore store.KVStore
37}
38
39var _ IGovStakerStore = (*govStakerStore)(nil)
40
41// NewGovStakerStore creates a new governance staker store instance backed by kvStore.
42//
43// Parameters:
44// - kvStore: Key-value store used to persist governance staker state.
45//
46// Returns:
47// - IGovStakerStore: store implementation that reads and writes the supplied KV store.
48func NewGovStakerStore(kvStore store.KVStore) IGovStakerStore {
49 return &govStakerStore{
50 kvStore: kvStore,
51 }
52}
53
54// Basic configuration methods
55// Returns:
56// - bool: true when the undelegation lockup-period key is present in storage.
57func (s *govStakerStore) HasUnDelegationLockupPeriodStoreKey() bool {
58 return s.kvStore.Has(StoreKeyUnDelegationLockupPeriod)
59}
60
61// GetUnDelegationLockupPeriod returns the configured undelegation lockup period in seconds.
62//
63// Returns:
64// - int64: lockup duration in seconds; panics if the stored value is unavailable or not int64.
65func (s *govStakerStore) GetUnDelegationLockupPeriod() int64 {
66 result, err := s.kvStore.Get(StoreKeyUnDelegationLockupPeriod)
67 if err != nil {
68 panic(err)
69 }
70
71 period, ok := result.(int64)
72 if !ok {
73 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
74 }
75
76 return period
77}
78
79// SetUnDelegationLockupPeriod stores the undelegation lockup period.
80//
81// Parameters:
82// - _: Internal call discriminator; pass 0.
83// - rlm: Propagated realm context; the write is accepted only when this realm is current.
84// - period: Undelegation lockup duration in seconds.
85//
86// Returns:
87// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
88func (s *govStakerStore) SetUnDelegationLockupPeriod(_ int, rlm realm, period int64) error {
89 if !rlm.IsCurrent() {
90 return errors.New(ErrSpoofedRealm)
91 }
92
93 return s.kvStore.Set(0, rlm, StoreKeyUnDelegationLockupPeriod, period)
94}
95
96// Returns:
97// - bool: true when the total delegated-amount key is present in storage.
98func (s *govStakerStore) HasTotalDelegatedAmountStoreKey() bool {
99 return s.kvStore.Has(StoreKeyTotalDelegatedAmount)
100}
101
102// GetTotalDelegatedAmount returns the total amount currently delegated.
103//
104// Returns:
105// - int64: aggregate delegated amount; panics if the stored value is unavailable or not int64.
106func (s *govStakerStore) GetTotalDelegatedAmount() int64 {
107 result, err := s.kvStore.Get(StoreKeyTotalDelegatedAmount)
108 if err != nil {
109 panic(err)
110 }
111
112 amount, ok := result.(int64)
113 if !ok {
114 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
115 }
116
117 return amount
118}
119
120// SetTotalDelegatedAmount stores the aggregate delegated amount.
121//
122// Parameters:
123// - _: Internal call discriminator; pass 0.
124// - rlm: Propagated realm context; the write is accepted only when this realm is current.
125// - amount: Aggregate amount of GNS delegated across all delegators.
126//
127// Returns:
128// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
129func (s *govStakerStore) SetTotalDelegatedAmount(_ int, rlm realm, amount int64) error {
130 if !rlm.IsCurrent() {
131 return errors.New(ErrSpoofedRealm)
132 }
133
134 return s.kvStore.Set(0, rlm, StoreKeyTotalDelegatedAmount, amount)
135}
136
137// Returns:
138// - bool: true when the total locked-amount key is present in storage.
139func (s *govStakerStore) HasTotalLockedAmountStoreKey() bool {
140 return s.kvStore.Has(StoreKeyTotalLockedAmount)
141}
142
143// GetTotalLockedAmount returns the total amount locked in undelegation withdrawals.
144//
145// Returns:
146// - int64: aggregate locked amount; panics if the stored value is unavailable or not int64.
147func (s *govStakerStore) GetTotalLockedAmount() int64 {
148 result, err := s.kvStore.Get(StoreKeyTotalLockedAmount)
149 if err != nil {
150 panic(err)
151 }
152
153 amount, ok := result.(int64)
154 if !ok {
155 panic(ufmt.Sprintf("failed to cast result to int64: %T", result))
156 }
157
158 return amount
159}
160
161// SetTotalLockedAmount stores the aggregate amount locked in undelegation.
162//
163// Parameters:
164// - _: Internal call discriminator; pass 0.
165// - rlm: Propagated realm context; the write is accepted only when this realm is current.
166// - amount: Aggregate GNS amount currently locked in undelegation withdrawals.
167//
168// Returns:
169// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
170func (s *govStakerStore) SetTotalLockedAmount(_ int, rlm realm, amount int64) error {
171 if !rlm.IsCurrent() {
172 return errors.New(ErrSpoofedRealm)
173 }
174
175 return s.kvStore.Set(0, rlm, StoreKeyTotalLockedAmount, amount)
176}
177
178// Delegation management methods
179// Returns:
180// - bool: true when the delegations tree key is present in storage.
181func (s *govStakerStore) HasDelegationsStoreKey() bool {
182 return s.kvStore.Has(StoreKeyDelegations)
183}
184
185// SetDelegations replaces the persisted delegation tree.
186//
187// Parameters:
188// - _: Internal call discriminator; pass 0.
189// - rlm: Propagated realm context; the write is accepted only when this realm is current.
190// - delegations: BPTree containing delegation records keyed by decimal delegation ID.
191//
192// Returns:
193// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
194func (s *govStakerStore) SetDelegations(_ int, rlm realm, delegations *bptree.BPTree) error {
195 if !rlm.IsCurrent() {
196 return errors.New(ErrSpoofedRealm)
197 }
198
199 return s.kvStore.Set(0, rlm, StoreKeyDelegations, delegations)
200}
201
202// HasDelegation reports whether a delegation with id exists.
203//
204// Parameters:
205// - id: Numeric delegation identifier converted to the tree's decimal-string key.
206//
207// Returns:
208// - bool: true when a delegation record exists for id, false when the key is absent.
209func (s *govStakerStore) HasDelegation(id int64) bool {
210 delegations := s.GetAllDelegations()
211 return delegations.Get(utils.Int64ToString(id)) != nil
212}
213
214// GetDelegation retrieves a delegation by id.
215//
216// Parameters:
217// - id: Numeric delegation identifier converted to the tree's decimal-string key.
218//
219// Returns:
220// - *Delegation: stored delegation, or nil when no record exists for id.
221// - bool: true when a delegation was found; false when id is absent.
222func (s *govStakerStore) GetDelegation(id int64) (*Delegation, bool) {
223 delegations := s.GetAllDelegations()
224
225 result := delegations.Get(utils.Int64ToString(id))
226 if result == nil {
227 return nil, false
228 }
229
230 delegation, ok := result.(*Delegation)
231 if !ok {
232 panic(ufmt.Sprintf("failed to cast result to *Delegation: %T", result))
233 }
234
235 return delegation, true
236}
237
238// SetDelegation stores one delegation under id.
239//
240// Parameters:
241// - _: Internal call discriminator; pass 0.
242// - rlm: Propagated realm context; the write is accepted only when this realm is current.
243// - id: Numeric identifier used as the delegation's decimal-string tree key.
244// - delegation: Delegation record to store for id.
245//
246// Returns:
247// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
248func (s *govStakerStore) SetDelegation(_ int, rlm realm, id int64, delegation *Delegation) error {
249 if !rlm.IsCurrent() {
250 return errors.New(ErrSpoofedRealm)
251 }
252
253 delegations := s.GetAllDelegations()
254
255 delegations.Set(utils.Int64ToString(id), delegation)
256 return s.kvStore.Set(0, rlm, StoreKeyDelegations, delegations)
257}
258
259// RemoveDelegation deletes the delegation stored under id.
260//
261// Parameters:
262// - _: Internal call discriminator; pass 0.
263// - rlm: Propagated realm context; the write is accepted only when this realm is current.
264// - id: Numeric delegation identifier whose decimal-string tree entry is removed.
265//
266// Returns:
267// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
268func (s *govStakerStore) RemoveDelegation(_ int, rlm realm, id int64) error {
269 if !rlm.IsCurrent() {
270 return errors.New(ErrSpoofedRealm)
271 }
272
273 delegations := s.GetAllDelegations()
274
275 delegations.Remove(utils.Int64ToString(id))
276 return s.kvStore.Set(0, rlm, StoreKeyDelegations, delegations)
277}
278
279// GetAllDelegations returns the persisted tree of delegation records keyed by decimal ID.
280//
281// Returns:
282// - *bptree.BPTree: delegation tree; panics if storage is unavailable or contains a different type.
283func (s *govStakerStore) GetAllDelegations() *bptree.BPTree {
284 result, err := s.kvStore.Get(StoreKeyDelegations)
285 if err != nil {
286 panic(err)
287 }
288
289 delegations, ok := result.(*bptree.BPTree)
290 if !ok {
291 panic(ufmt.Sprintf("failed to cast result to *bptree.BPTree: %T", result))
292 }
293
294 return delegations
295}
296
297// Returns:
298// - bool: true when the next-delegation-ID counter key is present in storage.
299func (s *govStakerStore) HasDelegationCounterStoreKey() bool {
300 return s.kvStore.Has(StoreKeyDelegationNextID)
301}
302
303// GetDelegationCounter returns the counter used to allocate delegation IDs.
304//
305// Returns:
306// - *Counter: persisted next-ID counter; panics if storage is unavailable or contains a different type.
307func (s *govStakerStore) GetDelegationCounter() *Counter {
308 result, err := s.kvStore.Get(StoreKeyDelegationNextID)
309 if err != nil {
310 panic(err)
311 }
312
313 counter, ok := result.(*Counter)
314 if !ok {
315 panic(ufmt.Sprintf("failed to cast result to Counter: %T", result))
316 }
317
318 return counter
319}
320
321// SetDelegationCounter stores the counter used to allocate delegation IDs.
322//
323// Parameters:
324// - _: Internal call discriminator; pass 0.
325// - rlm: Propagated realm context; the write is accepted only when this realm is current.
326// - counter: Counter holding the next delegation ID.
327//
328// Returns:
329// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
330func (s *govStakerStore) SetDelegationCounter(_ int, rlm realm, counter *Counter) error {
331 if !rlm.IsCurrent() {
332 return errors.New(ErrSpoofedRealm)
333 }
334
335 return s.kvStore.Set(0, rlm, StoreKeyDelegationNextID, counter)
336}
337
338// Total delegation history methods (timestamp -> int64)
339// Returns:
340// - bool: true when the total delegation-history key is present in storage.
341func (s *govStakerStore) HasTotalDelegationHistoryStoreKey() bool {
342 return s.kvStore.Has(StoreKeyTotalDelegationHistory)
343}
344
345// GetTotalDelegationHistory returns timestamp-indexed aggregate delegation history.
346//
347// Returns:
348// - *UintTree: history mapping Unix timestamps to cumulative delegated amounts; panics on missing or invalid storage.
349func (s *govStakerStore) GetTotalDelegationHistory() *UintTree {
350 result, err := s.kvStore.Get(StoreKeyTotalDelegationHistory)
351 if err != nil {
352 panic(err)
353 }
354
355 history, ok := result.(*UintTree)
356 if !ok {
357 panic(ufmt.Sprintf("failed to cast result to *UintTree: %T", result))
358 }
359
360 return history
361}
362
363// SetTotalDelegationHistory stores timestamp-indexed aggregate delegation history.
364//
365// Parameters:
366// - _: Internal call discriminator; pass 0.
367// - rlm: Propagated realm context; the write is accepted only when this realm is current.
368// - history: UintTree mapping timestamps to cumulative total delegated amounts.
369//
370// Returns:
371// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
372func (s *govStakerStore) SetTotalDelegationHistory(_ int, rlm realm, history *UintTree) error {
373 if !rlm.IsCurrent() {
374 return errors.New(ErrSpoofedRealm)
375 }
376
377 return s.kvStore.Set(0, rlm, StoreKeyTotalDelegationHistory, history)
378}
379
380// User delegation history methods (address -> *UintTree[timestamp -> int64])
381// Returns:
382// - bool: true when the per-user delegation-history key is present in storage.
383func (s *govStakerStore) HasUserDelegationHistoryStoreKey() bool {
384 return s.kvStore.Has(StoreKeyUserDelegationHistory)
385}
386
387// GetUserDelegationHistory returns the address-indexed delegation-history tree.
388//
389// Returns:
390// - *bptree.BPTree: tree mapping delegator addresses to timestamp histories; panics on missing or invalid storage.
391func (s *govStakerStore) GetUserDelegationHistory() *bptree.BPTree {
392 result, err := s.kvStore.Get(StoreKeyUserDelegationHistory)
393 if err != nil {
394 panic(err)
395 }
396
397 history, ok := result.(*bptree.BPTree)
398 if !ok {
399 panic(ufmt.Sprintf("failed to cast result to *bptree.BPTree: %T", result))
400 }
401
402 return history
403}
404
405// SetUserDelegationHistory stores the address-indexed delegation-history tree.
406//
407// Parameters:
408// - _: Internal call discriminator; pass 0.
409// - rlm: Propagated realm context; the write is accepted only when this realm is current.
410// - history: BPTree mapping delegator addresses to their timestamp-indexed histories.
411//
412// Returns:
413// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
414func (s *govStakerStore) SetUserDelegationHistory(_ int, rlm realm, history *bptree.BPTree) error {
415 if !rlm.IsCurrent() {
416 return errors.New(ErrSpoofedRealm)
417 }
418
419 return s.kvStore.Set(0, rlm, StoreKeyUserDelegationHistory, history)
420}
421
422// Returns:
423// - bool: true when the emission-reward-manager key is present in storage.
424func (s *govStakerStore) HasEmissionRewardManagerStoreKey() bool {
425 return s.kvStore.Has(StoreKeyEmissionRewardManager)
426}
427
428// GetEmissionRewardManager returns the persisted emission reward manager.
429//
430// Returns:
431// - *EmissionRewardManager: emission reward accounting state; panics on missing or invalid storage.
432func (s *govStakerStore) GetEmissionRewardManager() *EmissionRewardManager {
433 result, err := s.kvStore.Get(StoreKeyEmissionRewardManager)
434 if err != nil {
435 panic(err)
436 }
437
438 manager, ok := result.(*EmissionRewardManager)
439 if !ok {
440 panic(ufmt.Sprintf("failed to cast result to *EmissionRewardManager: %T", result))
441 }
442
443 return manager
444}
445
446// SetEmissionRewardManager stores the emission reward manager.
447//
448// Parameters:
449// - _: Internal call discriminator; pass 0.
450// - rlm: Propagated realm context; the write is accepted only when this realm is current.
451// - manager: Emission reward accounting state to persist.
452//
453// Returns:
454// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
455func (s *govStakerStore) SetEmissionRewardManager(_ int, rlm realm, manager *EmissionRewardManager) error {
456 if !rlm.IsCurrent() {
457 return errors.New(ErrSpoofedRealm)
458 }
459
460 return s.kvStore.Set(0, rlm, StoreKeyEmissionRewardManager, manager)
461}
462
463// Returns:
464// - bool: true when the protocol-fee reward-manager key is present in storage.
465func (s *govStakerStore) HasProtocolFeeRewardManagerStoreKey() bool {
466 return s.kvStore.Has(StoreKeyProtocolFeeRewardManager)
467}
468
469// GetProtocolFeeRewardManager returns the persisted protocol-fee reward manager.
470//
471// Returns:
472// - *ProtocolFeeRewardManager: protocol-fee reward accounting state; panics on missing or invalid storage.
473func (s *govStakerStore) GetProtocolFeeRewardManager() *ProtocolFeeRewardManager {
474 result, err := s.kvStore.Get(StoreKeyProtocolFeeRewardManager)
475 if err != nil {
476 panic(err)
477 }
478
479 manager, ok := result.(*ProtocolFeeRewardManager)
480 if !ok {
481 panic(ufmt.Sprintf("failed to cast result to *ProtocolFeeRewardManager: %T", result))
482 }
483
484 return manager
485}
486
487// SetProtocolFeeRewardManager stores the protocol-fee reward manager.
488//
489// Parameters:
490// - _: Internal call discriminator; pass 0.
491// - rlm: Propagated realm context; the write is accepted only when this realm is current.
492// - manager: Protocol-fee reward accounting state to persist.
493//
494// Returns:
495// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
496func (s *govStakerStore) SetProtocolFeeRewardManager(_ int, rlm realm, manager *ProtocolFeeRewardManager) error {
497 if !rlm.IsCurrent() {
498 return errors.New(ErrSpoofedRealm)
499 }
500
501 return s.kvStore.Set(0, rlm, StoreKeyProtocolFeeRewardManager, manager)
502}
503
504// Returns:
505// - bool: true when the delegation-manager key is present in storage.
506func (s *govStakerStore) HasDelegationManagerStoreKey() bool {
507 return s.kvStore.Has(StoreKeyDelegationManager)
508}
509
510// GetDelegationManager returns the persisted delegation manager.
511//
512// Returns:
513// - *DelegationManager: delegation-management state; panics on missing or invalid storage.
514func (s *govStakerStore) GetDelegationManager() *DelegationManager {
515 result, err := s.kvStore.Get(StoreKeyDelegationManager)
516 if err != nil {
517 panic(err)
518 }
519
520 manager, ok := result.(*DelegationManager)
521 if !ok {
522 panic(ufmt.Sprintf("failed to cast result to *DelegationManager: %T", result))
523 }
524
525 return manager
526}
527
528// SetDelegationManager stores the delegation manager.
529//
530// Parameters:
531// - _: Internal call discriminator; pass 0.
532// - rlm: Propagated realm context; the write is accepted only when this realm is current.
533// - manager: Delegation-management state to persist.
534//
535// Returns:
536// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
537func (s *govStakerStore) SetDelegationManager(_ int, rlm realm, manager *DelegationManager) error {
538 if !rlm.IsCurrent() {
539 return errors.New(ErrSpoofedRealm)
540 }
541
542 return s.kvStore.Set(0, rlm, StoreKeyDelegationManager, manager)
543}
544
545// Returns:
546// - bool: true when the launchpad-project-deposits key is present in storage.
547func (s *govStakerStore) HasLaunchpadProjectDepositsStoreKey() bool {
548 return s.kvStore.Has(StoreKeyLaunchpadProjectDeposits)
549}
550
551// GetLaunchpadProjectDeposits returns persisted launchpad project deposit state.
552//
553// Returns:
554// - *LaunchpadProjectDeposits: launchpad deposit accounting state; panics on missing or invalid storage.
555func (s *govStakerStore) GetLaunchpadProjectDeposits() *LaunchpadProjectDeposits {
556 result, err := s.kvStore.Get(StoreKeyLaunchpadProjectDeposits)
557 if err != nil {
558 panic(err)
559 }
560
561 deposits, ok := result.(*LaunchpadProjectDeposits)
562 if !ok {
563 panic(ufmt.Sprintf("failed to cast result to *LaunchpadProjectDeposits: %T", result))
564 }
565
566 return deposits
567}
568
569// SetLaunchpadProjectDeposits stores launchpad project deposit state.
570//
571// Parameters:
572// - _: Internal call discriminator; pass 0.
573// - rlm: Propagated realm context; the write is accepted only when this realm is current.
574// - deposits: Launchpad project deposit accounting state to persist.
575//
576// Returns:
577// - error: nil on success; ErrSpoofedRealm when rlm is not current, or the underlying KV-store error.
578func (s *govStakerStore) SetLaunchpadProjectDeposits(_ int, rlm realm, deposits *LaunchpadProjectDeposits) error {
579 if !rlm.IsCurrent() {
580 return errors.New(ErrSpoofedRealm)
581 }
582
583 return s.kvStore.Set(0, rlm, StoreKeyLaunchpadProjectDeposits, deposits)
584}