Search Apps Documentation Source Content File Folder Download Copy Actions Download 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"
  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}