Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

util.gno

2.95 Kb · 116 lines
  1package staker
  2
  3import (
  4	"strconv"
  5
  6	gnsmath "gno.land/p/gnoswap/gnsmath/v1"
  7	bptree "gno.land/p/nt/bptree/v0"
  8	ufmt "gno.land/p/nt/ufmt/v0"
  9	"gno.land/p/onbloc/json/v0"
 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}