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

votelock.gno

2.95 Kb · 124 lines
  1package kourt
  2import "gno.land/p/nt/bptree/v0"
  3const (
  4	voteLockDispute  = "d"
  5	voteLockElection = "e"
  6)
  7func voteLockKey(who address, kind string, id, sub uint64) string {
  8	return string(who) + kind + beClaimKey(id) + beClaimKey(sub)
  9}
 10func voteLockParts(who address, key string) (kind string, id, sub uint64, ok bool) {
 11	tail := key[len(string(who)):]
 12	if len(tail) != 1+8+8 {
 13		return "", 0, 0, false
 14	}
 15	return tail[0:1], beClaimID(tail[1:9]), beClaimID(tail[9:17]), true
 16}
 17func voteLockOpen(c *Court, who address, key string) bool {
 18	kind, id, sub, ok := voteLockParts(who, key)
 19	if !ok {
 20		return false
 21	}
 22	switch kind {
 23	case voteLockDispute:
 24		v := c.claims.Get(beClaimKey(id))
 25		if v == nil {
 26			return false
 27		}
 28		cs := v.(*claimState)
 29		return cs.disputeOpen && cs.proposalID == int64(sub)
 30	case voteLockElection:
 31		if c.mod == nil || c.mod.election == nil {
 32			return false
 33		}
 34		e := c.mod.election
 35		return e.seq == id && !e.resolved
 36	}
 37	return false
 38}
 39func voteLockedOf(c *Court, who address) int64 {
 40	if c.voteLocks == nil {
 41		return 0
 42	}
 43	var most int64
 44	pre := string(who)
 45	c.voteLocks.Iterate(pre, pre+"\xff", func(k string, v any) bool {
 46		if w := v.(int64); w > most && voteLockOpen(c, who, k) {
 47			most = w
 48		}
 49		return false
 50	})
 51	return most
 52}
 53func lockVote(c *Court, who address, kind string, id, sub, amount int64) {
 54	if amount <= 0 {
 55		return
 56	}
 57	if c.voteLocks == nil {
 58		c.voteLocks = bptree.NewBPTree32()
 59	}
 60	pruneVoteLocks(c, who)
 61	c.voteLocks.Set(voteLockKey(who, kind, uint64(id), uint64(sub)), amount)
 62}
 63func pruneVoteLocks(c *Court, who address) int {
 64	if c.voteLocks == nil {
 65		return 0
 66	}
 67	var stale []string
 68	pre := string(who)
 69	c.voteLocks.Iterate(pre, pre+"\xff", func(k string, _ any) bool {
 70		if _, _, _, ok := voteLockParts(who, k); !ok {
 71			return false
 72		}
 73		if !voteLockOpen(c, who, k) {
 74			stale = append(stale, k)
 75		}
 76		return false
 77	})
 78	for _, k := range stale {
 79		c.voteLocks.Remove(k)
 80	}
 81	return len(stale)
 82}
 83func beClaimID(s string) uint64 {
 84	var v uint64
 85	for i := 0; i < 8; i++ {
 86		v = v<<8 | uint64(s[i])
 87	}
 88	return v
 89}
 90func PruneVoteLocks(cur realm, courtSlug string, who address) int {
 91	if !cur.IsCurrent() {
 92		panic(errStaleRealm)
 93	}
 94	if !who.IsValid() {
 95		panic("kourtv2: that is not a valid address")
 96	}
 97	return pruneVoteLocks(mustCourt(courtSlug), who)
 98}
 99func CommitmentsOf(courtSlug string, who address) string {
100	c := mustCourt(courtSlug)
101	out := "stake:" + itoa(lockedOf(c, who)) +
102		";vote:" + itoa(voteLockedOf(c, who)) +
103		";free:" + itoa(disposable(c, who))
104	if c.voteLocks == nil {
105		return out
106	}
107	pre := string(who)
108	c.voteLocks.Iterate(pre, pre+"\xff", func(k string, v any) bool {
109		if !voteLockOpen(c, who, k) {
110			return false
111		}
112		kind, id, sub, ok := voteLockParts(who, k)
113		if !ok {
114			return false
115		}
116		out += ";q:" + kind + ":" + itoa(int64(id)) + ":" + itoa(int64(sub)) +
117			":" + itoa(v.(int64))
118		return false
119	})
120	return out
121}
122func VoteLockedOf(courtSlug string, who address) int64 {
123	return voteLockedOf(mustCourt(courtSlug), who)
124}