package staker import ( "strconv" gnsmath "gno.land/p/gnoswap/gnsmath" bptree "gno.land/p/nt/bptree/v0" ufmt "gno.land/p/nt/ufmt/v0" "gno.land/p/onbloc/json" ) // marshal data to json string func marshal(data *json.Node) string { b, err := json.Marshal(data) if err != nil { panic(err.Error()) } return string(b) } // getUint64FromTree returns the uint64 value from the tree func getUint64FromTree(tree *bptree.BPTree, key string) uint64 { value := tree.Get(key) if value == nil { return 0 } v, ok := value.(uint64) if !ok { panic(ufmt.Sprintf("failed to cast value to uint64: %T", value)) } return v } // updateUint64InTree updates the uint64 value in the tree func updateUint64InTree(tree *bptree.BPTree, key string, delta uint64, add bool) uint64 { current := getUint64FromTree(tree, key) var newValue uint64 if add { newValue = gnsmath.SafeAddUint64(current, delta) } else { if current < delta { panic(makeErrorWithDetails( errNotEnoughBalance, ufmt.Sprintf("not enough balance: current(%d) < requested(%d)", current, delta), )) } newValue = gnsmath.SafeSubUint64(current, delta) } tree.Set(key, newValue) return newValue } // milliToSec converts milliseconds to seconds func milliToSec(ms int64) int64 { var msPerSec int64 = 1000 return ms / msPerSec } // userHistoryKeySeparator is chosen to be lexicographically smaller than any const ( userHistoryKeySeparator = "|" userHistoryKeySeparatorNextWord = string(int32('|') + 1) ) // userHistoryTimestampWidth is the zero-padded width that fits the maximum const userHistoryTimestampWidth = 20 // makeUserHistoryKey builds the composite key "addr|paddedTimestamp" used in the user delegation history BPTree. func makeUserHistoryKey(addrStr string, timestamp int64) string { return addrStr + userHistoryKeySeparator + padTimestamp(timestamp) } // userHistoryKeyRange returns the half-open prefix range that covers all composite keys belonging to addrStr. func userHistoryKeyRange(addrStr string) (lo, hi string) { lo = addrStr + userHistoryKeySeparator hi = addrStr + userHistoryKeySeparatorNextWord return lo, hi } // padTimestamp left-pads timestamp with zeros to userHistoryTimestampWidth so // that lexicographic ordering of the resulting strings matches numeric order. func padTimestamp(timestamp int64) string { s := strconv.FormatInt(timestamp, 10) if len(s) >= userHistoryTimestampWidth { return s } pad := make([]byte, userHistoryTimestampWidth-len(s)) for i := range pad { pad[i] = '0' } return string(pad) + s } // parseUserHistoryKey splits a composite key produced by makeUserHistoryKey back into its address and timestamp components. func parseUserHistoryKey(key string) (addrStr string, timestamp int64, ok bool) { for i := len(key) - 1; i >= 0; i-- { if key[i] == userHistoryKeySeparator[0] { ts, err := strconv.ParseInt(key[i+1:], 10, 64) if err != nil { return "", 0, false } return key[:i], ts, true } } return "", 0, false }