util.gno
2.95 Kb · 116 lines
1package staker
2
3import (
4 "strconv"
5
6 gnsmath "gno.land/p/gnoswap/gnsmath"
7 bptree "gno.land/p/nt/bptree/v0"
8 ufmt "gno.land/p/nt/ufmt/v0"
9 "gno.land/p/onbloc/json"
10)
11
12// marshal data to json string
13func marshal(data *json.Node) string {
14 b, err := json.Marshal(data)
15 if err != nil {
16 panic(err.Error())
17 }
18
19 return string(b)
20}
21
22// getUint64FromTree returns the uint64 value from the tree
23func getUint64FromTree(tree *bptree.BPTree, key string) uint64 {
24 value := tree.Get(key)
25 if value == nil {
26 return 0
27 }
28
29 v, ok := value.(uint64)
30 if !ok {
31 panic(ufmt.Sprintf("failed to cast value to uint64: %T", value))
32 }
33
34 return v
35}
36
37// updateUint64InTree updates the uint64 value in the tree
38func updateUint64InTree(tree *bptree.BPTree, key string, delta uint64, add bool) uint64 {
39 current := getUint64FromTree(tree, key)
40 var newValue uint64
41 if add {
42 newValue = gnsmath.SafeAddUint64(current, delta)
43 } else {
44 if current < delta {
45 panic(makeErrorWithDetails(
46 errNotEnoughBalance,
47 ufmt.Sprintf("not enough balance: current(%d) < requested(%d)", current, delta),
48 ))
49 }
50 newValue = gnsmath.SafeSubUint64(current, delta)
51 }
52
53 tree.Set(key, newValue)
54
55 return newValue
56}
57
58// milliToSec converts milliseconds to seconds
59func milliToSec(ms int64) int64 {
60 var msPerSec int64 = 1000
61 return ms / msPerSec
62}
63
64// userHistoryKeySeparator is chosen to be lexicographically smaller than any
65const (
66 userHistoryKeySeparator = "|"
67 userHistoryKeySeparatorNextWord = string(int32('|') + 1)
68)
69
70// userHistoryTimestampWidth is the zero-padded width that fits the maximum
71const userHistoryTimestampWidth = 20
72
73// makeUserHistoryKey builds the composite key "addr|paddedTimestamp" used in the user delegation history BPTree.
74func makeUserHistoryKey(addrStr string, timestamp int64) string {
75 return addrStr + userHistoryKeySeparator + padTimestamp(timestamp)
76}
77
78// userHistoryKeyRange returns the half-open prefix range that covers all composite keys belonging to addrStr.
79func userHistoryKeyRange(addrStr string) (lo, hi string) {
80 lo = addrStr + userHistoryKeySeparator
81 hi = addrStr + userHistoryKeySeparatorNextWord
82
83 return lo, hi
84}
85
86// padTimestamp left-pads timestamp with zeros to userHistoryTimestampWidth so
87// that lexicographic ordering of the resulting strings matches numeric order.
88func padTimestamp(timestamp int64) string {
89 s := strconv.FormatInt(timestamp, 10)
90 if len(s) >= userHistoryTimestampWidth {
91 return s
92 }
93
94 pad := make([]byte, userHistoryTimestampWidth-len(s))
95 for i := range pad {
96 pad[i] = '0'
97 }
98
99 return string(pad) + s
100}
101
102// parseUserHistoryKey splits a composite key produced by makeUserHistoryKey back into its address and timestamp components.
103func parseUserHistoryKey(key string) (addrStr string, timestamp int64, ok bool) {
104 for i := len(key) - 1; i >= 0; i-- {
105 if key[i] == userHistoryKeySeparator[0] {
106 ts, err := strconv.ParseInt(key[i+1:], 10, 64)
107 if err != nil {
108 return "", 0, false
109 }
110
111 return key[:i], ts, true
112 }
113 }
114
115 return "", 0, false
116}