Kind Realm (renderable)
Name protocol_fee
Namespace gnoswap
Exported functions 29
Module gno.land/r/gnoswap/protocol_fee
gno 0.9 store.gno gno
⧉
1 package protocol_fee 2 3 import ( 4 "errors" 5 6 bptree "gno.land/p/nt/bptree/v0" 7 ufmt "gno.land/p/nt/ufmt/v0" 8 AddToProtocolFee (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, tokenPath string, amount int64) interface {Error func() string}
AdvanceAccrualEpoch (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}) int64
ConsumeAccrualBuckets (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, tokenPath string, limit int) ([]int64, []int64)
DistributeProtocolFee (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string})
DistributeProtocolFeeByTokenPath (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, tokenPath string)
GetAccrualBuckets (tokenPath string, limit int) ([]int64, []int64)
GetAccrualEpoch () int64
GetAccrualPendingTokens () []string
GetAccuTransfersToDevOps () map[string]int64
GetAccuTransfersToGovStaker () map[string]int64
GetAccuTransferToDevOpsByTokenPath (tokenPath string) int64
GetAccuTransferToGovStakerByTokenPath (tokenPath string) int64
GetActualDistributedToDevOps () map[string]int64
GetActualDistributedToDevOpsByTokenPath (tokenPath string) int64
GetActualDistributedToGovStaker () map[string]int64
GetActualDistributedToGovStakerByTokenPath (tokenPath string) int64
GetDevOpsPct () int64
GetDomainPath () string
GetGovStakerPct () int64
GetImplementationPackagePath () string
GetReservedTokens () []string
GetVersionPackagePath () string
NewBPTreeN (fanout int) *gno.land/p/nt/bptree/v0.BPTree
NewProtocolFeeStore (kvStore interface {AddAuthorizedCaller func(int, .uverse.realm, .uverse.address, gno.land/p/gnoswap/store/v1.Permission) .uverse.error; Delete func(int, .uverse.realm, string) .uverse.error; Get func(string) (interface {}, .uverse.error); GetAddress func(string) (.uverse.address, .uverse.error); GetAllKeys func() ([]string, .uverse.error); GetAuthorizedCallers func() (map[.uverse.address]gno.land/p/gnoswap/store/v1.Permission, .uverse.error); GetBPTree func(string) (*gno.land/p/nt/bptree/v0.BPTree, .uverse.error); GetBool func(string) (bool, .uverse.error); GetDomainAddress func() .uverse.address; GetInt64 func(string) (int64, .uverse.error); GetString func(string) (string, .uverse.error); GetUint64 func(string) (uint64, .uverse.error); Has func(string) bool; IsWriteAuthorized func(.uverse.address) bool; RemoveAuthorizedCaller func(int, .uverse.realm, .uverse.address) .uverse.error; Set func(int, .uverse.realm, string, interface {}) .uverse.error; UpdateAuthorizedCaller func(int, .uverse.realm, .uverse.address, gno.land/p/gnoswap/store/v1.Permission) .uverse.error}) interface {AddAccrualBucket func(int, .uverse.realm, string, int64, int64) .uverse.error; AddAccrualPendingToken func(int, .uverse.realm, string) .uverse.error; AddReservedToken func(int, .uverse.realm, string) .uverse.error; GetAccrualBuckets func(string, int) ([]int64, []int64); GetAccrualEpoch func() int64; GetAccrualPendingTokens func() []string; GetAccuToDevOps func() *gno.land/p/nt/bptree/v0.BPTree; GetAccuToDevOpsItem func(string) (int64, bool); GetAccuToGovStaker func() *gno.land/p/nt/bptree/v0.BPTree; GetAccuToGovStakerItem func(string) (int64, bool); GetDevOpsPct func() int64; GetDistributedToDevOpsHistory func() *gno.land/p/nt/bptree/v0.BPTree; GetDistributedToDevOpsHistoryItem func(string) (int64, bool); GetDistributedToGovStakerHistory func() *gno.land/p/nt/bptree/v0.BPTree; GetDistributedToGovStakerHistoryItem func(string) (int64, bool); GetReservedTokens func() []string; HasAccrualBucketsStoreKey func() bool; HasAccrualEpochStoreKey func() bool; HasAccrualPendingTokensStoreKey func() bool; HasAccuToDevOpsStoreKey func() bool; HasAccuToGovStakerStoreKey func() bool; HasDevOpsPctStoreKey func() bool; HasDistributedToDevOpsHistoryStoreKey func() bool; HasDistributedToGovStakerHistoryStoreKey func() bool; HasReservedToken func(string) bool; HasReservedTokensStoreKey func() bool; InitializeAccrualBuckets func(int, .uverse.realm) .uverse.error; InitializeAccrualEpoch func(int, .uverse.realm) .uverse.error; InitializeAccrualPendingTokens func(int, .uverse.realm) .uverse.error; InitializeAccuToDevOps func(int, .uverse.realm) .uverse.error; InitializeAccuToGovStaker func(int, .uverse.realm) .uverse.error; InitializeDevOpsPct func(int, .uverse.realm) .uverse.error; InitializeDistributedToDevOpsHistory func(int, .uverse.realm) .uverse.error; InitializeDistributedToGovStakerHistory func(int, .uverse.realm) .uverse.error; InitializeReservedTokens func(int, .uverse.realm) .uverse.error; RemoveAccrualBuckets func(int, .uverse.realm, string, []int64) .uverse.error; RemoveAccrualPendingToken func(int, .uverse.realm, string) .uverse.error; RemoveReservedToken func(int, .uverse.realm, string) .uverse.error; SetAccrualEpoch func(int, .uverse.realm, int64) .uverse.error; SetAccuToDevOpsItem func(int, .uverse.realm, string, int64) .uverse.error; SetAccuToGovStakerItem func(int, .uverse.realm, string, int64) .uverse.error; SetDevOpsPct func(int, .uverse.realm, int64) .uverse.error; SetDistributedToDevOpsHistoryItem func(int, .uverse.realm, string, int64) .uverse.error; SetDistributedToGovStakerHistoryItem func(int, .uverse.realm, string, int64) .uverse.error}
RegisterInitializer (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, initializer func(int, .uverse.realm, gno.land/r/gnoswap/protocol_fee.IProtocolFeeStore) gno.land/r/gnoswap/protocol_fee.IProtocolFee)
Render (path string) string
SetDevOpsPct (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, pct int64)
SetGovStakerPct (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, pct int64)
UpgradeImpl (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, packagePath string)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
9 "gno.land/p/gnoswap/gnsmath/v1"
10 "gno.land/p/gnoswap/store/v1"
11 "gno.land/p/gnoswap/utils/v1"
12 )
13
14 type StoreKey string
15
16 // String returns the textual store-key value.
17 //
18 // Returns:
19 // - key: The string representation of the StoreKey.
20 func (s StoreKey) String() string {
21 return string (s)
22 }
23
24 const (
25 // By default, devOps will get 0% of the protocol fee (which means gov/staker will get 100% of the protocol fee)
26 // This percentage can be modified through governance.
27 StoreKeyDevOpsPct StoreKey = "devOpsPct"
28
29 // accuToGovStaker tracks the cumulative amount allocated to GovStaker,
30 // including allocations that are still pending distribution.
31 StoreKeyAccuToGovStaker StoreKey = "accuToGovStaker" // tokenPath -> amount
32 // accuToDevOps tracks the cumulative amount allocated to DevOps,
33 // including allocations that are still pending distribution.
34 StoreKeyAccuToDevOps StoreKey = "accuToDevOps" // tokenPath -> amount
35
36 // Distribution-history trees track cumulative amounts actually transferred.
37 StoreKeyDistributedToGovStakerHistory StoreKey = "distributedToGovStakerHistory" // tokenPath -> amount
38 StoreKeyDistributedToDevOpsHistory StoreKey = "distributedToDevOpsHistory" // tokenPath -> amount
39
40 // reservedTokens tracks token paths collected but not yet distributed.
41 StoreKeyReservedTokens StoreKey = "reservedTokens"
42
43 // accrualEpoch, accrualBuckets and accrualPendingTokens track the gov/staker share
44 // per token path and accrual epoch until gov/staker folds it into its accumulator.
45 StoreKeyAccrualEpoch StoreKey = "accrualEpoch"
46 StoreKeyAccrualBuckets StoreKey = "accrualBuckets" // tokenPath -> (epoch -> amount)
47 StoreKeyAccrualPendingTokens StoreKey = "accrualPendingTokens" // tokenPath -> true
48 )
49
50 const (
51 defaultDevOpsPct = int64 ( 0 )
52 errSpoofedRealm = "rlm does not match the current crossing frame"
53 )
54
55 // NewBPTreeN allocates a BP-tree under /r/gnoswap/protocol_fee's realm context
56 // so tree.Set leaf-slot writes clear the readonly-taint gate regardless of
57 // which realm (protocol_fee/v1, mock, tests) calls Set. Callers must allocate
58 // protocol_fee trees through here rather than bptree.NewBPTreeN directly.
59 //
60 // Parameters:
61 // - fanout: Branching factor passed to the BP-tree constructor.
62 //
63 // Returns:
64 // - tree: A new BP-tree configured with fanout and allocated in the protocol-fee realm context.
65 func NewBPTreeN(fanout int ) *bptree.BPTree {
66 return bptree.NewBPTreeN(fanout)
67 }
68
69 type protocolFeeStore struct {
70 kvStore store.KVStore
71 }
72
73 // handle devOpsPct store data
74 //
75 // Returns:
76 // - exists: True when the DevOps percentage store key is present in the KV store.
77 func (s *protocolFeeStore) HasDevOpsPctStoreKey() bool {
78 return s.kvStore.Has(StoreKeyDevOpsPct.String())
79 }
80
81 // InitializeDevOpsPct creates the DevOps allocation percentage entry with its default value.
82 //
83 // Parameters:
84 // - _: Crossing discriminator for the store operation; pass 0.
85 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
86 //
87 // Returns:
88 // - err: Nil when the key is initialized; otherwise the current-realm or KV-store write error.
89 func (s *protocolFeeStore) InitializeDevOpsPct(_ int , rlm realm) error {
90 if !rlm.IsCurrent() {
91 return errors.New(errSpoofedRealm)
92 }
93
94 return s.kvStore.Set( 0 , rlm, StoreKeyDevOpsPct.String(), defaultDevOpsPct)
95 }
96
97 // GetDevOpsPct reads the persisted DevOps allocation percentage.
98 //
99 // Returns:
100 // - pct: The stored DevOps allocation percentage in basis points; the method panics if the key is missing or cannot be decoded as int64.
101 func (s *protocolFeeStore) GetDevOpsPct() int64 {
102 devOpsPct, err := s.kvStore.GetInt64(StoreKeyDevOpsPct.String())
103 if err != nil {
104 panic(err)
105 }
106
107 return devOpsPct
108 }
109
110 // SetDevOpsPct persists the DevOps allocation percentage.
111 //
112 // Parameters:
113 // - _: Crossing discriminator for the store operation; pass 0.
114 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
115 // - pct: DevOps share of protocol fees in basis points; the state layer constrains this value to 0 through 10000 before calling the store.
116 //
117 // Returns:
118 // - err: Nil when the percentage is persisted; otherwise the current-realm or KV-store write error.
119 func (s *protocolFeeStore) SetDevOpsPct(_ int , rlm realm, pct int64 ) error {
120 if !rlm.IsCurrent() {
121 return errors.New(errSpoofedRealm)
122 }
123
124 return s.kvStore.Set( 0 , rlm, StoreKeyDevOpsPct.String(), pct)
125 }
126
127 // handle accuToGovStaker store data
128 //
129 // Returns:
130 // - exists: True when the cumulative Gov/Staker allocation tree key is present in the KV store.
131 func (s *protocolFeeStore) HasAccuToGovStakerStoreKey() bool {
132 return s.kvStore.Has(StoreKeyAccuToGovStaker.String())
133 }
134
135 // InitializeAccuToGovStaker creates the cumulative Gov/Staker allocation tree.
136 //
137 // Parameters:
138 // - _: Crossing discriminator for the store operation; pass 0.
139 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
140 //
141 // Returns:
142 // - err: Nil when the tree is initialized; otherwise the current-realm or KV-store write error.
143 func (s *protocolFeeStore) InitializeAccuToGovStaker(_ int , rlm realm) error {
144 if !rlm.IsCurrent() {
145 return errors.New(errSpoofedRealm)
146 }
147
148 return s.kvStore.Set( 0 , rlm, StoreKeyAccuToGovStaker.String(), NewBPTreeN( 16 ))
149 }
150
151 // GetAccuToGovStaker reads the cumulative Gov/Staker allocation tree.
152 //
153 // Returns:
154 // - tree: The BP-tree mapping token paths to cumulative amounts; the method panics if the store value is absent or has the wrong type.
155 func (s *protocolFeeStore) GetAccuToGovStaker() *bptree.BPTree {
156 accuToGovStaker, err := s.kvStore.GetBPTree(StoreKeyAccuToGovStaker.String())
157 if err != nil {
158 panic(err)
159 }
160
161 return accuToGovStaker
162 }
163
164 // GetAccuToGovStakerItem reads one token's cumulative Gov/Staker allocation.
165 //
166 // Parameters:
167 // - tokenPath: Token path whose cumulative allocation should be looked up.
168 //
169 // Returns:
170 // - amount: The stored cumulative allocation for tokenPath, or zero when no entry exists.
171 // - found: True when tokenPath has an entry in the allocation tree; false when it is absent.
172 func (s *protocolFeeStore) GetAccuToGovStakerItem(tokenPath string ) ( int64 , bool ) {
173 accuToGovStaker, err := s.kvStore.GetBPTree(StoreKeyAccuToGovStaker.String())
174 if err != nil {
175 panic(err)
176 }
177
178 result := accuToGovStaker.Get(tokenPath)
179 if result == nil {
180 return 0 , false
181 }
182
183 amount, ok := result.( int64 )
184 if !ok {
185 panic(ufmt.Errorf( "failed to cast result to int64: %T" , result))
186 }
187
188 return amount, true
189 }
190
191 // SetAccuToGovStakerItem updates one token's cumulative Gov/Staker allocation.
192 //
193 // Parameters:
194 // - _: Crossing discriminator for the store operation; pass 0.
195 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
196 // - tokenPath: Token path whose cumulative allocation is replaced.
197 // - amount: Cumulative Gov/Staker allocation to store for tokenPath.
198 //
199 // Returns:
200 // - err: Nil when the allocation tree is persisted; otherwise the current-realm, tree-read, or KV-store write error.
201 func (s *protocolFeeStore) SetAccuToGovStakerItem(_ int , rlm realm, tokenPath string , amount int64 ) error {
202 if !rlm.IsCurrent() {
203 return errors.New(errSpoofedRealm)
204 }
205
206 accuToGovStaker, err := s.kvStore.GetBPTree(StoreKeyAccuToGovStaker.String())
207 if err != nil {
208 return err
209 }
210
211 accuToGovStaker.Set(tokenPath, amount)
212
213 return s.kvStore.Set( 0 , rlm, StoreKeyAccuToGovStaker.String(), accuToGovStaker)
214 }
215
216 // handle accuToDevOps store data
217 //
218 // Returns:
219 // - exists: True when the cumulative DevOps allocation tree key is present in the KV store.
220 func (s *protocolFeeStore) HasAccuToDevOpsStoreKey() bool {
221 return s.kvStore.Has(StoreKeyAccuToDevOps.String())
222 }
223
224 // InitializeAccuToDevOps creates the cumulative DevOps allocation tree.
225 //
226 // Parameters:
227 // - _: Crossing discriminator for the store operation; pass 0.
228 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
229 //
230 // Returns:
231 // - err: Nil when the tree is initialized; otherwise the current-realm or KV-store write error.
232 func (s *protocolFeeStore) InitializeAccuToDevOps(_ int , rlm realm) error {
233 if !rlm.IsCurrent() {
234 return errors.New(errSpoofedRealm)
235 }
236
237 return s.kvStore.Set( 0 , rlm, StoreKeyAccuToDevOps.String(), NewBPTreeN( 16 ))
238 }
239
240 // GetAccuToDevOps reads the cumulative DevOps allocation tree.
241 //
242 // Returns:
243 // - tree: The BP-tree mapping token paths to cumulative amounts; the method panics if the store value is absent or has the wrong type.
244 func (s *protocolFeeStore) GetAccuToDevOps() *bptree.BPTree {
245 accuToDevOps, err := s.kvStore.GetBPTree(StoreKeyAccuToDevOps.String())
246 if err != nil {
247 panic(err)
248 }
249
250 return accuToDevOps
251 }
252
253 // GetAccuToDevOpsItem reads one token's cumulative DevOps allocation.
254 //
255 // Parameters:
256 // - tokenPath: Token path whose cumulative allocation should be looked up.
257 //
258 // Returns:
259 // - amount: The stored cumulative allocation for tokenPath, or zero when no entry exists.
260 // - found: True when tokenPath has an entry in the allocation tree; false when it is absent.
261 func (s *protocolFeeStore) GetAccuToDevOpsItem(tokenPath string ) ( int64 , bool ) {
262 accuToDevOps, err := s.kvStore.GetBPTree(StoreKeyAccuToDevOps.String())
263 if err != nil {
264 panic(err)
265 }
266
267 result := accuToDevOps.Get(tokenPath)
268 if result == nil {
269 return 0 , false
270 }
271
272 amount, ok := result.( int64 )
273 if !ok {
274 panic(ufmt.Errorf( "failed to cast result to int64: %T" , result))
275 }
276
277 return amount, true
278 }
279
280 // SetAccuToDevOpsItem updates one token's cumulative DevOps allocation.
281 //
282 // Parameters:
283 // - _: Crossing discriminator for the store operation; pass 0.
284 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
285 // - tokenPath: Token path whose cumulative allocation is replaced.
286 // - amount: Cumulative DevOps allocation to store for tokenPath.
287 //
288 // Returns:
289 // - err: Nil when the allocation tree is persisted; otherwise the current-realm, tree-read, or KV-store write error.
290 func (s *protocolFeeStore) SetAccuToDevOpsItem(_ int , rlm realm, tokenPath string , amount int64 ) error {
291 if !rlm.IsCurrent() {
292 return errors.New(errSpoofedRealm)
293 }
294
295 accuToDevOps, err := s.kvStore.GetBPTree(StoreKeyAccuToDevOps.String())
296 if err != nil {
297 return err
298 }
299
300 accuToDevOps.Set(tokenPath, amount)
301
302 return s.kvStore.Set( 0 , rlm, StoreKeyAccuToDevOps.String(), accuToDevOps)
303 }
304
305 // handle distributedToGovStakerHistory store data
306 // HasDistributedToGovStakerHistoryStoreKey reports whether the Gov/Staker distribution-history tree exists.
307 //
308 // Returns:
309 // - exists: True when the Gov/Staker distribution-history tree key is present in the KV store.
310 func (s *protocolFeeStore) HasDistributedToGovStakerHistoryStoreKey() bool {
311 return s.kvStore.Has(StoreKeyDistributedToGovStakerHistory.String())
312 }
313
314 // InitializeDistributedToGovStakerHistory creates the Gov/Staker distribution-history tree.
315 //
316 // Parameters:
317 // - _: Crossing discriminator for the store operation; pass 0.
318 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
319 //
320 // Returns:
321 // - err: Nil when the history tree is initialized; otherwise the current-realm or KV-store write error.
322 func (s *protocolFeeStore) InitializeDistributedToGovStakerHistory(_ int , rlm realm) error {
323 if !rlm.IsCurrent() {
324 return errors.New(errSpoofedRealm)
325 }
326
327 return s.kvStore.Set( 0 , rlm, StoreKeyDistributedToGovStakerHistory.String(), NewBPTreeN( 16 ))
328 }
329
330 // GetDistributedToGovStakerHistory reads the cumulative Gov/Staker distribution-history tree.
331 //
332 // Returns:
333 // - tree: The BP-tree mapping token paths to amounts actually distributed to Gov/Staker; the method panics if the stored value is absent or has the wrong type.
334 func (s *protocolFeeStore) GetDistributedToGovStakerHistory() *bptree.BPTree {
335 distributedToGovStakerHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToGovStakerHistory.String())
336 if err != nil {
337 panic(err)
338 }
339
340 return distributedToGovStakerHistory
341 }
342
343 // GetDistributedToGovStakerHistoryItem reads one token's cumulative Gov/Staker distribution history.
344 //
345 // Parameters:
346 // - tokenPath: Token path whose distributed amount should be looked up.
347 //
348 // Returns:
349 // - amount: The stored cumulative amount distributed to Gov/Staker for tokenPath, or zero when no entry exists.
350 // - found: True when tokenPath has a history entry; false when it is absent.
351 func (s *protocolFeeStore) GetDistributedToGovStakerHistoryItem(tokenPath string ) ( int64 , bool ) {
352 distributedToGovStakerHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToGovStakerHistory.String())
353 if err != nil {
354 panic(err)
355 }
356
357 result := distributedToGovStakerHistory.Get(tokenPath)
358 if result == nil {
359 return 0 , false
360 }
361
362 amount, ok := result.( int64 )
363 if !ok {
364 panic(ufmt.Errorf( "failed to cast result to int64: %T" , result))
365 }
366
367 return amount, true
368 }
369
370 // SetDistributedToGovStakerHistoryItem updates one token's cumulative Gov/Staker distribution history.
371 //
372 // Parameters:
373 // - _: Crossing discriminator for the store operation; pass 0.
374 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
375 // - tokenPath: Token path whose distributed amount is replaced.
376 // - amount: Cumulative amount actually distributed to Gov/Staker to store for tokenPath.
377 //
378 // Returns:
379 // - err: Nil when the history tree is persisted; otherwise the current-realm, tree-read, or KV-store write error.
380 func (s *protocolFeeStore) SetDistributedToGovStakerHistoryItem(_ int , rlm realm, tokenPath string , amount int64 ) error {
381 if !rlm.IsCurrent() {
382 return errors.New(errSpoofedRealm)
383 }
384
385 distributedToGovStakerHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToGovStakerHistory.String())
386 if err != nil {
387 return err
388 }
389
390 distributedToGovStakerHistory.Set(tokenPath, amount)
391
392 return s.kvStore.Set( 0 , rlm, StoreKeyDistributedToGovStakerHistory.String(), distributedToGovStakerHistory)
393 }
394
395 // HasDistributedToDevOpsHistoryStoreKey reports whether the DevOps distribution-history tree exists.
396 //
397 // Returns:
398 // - exists: True when the DevOps distribution-history tree key is present in the KV store.
399 //
400 // handle distributedToDevOpsHistory store data
401 func (s *protocolFeeStore) HasDistributedToDevOpsHistoryStoreKey() bool {
402 return s.kvStore.Has(StoreKeyDistributedToDevOpsHistory.String())
403 }
404
405 // InitializeDistributedToDevOpsHistory creates the DevOps distribution-history tree.
406 //
407 // Parameters:
408 // - _: Crossing discriminator for the store operation; pass 0.
409 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
410 //
411 // Returns:
412 // - err: Nil when the history tree is initialized; otherwise the current-realm or KV-store write error.
413 func (s *protocolFeeStore) InitializeDistributedToDevOpsHistory(_ int , rlm realm) error {
414 if !rlm.IsCurrent() {
415 return errors.New(errSpoofedRealm)
416 }
417
418 return s.kvStore.Set( 0 , rlm, StoreKeyDistributedToDevOpsHistory.String(), NewBPTreeN( 16 ))
419 }
420
421 // GetDistributedToDevOpsHistory reads the cumulative DevOps distribution-history tree.
422 //
423 // Returns:
424 // - tree: The BP-tree mapping token paths to amounts actually distributed to DevOps; the method panics if the stored value is absent or has the wrong type.
425 func (s *protocolFeeStore) GetDistributedToDevOpsHistory() *bptree.BPTree {
426 distributedToDevOpsHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToDevOpsHistory.String())
427 if err != nil {
428 panic(err)
429 }
430
431 return distributedToDevOpsHistory
432 }
433
434 // GetDistributedToDevOpsHistoryItem reads one token's cumulative DevOps distribution history.
435 //
436 // Parameters:
437 // - tokenPath: Token path whose distributed amount should be looked up.
438 //
439 // Returns:
440 // - amount: The stored cumulative amount distributed to DevOps for tokenPath, or zero when no entry exists.
441 // - found: True when tokenPath has a history entry; false when it is absent.
442 func (s *protocolFeeStore) GetDistributedToDevOpsHistoryItem(tokenPath string ) ( int64 , bool ) {
443 distributedToDevOpsHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToDevOpsHistory.String())
444 if err != nil {
445 panic(err)
446 }
447
448 result := distributedToDevOpsHistory.Get(tokenPath)
449 if result == nil {
450 return 0 , false
451 }
452
453 amount, ok := result.( int64 )
454 if !ok {
455 panic(ufmt.Errorf( "failed to cast result to int64: %T" , result))
456 }
457
458 return amount, true
459 }
460
461 // SetDistributedToDevOpsHistoryItem updates one token's cumulative DevOps distribution history.
462 //
463 // Parameters:
464 // - _: Crossing discriminator for the store operation; pass 0.
465 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
466 // - tokenPath: Token path whose distributed amount is replaced.
467 // - amount: Cumulative amount actually distributed to DevOps to store for tokenPath.
468 //
469 // Returns:
470 // - err: Nil when the history tree is persisted; otherwise the current-realm, tree-read, or KV-store write error.
471 func (s *protocolFeeStore) SetDistributedToDevOpsHistoryItem(_ int , rlm realm, tokenPath string , amount int64 ) error {
472 if !rlm.IsCurrent() {
473 return errors.New(errSpoofedRealm)
474 }
475
476 distributedToDevOpsHistory, err := s.kvStore.GetBPTree(StoreKeyDistributedToDevOpsHistory.String())
477 if err != nil {
478 return err
479 }
480
481 distributedToDevOpsHistory.Set(tokenPath, amount)
482
483 return s.kvStore.Set( 0 , rlm, StoreKeyDistributedToDevOpsHistory.String(), distributedToDevOpsHistory)
484 }
485
486 // handle reservedTokens store data
487 //
488 // reservedTokens is the set of token paths that collected a fee not yet transferred out
489 // by DistributeProtocolFee. It is kept as a tree so that a single token can be added or
490 // settled without rewriting the whole set.
491 //
492 // Returns:
493 // - exists: True when the reserved-token index key is present in the KV store.
494 func (s *protocolFeeStore) HasReservedTokensStoreKey() bool {
495 return s.kvStore.Has(StoreKeyReservedTokens.String())
496 }
497
498 // InitializeReservedTokens creates the reserved-token index tree.
499 //
500 // Parameters:
501 // - _: Crossing discriminator for the store operation; pass 0.
502 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
503 //
504 // Returns:
505 // - err: Nil when the index tree is initialized; otherwise the current-realm or KV-store write error.
506 func (s *protocolFeeStore) InitializeReservedTokens(_ int , rlm realm) error {
507 if !rlm.IsCurrent() {
508 return errors.New(errSpoofedRealm)
509 }
510
511 return s.kvStore.Set( 0 , rlm, StoreKeyReservedTokens.String(), NewBPTreeN( 16 ))
512 }
513
514 func (s *protocolFeeStore) getReservedTokenTree() *bptree.BPTree {
515 reservedTokens, err := s.kvStore.GetBPTree(StoreKeyReservedTokens.String())
516 if err != nil {
517 panic(err)
518 }
519
520 return reservedTokens
521 }
522
523 // GetReservedTokens returns all token paths currently reserved for distribution.
524 //
525 // Returns:
526 // - tokenPaths: Token paths present in the reserved-token index, in BP-tree iteration order.
527 func (s *protocolFeeStore) GetReservedTokens() [] string {
528 return collectTreeKeys(s.getReservedTokenTree())
529 }
530
531 // HasReservedToken reports whether tokenPath is currently reserved for distribution.
532 //
533 // Parameters:
534 // - tokenPath: Token path to look up in the reserved-token index.
535 //
536 // Returns:
537 // - exists: True when tokenPath is in the reserved-token index; false otherwise.
538 func (s *protocolFeeStore) HasReservedToken(tokenPath string ) bool {
539 return s.getReservedTokenTree().Has(tokenPath)
540 }
541
542 // AddReservedToken adds tokenPath to the reserved-token index.
543 //
544 // Parameters:
545 // - _: Crossing discriminator for the store operation; pass 0.
546 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
547 // - tokenPath: Token path collected for protocol-fee distribution.
548 //
549 // Returns:
550 // - err: Nil when tokenPath is already present or has been added; otherwise the current-realm or KV-store write error.
551 func (s *protocolFeeStore) AddReservedToken(_ int , rlm realm, tokenPath string ) error {
552 if !rlm.IsCurrent() {
553 return errors.New(errSpoofedRealm)
554 }
555
556 reservedTokens := s.getReservedTokenTree()
557 if reservedTokens.Has(tokenPath) {
558 return nil
559 }
560
561 reservedTokens.Set(tokenPath, true )
562
563 return s.kvStore.Set( 0 , rlm, StoreKeyReservedTokens.String(), reservedTokens)
564 }
565
566 // RemoveReservedToken removes one tokenPath from the reserved-token set when present.
567 //
568 // Parameters:
569 // - _: Crossing discriminator for the store operation; pass 0.
570 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
571 // - tokenPath: Token path to remove from the reserved-token set.
572 //
573 // Returns:
574 // - err: Nil when tokenPath is absent or has been removed; otherwise the current-realm or KV-store write error.
575 func (s *protocolFeeStore) RemoveReservedToken(_ int , rlm realm, tokenPath string ) error {
576 if !rlm.IsCurrent() {
577 return errors.New(errSpoofedRealm)
578 }
579
580 reservedTokens := s.getReservedTokenTree()
581 if _, removed := reservedTokens.Remove(tokenPath); !removed {
582 return nil
583 }
584
585 return s.kvStore.Set( 0 , rlm, StoreKeyReservedTokens.String(), reservedTokens)
586 }
587
588 // handle accrualEpoch store data
589 //
590 // accrualEpoch numbers the intervals between gov/staker stake changes. gov/staker
591 // advances it on every stake change, so every fee that arrives is attributed to the
592 // stake distribution in force when it arrived.
593 //
594 // Returns:
595 // - exists: True when the accrual-epoch store key is present in the KV store.
596 func (s *protocolFeeStore) HasAccrualEpochStoreKey() bool {
597 return s.kvStore.Has(StoreKeyAccrualEpoch.String())
598 }
599
600 // InitializeAccrualEpoch initializes the current fee-accrual epoch to zero.
601 //
602 // Parameters:
603 // - _: Crossing discriminator for the store operation; pass 0.
604 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
605 //
606 // Returns:
607 // - err: Nil when the epoch key is initialized; otherwise the current-realm or KV-store write error.
608 func (s *protocolFeeStore) InitializeAccrualEpoch(_ int , rlm realm) error {
609 if !rlm.IsCurrent() {
610 return errors.New(errSpoofedRealm)
611 }
612
613 return s.kvStore.Set( 0 , rlm, StoreKeyAccrualEpoch.String(), int64 ( 0 ))
614 }
615
616 // GetAccrualEpoch reads the epoch under which new Gov/Staker accrual buckets are recorded.
617 //
618 // Returns:
619 // - epoch: The persisted current accrual epoch; the method panics if the key is missing or cannot be decoded as int64.
620 func (s *protocolFeeStore) GetAccrualEpoch() int64 {
621 accrualEpoch, err := s.kvStore.GetInt64(StoreKeyAccrualEpoch.String())
622 if err != nil {
623 panic(err)
624 }
625
626 return accrualEpoch
627 }
628
629 // SetAccrualEpoch persists the current fee-accrual epoch.
630 //
631 // Parameters:
632 // - _: Crossing discriminator for the store operation; pass 0.
633 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
634 // - accrualEpoch: Epoch number assigned to newly collected Gov/Staker accrual buckets.
635 //
636 // Returns:
637 // - err: Nil when the epoch is persisted; otherwise the current-realm or KV-store write error.
638 func (s *protocolFeeStore) SetAccrualEpoch(_ int , rlm realm, accrualEpoch int64 ) error {
639 if !rlm.IsCurrent() {
640 return errors.New(errSpoofedRealm)
641 }
642
643 return s.kvStore.Set( 0 , rlm, StoreKeyAccrualEpoch.String(), accrualEpoch)
644 }
645
646 // handle accrualBuckets store data
647 //
648 // accrualBuckets holds, per token path, the gov/staker share collected during each
649 // accrual epoch that gov/staker has not folded into its accumulator yet. Folding
650 // consumes the oldest buckets first, so a token is settled in epoch order.
651 //
652 // Returns:
653 // - exists: True when the accrual-bucket store key is present in the KV store.
654 func (s *protocolFeeStore) HasAccrualBucketsStoreKey() bool {
655 return s.kvStore.Has(StoreKeyAccrualBuckets.String())
656 }
657
658 // InitializeAccrualBuckets creates the nested accrual-bucket tree.
659 //
660 // Parameters:
661 // - _: Crossing discriminator for the store operation; pass 0.
662 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
663 //
664 // Returns:
665 // - err: Nil when the bucket tree is initialized; otherwise the current-realm or KV-store write error.
666 func (s *protocolFeeStore) InitializeAccrualBuckets(_ int , rlm realm) error {
667 if !rlm.IsCurrent() {
668 return errors.New(errSpoofedRealm)
669 }
670
671 return s.kvStore.Set( 0 , rlm, StoreKeyAccrualBuckets.String(), NewBPTreeN( 16 ))
672 }
673
674 func (s *protocolFeeStore) getAccrualBucketTree() *bptree.BPTree {
675 accrualBuckets, err := s.kvStore.GetBPTree(StoreKeyAccrualBuckets.String())
676 if err != nil {
677 panic(err)
678 }
679
680 return accrualBuckets
681 }
682
683 func (s *protocolFeeStore) getTokenAccrualBucketTree(accrualBuckets *bptree.BPTree, tokenPath string ) *bptree.BPTree {
684 result := accrualBuckets.Get(tokenPath)
685 if result == nil {
686 return nil
687 }
688
689 tokenBuckets, ok := result.(*bptree.BPTree)
690 if !ok {
691 panic(ufmt.Errorf( "failed to cast result to *bptree.BPTree: %T" , result))
692 }
693
694 return tokenBuckets
695 }
696
697 // GetAccrualBuckets returns up to limit of the oldest pending buckets of tokenPath in
698 // epoch order. A limit of zero or less returns every pending bucket.
699 //
700 // Parameters:
701 // - tokenPath: Token path whose pending Gov/Staker accrual buckets should be read.
702 // - limit: Maximum number of buckets to return; zero or a negative value returns all pending buckets.
703 //
704 // Returns:
705 // - epochs: Epoch numbers for the returned buckets, in ascending BP-tree iteration order.
706 // - amounts: Gov/Staker amounts for the returned epochs; amounts[i] corresponds to epochs[i].
707 func (s *protocolFeeStore) GetAccrualBuckets(tokenPath string , limit int ) ([] int64 , [] int64 ) {
708 epochs := [] int64 {}
709 amounts := [] int64 {}
710
711 tokenBuckets := s.getTokenAccrualBucketTree(s.getAccrualBucketTree(), tokenPath)
712 if tokenBuckets == nil {
713 return epochs, amounts
714 }
715
716 tokenBuckets.Iterate( "" , "" , func (key string , value any ) bool {
717 if limit > 0 && len(epochs) >= limit {
718 return true
719 }
720
721 amount, ok := value.( int64 )
722 if !ok {
723 panic(ufmt.Errorf( "failed to cast result to int64: %T" , value))
724 }
725
726 epochs = append(epochs, decodeEpochKey(key))
727 amounts = append(amounts, amount)
728
729 return false
730 })
731
732 return epochs, amounts
733 }
734
735 // AddAccrualBucket adds amount to the bucket of tokenPath at epoch.
736 //
737 // Parameters:
738 // - _: Crossing discriminator for the store operation; pass 0.
739 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
740 // - tokenPath: Token path whose Gov/Staker accrual bucket is updated.
741 // - epoch: Non-negative accrual epoch identifying the bucket; negative epochs panic during key encoding.
742 // - amount: Amount to add to the existing bucket value.
743 //
744 // Returns:
745 // - err: Nil when the bucket tree is persisted; otherwise the current-realm or KV-store write error.
746 func (s *protocolFeeStore) AddAccrualBucket(_ int , rlm realm, tokenPath string , epoch int64 , amount int64 ) error {
747 if !rlm.IsCurrent() {
748 return errors.New(errSpoofedRealm)
749 }
750
751 accrualBuckets := s.getAccrualBucketTree()
752 tokenBuckets := s.getTokenAccrualBucketTree(accrualBuckets, tokenPath)
753 if tokenBuckets == nil {
754 tokenBuckets = NewBPTreeN( 16 )
755 accrualBuckets.Set(tokenPath, tokenBuckets)
756 }
757
758 key := encodeEpochKey(epoch)
759 existing := int64 ( 0 )
760 if result := tokenBuckets.Get(key); result != nil {
761 current, ok := result.( int64 )
762 if !ok {
763 panic(ufmt.Errorf( "failed to cast result to int64: %T" , result))
764 }
765 existing = current
766 }
767
768 tokenBuckets.Set(key, gnsmath.SafeAddInt64(existing, amount))
769
770 return s.kvStore.Set( 0 , rlm, StoreKeyAccrualBuckets.String(), accrualBuckets)
771 }
772
773 // RemoveAccrualBuckets drops the buckets of tokenPath at the given epochs. The token's
774 // tree is dropped as well once no bucket remains.
775 //
776 // Parameters:
777 // - _: Crossing discriminator for the store operation; pass 0.
778 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
779 // - tokenPath: Token path whose selected accrual buckets are removed.
780 // - epochs: Epoch numbers whose buckets should be deleted; an absent token or epoch is ignored.
781 //
782 // Returns:
783 // - err: Nil when removals are applied (including an absent token); otherwise the current-realm or KV-store write error.
784 func (s *protocolFeeStore) RemoveAccrualBuckets(_ int , rlm realm, tokenPath string , epochs [] int64 ) error {
785 if !rlm.IsCurrent() {
786 return errors.New(errSpoofedRealm)
787 }
788
789 accrualBuckets := s.getAccrualBucketTree()
790 tokenBuckets := s.getTokenAccrualBucketTree(accrualBuckets, tokenPath)
791 if tokenBuckets == nil {
792 return nil
793 }
794
795 for _, epoch := range epochs {
796 tokenBuckets.Remove(encodeEpochKey(epoch))
797 }
798
799 if tokenBuckets.Size() == 0 {
800 accrualBuckets.Remove(tokenPath)
801 }
802
803 return s.kvStore.Set( 0 , rlm, StoreKeyAccrualBuckets.String(), accrualBuckets)
804 }
805
806 // handle accrualPendingTokens store data
807 //
808 // accrualPendingTokens is the set of token paths that still own at least one accrual
809 // bucket, so gov/staker can enumerate what it has to fold without scanning every token.
810 //
811 // Returns:
812 // - exists: True when the pending-token index key is present in the KV store.
813 func (s *protocolFeeStore) HasAccrualPendingTokensStoreKey() bool {
814 return s.kvStore.Has(StoreKeyAccrualPendingTokens.String())
815 }
816
817 // InitializeAccrualPendingTokens creates the index of tokens with pending accrual buckets.
818 //
819 // Parameters:
820 // - _: Crossing discriminator for the store operation; pass 0.
821 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
822 //
823 // Returns:
824 // - err: Nil when the pending-token index is initialized; otherwise the current-realm or KV-store write error.
825 func (s *protocolFeeStore) InitializeAccrualPendingTokens(_ int , rlm realm) error {
826 if !rlm.IsCurrent() {
827 return errors.New(errSpoofedRealm)
828 }
829
830 return s.kvStore.Set( 0 , rlm, StoreKeyAccrualPendingTokens.String(), NewBPTreeN( 16 ))
831 }
832
833 func (s *protocolFeeStore) getAccrualPendingTokenTree() *bptree.BPTree {
834 accrualPendingTokens, err := s.kvStore.GetBPTree(StoreKeyAccrualPendingTokens.String())
835 if err != nil {
836 panic(err)
837 }
838
839 return accrualPendingTokens
840 }
841
842 // GetAccrualPendingTokens returns token paths that still own accrual buckets.
843 //
844 // Returns:
845 // - tokenPaths: Token paths in the pending-accrual index, in BP-tree iteration order.
846 func (s *protocolFeeStore) GetAccrualPendingTokens() [] string {
847 return collectTreeKeys(s.getAccrualPendingTokenTree())
848 }
849
850 // AddAccrualPendingToken adds tokenPath to the pending-accrual index.
851 //
852 // Parameters:
853 // - _: Crossing discriminator for the store operation; pass 0.
854 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
855 // - tokenPath: Token path with at least one accrual bucket pending.
856 //
857 // Returns:
858 // - err: Nil when tokenPath is already present or has been added; otherwise the current-realm or KV-store write error.
859 func (s *protocolFeeStore) AddAccrualPendingToken(_ int , rlm realm, tokenPath string ) error {
860 if !rlm.IsCurrent() {
861 return errors.New(errSpoofedRealm)
862 }
863
864 accrualPendingTokens := s.getAccrualPendingTokenTree()
865 if accrualPendingTokens.Has(tokenPath) {
866 return nil
867 }
868
869 accrualPendingTokens.Set(tokenPath, true )
870
871 return s.kvStore.Set( 0 , rlm, StoreKeyAccrualPendingTokens.String(), accrualPendingTokens)
872 }
873
874 // RemoveAccrualPendingToken drops one token from the set. It writes only when the
875 // token was listed.
876 //
877 // Parameters:
878 // - _: Crossing discriminator for the store operation; pass 0.
879 // - rlm: Propagated realm context for this store write; it must be current (`rlm.IsCurrent()`).
880 // - tokenPath: Token path to remove from the pending-accrual index.
881 //
882 // Returns:
883 // - err: Nil when tokenPath is absent or has been removed; otherwise the current-realm or KV-store write error.
884 func (s *protocolFeeStore) RemoveAccrualPendingToken(_ int , rlm realm, tokenPath string ) error {
885 if !rlm.IsCurrent() {
886 return errors.New(errSpoofedRealm)
887 }
888
889 accrualPendingTokens := s.getAccrualPendingTokenTree()
890 if _, removed := accrualPendingTokens.Remove(tokenPath); !removed {
891 return nil
892 }
893
894 return s.kvStore.Set( 0 , rlm, StoreKeyAccrualPendingTokens.String(), accrualPendingTokens)
895 }
896
897 func collectTreeKeys(tree *bptree.BPTree) [] string {
898 keys := make([] string , 0 , tree.Size())
899 tree.Iterate( "" , "" , func (key string , _ any ) bool {
900 keys = append(keys, key)
901 return false
902 })
903
904 return keys
905 }
906
907 func encodeEpochKey(epoch int64 ) string {
908 if epoch < 0 {
909 panic(ufmt.Sprintf( "negative epoch not supported: %d" , epoch))
910 }
911
912 return utils.EncodeUint64( uint64 (epoch))
913 }
914
915 func decodeEpochKey(key string ) int64 {
916 return gnsmath.SafeUint64ToInt64(utils.DecodeUint64(key))
917 }
918
919 // NewProtocolFeeStore creates a protocol-fee store backed by the provided KV store.
920 // This function is used by the upgrade system to create storage instances for each implementation.
921 //
922 // Parameters:
923 // - kvStore: Domain KV store used to persist protocol-fee state.
924 //
925 // Returns:
926 // - protocolFeeStore: An IProtocolFeeStore implementation backed by kvStore.
927 func NewProtocolFeeStore(kvStore store.KVStore) IProtocolFeeStore {
928 return &protocolFeeStore{
929 kvStore: kvStore,
930 }
931 }
932
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.