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

stakeseries.gno

3.69 Kb · 151 lines
  1package kourtv3
  2import (
  3	"strconv"
  4	"strings"
  5	checkpoint "gno.land/p/g1leu8d2vsplhehcfkjg50mwgdpxdkt8tztu95wr/checkpoint/v0"
  6)
  7const (
  8	hourlyKeep = uint32(168)
  9	trimBudget = 2
 10	dailyBlocks = int64(17_280)
 11	seriesRowCap = 400
 12)
 13func csKey(id uint64, suffix string) string {
 14	return "cs:" + strconv.FormatUint(id, 10) + ":" + suffix
 15}
 16func ensureCSArch(c *Court) *checkpoint.Archive {
 17	if c.csArch == nil {
 18		c.csArch = checkpoint.NewArchive()
 19	}
 20	return c.csArch
 21}
 22func setIfChanged(a *checkpoint.Archive, s *checkpoint.Series, key string, e uint32, v int64) {
 23	if v != s.Value() {
 24		s.SetAt(a, key, e, v)
 25	}
 26}
 27func recordPools(c *Court, cs *claimState) {
 28	h := heightNow()
 29	a := ensureCSArch(c)
 30	hE := uint32(h/epochBlocks) + 1
 31	dE := uint32(h/dailyBlocks) + 1
 32	setIfChanged(a, &cs.yesH, csKey(cs.id, "yh"), hE, cs.yesStake)
 33	setIfChanged(a, &cs.noH, csKey(cs.id, "nh"), hE, cs.noStake)
 34	setIfChanged(a, &cs.yesD, csKey(cs.id, "yd"), dE, cs.yesStake)
 35	setIfChanged(a, &cs.noD, csKey(cs.id, "nd"), dE, cs.noStake)
 36	if hE > cs.histTrimmedTo {
 37		cs.histTrimmedTo = hE
 38		trimClaimHistory(c, cs, hE)
 39	}
 40}
 41func trimClaimHistory(c *Court, cs *claimState, hE uint32) {
 42	if c.csArch == nil || hE <= hourlyKeep+1 {
 43		return
 44	}
 45	keep := hE - hourlyKeep
 46	c.csArch.Trim(csKey(cs.id, "yh"), keep, trimBudget)
 47	c.csArch.Trim(csKey(cs.id, "nh"), keep, trimBudget)
 48}
 49type histPoint struct {
 50	e uint32
 51	v int64
 52}
 53func collectSeriesKeyed(a *checkpoint.Archive, s *checkpoint.Series, key string) ([]histPoint, bool) {
 54	pts := []histPoint{}
 55	more := false
 56	if a != nil && key != "" {
 57		a.WalkDesc(key, func(e uint32, v int64) bool {
 58			if len(pts) >= seriesRowCap {
 59				more = true
 60				return true
 61			}
 62			pts = append(pts, histPoint{e, v})
 63			return false
 64		})
 65	}
 66	for i, j := 0, len(pts)-1; i < j; i, j = i+1, j-1 {
 67		pts[i], pts[j] = pts[j], pts[i]
 68	}
 69	if e1, pv := s.Prev(); e1 != 0 {
 70		pts = append(pts, histPoint{e1, pv})
 71	}
 72	if e0 := s.Since(); e0 != 0 {
 73		pts = append(pts, histPoint{e0, s.Value()})
 74	}
 75	return pts, more
 76}
 77func ClaimSeries(courtSlug string, claimID uint64, grain string) string {
 78	c := mustCourt(courtSlug)
 79	cs := mustClaim(c, claimID)
 80	var width int64
 81	var yS, nS *checkpoint.Series
 82	var yKey, nKey string
 83	switch grain {
 84	case "hourly":
 85		width = epochBlocks
 86		yS, nS = &cs.yesH, &cs.noH
 87		yKey, nKey = csKey(claimID, "yh"), csKey(claimID, "nh")
 88	case "daily":
 89		width = dailyBlocks
 90		yS, nS = &cs.yesD, &cs.noD
 91		yKey, nKey = csKey(claimID, "yd"), csKey(claimID, "nd")
 92	default:
 93		panic(`kourtv3: grain is "hourly" or "daily"`)
 94	}
 95	now := uint32(heightNow()/width) + 1
 96	ys, moreY := collectSeriesKeyed(c.csArch, yS, yKey)
 97	ns, moreN := collectSeriesKeyed(c.csArch, nS, nKey)
 98	start := uint32(0)
 99	if moreY && len(ys) > 0 && ys[0].e > start {
100		start = ys[0].e
101	}
102	if moreN && len(ns) > 0 && ns[0].e > start {
103		start = ns[0].e
104	}
105	more := moreY || moreN
106	curY, curN := int64(0), int64(0)
107	i, j := 0, 0
108	for i < len(ys) && ys[i].e < start {
109		curY = ys[i].v
110		i++
111	}
112	for j < len(ns) && ns[j].e < start {
113		curN = ns[j].v
114		j++
115	}
116	rows := []string{}
117	for i < len(ys) || j < len(ns) {
118		var e uint32
119		switch {
120		case i >= len(ys):
121			e = ns[j].e
122		case j >= len(ns):
123			e = ys[i].e
124		case ys[i].e < ns[j].e:
125			e = ys[i].e
126		default:
127			e = ns[j].e
128		}
129		if i < len(ys) && ys[i].e == e {
130			curY = ys[i].v
131			i++
132		}
133		if j < len(ns) && ns[j].e == e {
134			curN = ns[j].v
135			j++
136		}
137		rows = append(rows, strconv.FormatUint(uint64(e), 10)+":"+
138			strconv.FormatInt(curY, 10)+":"+strconv.FormatInt(curN, 10))
139	}
140	if len(rows) > seriesRowCap {
141		rows = rows[len(rows)-seriesRowCap:]
142		more = true
143	}
144	m := "0"
145	if more {
146		m = "1"
147	}
148	return grain + "," + strconv.FormatInt(width, 10) + "," +
149		strconv.FormatUint(uint64(now), 10) + "," + m + ";" +
150		strings.Join(rows, ",")
151}