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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

meta.gno

9.87 Kb · 380 lines
  1package kourt
  2import (
  3	"chain"
  4	"strconv"
  5	"strings"
  6	unsafe "chain/runtime/unsafe"
  7	"math/overflow"
  8	bptree "gno.land/p/nt/bptree/v0"
  9)
 10const metaRealmPath = "gno.land/r/g1ecsuj0q572jr0dhu29q9njtnmw03hyu7tyyvv6/kourt"
 11const (
 12	metaPrefix   = "mod:"
 13	metaCourtNm  = "Meta"
 14	metaExecuted = "MetaExecuted"
 15)
 16const (
 17	verbUnhide    = "unhide"
 18	verbClear     = "clear"
 19	verbHide      = "hide"
 20	verbSuspend   = "suspend"
 21	verbUnsuspend = "unsuspend"
 22	verbSetmods   = "setmods"
 23	verbNewset = "newset"
 24)
 25func verbIsAggressive(v string) bool {
 26	return v == verbHide || v == verbSuspend || v == verbUnsuspend || v == verbSetmods
 27}
 28type modParse struct {
 29	valid     bool
 30	verb      string
 31	court     string
 32	target    uint64
 33	hasTarget bool
 34	poisoned  bool
 35}
 36type metaState struct {
 37	parses   *bptree.BPTree
 38	bindings *bptree.BPTree
 39	latches  *bptree.BPTree
 40	executed *bptree.BPTree
 41}
 42var meta = &metaState{
 43	parses:   bptree.NewBPTree32(),
 44	bindings: bptree.NewBPTree32(),
 45	latches:  bptree.NewBPTree32(),
 46	executed: bptree.NewBPTree32(),
 47}
 48func init() {
 49	startCourt(unsafe.OriginCaller(), chain.PackageAddress(metaRealmPath), metaSlug, metaCourtNm, 0)
 50}
 51func parseModTitle(title string) modParse {
 52	p := modParse{}
 53	if !strings.HasPrefix(title, metaPrefix) {
 54		return p
 55	}
 56	rest := title[len(metaPrefix):]
 57	slash := strings.Index(rest, ":")
 58	if slash < 0 {
 59		return p
 60	}
 61	verb := rest[:slash]
 62	arg := rest[slash+1:]
 63	switch verb {
 64	case verbUnhide, verbClear, verbHide, verbSetmods, verbNewset:
 65		cut := strings.Index(arg, "/")
 66		if cut <= 0 || cut == len(arg)-1 {
 67			return p
 68		}
 69		id, err := strconv.ParseUint(arg[cut+1:], 10, 64)
 70		if err != nil || id == 0 {
 71			return p
 72		}
 73		p.court, p.target, p.hasTarget = arg[:cut], id, true
 74	case verbSuspend, verbUnsuspend:
 75		if arg == "" || strings.Contains(arg, "/") {
 76			return p
 77		}
 78		p.court = arg
 79	default:
 80		return p
 81	}
 82	for i := 0; i < len(p.court); i++ {
 83		ch := p.court[i]
 84		if !((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '-') {
 85			return modParse{}
 86		}
 87	}
 88	p.verb, p.valid = verb, true
 89	return p
 90}
 91func latchKey(p modParse) string {
 92	switch p.verb {
 93	case verbSetmods:
 94		return "set:" + p.court
 95	case verbNewset:
 96		return "fold:" + p.court
 97	case verbSuspend, verbUnsuspend:
 98		return "sus:" + p.court
 99	default:
100		return "item:" + p.court + ":" + strconv.FormatUint(p.target, 10)
101	}
102}
103func onClaimOpened(c *Court, cs *claimState) {
104	if c.id != metaSlug {
105		return
106	}
107	p := parseModTitle(cs.title)
108	meta.parses.Set(beClaimKey(cs.id), &p)
109	cs.noAccuracy = p.valid && p.verb == verbNewset
110	if p.valid {
111		pendingEnter(c, cs)
112	}
113}
114func onTitleEdited(c *Court, cs *claimState) {
115	if c.id != metaSlug {
116		return
117	}
118	p := parseModTitle(cs.title)
119	if prev := meta.parses.Get(beClaimKey(cs.id)); prev != nil && prev.(*modParse).poisoned {
120		p.poisoned = true
121	}
122	meta.parses.Set(beClaimKey(cs.id), &p)
123	cs.noAccuracy = p.valid && p.verb == verbNewset
124	if p.valid || cs.seeded {
125		pendingEnter(c, cs)
126	} else {
127		pendingExit(c, cs)
128	}
129}
130func onClaimAnswered(c *Court, cs *claimState) {
131	if c.id != metaSlug {
132		return
133	}
134	v := meta.parses.Get(beClaimKey(cs.id))
135	if v == nil {
136		return
137	}
138	p := v.(*modParse)
139	if !p.valid || p.poisoned {
140		return
141	}
142	k := latchKey(*p)
143	if held := meta.latches.Get(k); held != nil {
144		if held.(uint64) != cs.id {
145			panic("kourtv2: another appeal already holds this target's review slot")
146		}
147	}
148	meta.latches.Set(k, cs.id)
149	bind := *p
150	meta.bindings.Set(beClaimKey(cs.id), &bind)
151}
152func releaseMetaLatchIfMeta(c *Court, cs *claimState) {
153	if c.id != metaSlug {
154		return
155	}
156	releaseMetaLatch(cs)
157}
158func releaseMetaLatch(cs *claimState) {
159	v := meta.bindings.Get(beClaimKey(cs.id))
160	if v == nil {
161		return
162	}
163	k := latchKey(*v.(*modParse))
164	if held := meta.latches.Get(k); held != nil && held.(uint64) == cs.id {
165		meta.latches.Remove(k)
166	}
167}
168func poisonMetaParse(claimID uint64) {
169	if v := meta.parses.Get(beClaimKey(claimID)); v != nil {
170		v.(*modParse).poisoned = true
171	}
172}
173func metaVerdictExpired(cs *claimState, votingBlocks int64) bool {
174	passed, known := pastDeadline(cs.verdictAtTime, blocksToSecs(votingBlocks)+1)
175	return (known && passed) || (!known && heightNow() > cs.verdictAt+votingBlocks)
176}
177func ExecuteMetaVerdict(cur realm, metaClaimID uint64) {
178	if !cur.IsCurrent() {
179		panic(errStaleRealm)
180	}
181	mc := mustCourt(metaSlug)
182	cs := mustClaim(mc, metaClaimID)
183	bv := meta.bindings.Get(beClaimKey(metaClaimID))
184	if bv == nil {
185		panic("kourtv2: this claim carries no binding appeal")
186	}
187	p := *bv.(*modParse)
188	if !Exists(p.court) {
189		panic("kourtv2: the target court does not exist")
190	}
191	tc := mustCourt(p.court)
192	if tc.createdAt >= cs.openedAt {
193		panic("kourtv2: the target court does not predate this appeal")
194	}
195	var target *claimState
196	if p.hasTarget && p.verb != verbSetmods && p.verb != verbNewset {
197		target = mustClaim(tc, p.target)
198		if target.openedAt >= cs.openedAt {
199			panic("kourtv2: the target claim does not predate this appeal")
200		}
201	}
202	if p.verb == verbSetmods {
203		if cand := ensureMod(tc).mustCandidate(p.target); cand.at >= cs.openedAt {
204			panic("kourtv2: the candidate set does not predate this appeal")
205		}
206	}
207	if p.verb == verbNewset {
208		if prop := ensureMod(tc).mustFolderProposal(p.target); prop.at >= cs.openedAt {
209			panic("kourtv2: the folder proposal does not predate this appeal")
210		}
211	}
212	if cs.verdictAt == 0 || cs.provClose {
213		panic("kourtv2: no final verdict")
214	}
215	if int(cs.provisional) != sideYES {
216		panic("kourtv2: the verdict was not YES")
217	}
218	if verbIsAggressive(p.verb) {
219		if cs.route != "vote" || cs.decidedRounds == 0 {
220			panic("kourtv2: this verb needs a decided contested vote, not silence")
221		}
222		if p.verb != verbHide && !cs.credEligible {
223			panic("kourtv2: a manufactured contest cannot seize authority — this verb needs weight voted against it")
224		}
225	}
226	if meta.executed.Has(beClaimKey(metaClaimID)) {
227		panic("kourtv2: already executed")
228	}
229	if metaVerdictExpired(cs, mc.params.votingBlocks) {
230		panic("kourtv2: this verdict has expired; re-appeal")
231	}
232	cm := ensureMod(tc)
233	switch p.verb {
234	case verbSetmods:
235		if cm.setActHeight > cs.verdictAt {
236			panic("kourtv2: the moderator set changed after this verdict; re-appeal")
237		}
238		if cm.suspended && cm.suspendActByGlobal > cs.openedAt {
239			panic("kourtv2: the global DAO changed this court's suspension under this appeal; re-appeal")
240		}
241	case verbSuspend, verbUnsuspend:
242		if cm.lastElectionAt > cs.openedAt || cm.setActHeight > cs.verdictAt {
243			panic("kourtv2: the moderator set changed under this appeal; re-appeal")
244		}
245		if cm.suspendActByGlobal > cs.openedAt &&
246			cm.suspended == (p.verb == verbUnsuspend) {
247			panic("kourtv2: the global DAO changed this court's suspension under this appeal; re-appeal")
248		}
249	case verbUnhide:
250		if cm.lastElectionAt > cs.openedAt {
251			panic("kourtv2: the moderator set changed under this appeal; re-appeal")
252		}
253	}
254	meta.executed.Set(beClaimKey(metaClaimID), true)
255	applyMetaVerb(mc, tc, cm, p, cs, target)
256	releaseMetaLatch(cs)
257	chain.Emit(metaExecuted,
258		"appeal", strconv.FormatUint(metaClaimID, 10),
259		"verb", p.verb, "court", p.court,
260		"target", strconv.FormatUint(p.target, 10),
261	)
262}
263func applyMetaVerb(mc, tc *Court, cm *courtMod, p modParse, cs, target *claimState) {
264	by := cs.answerer
265	switch p.verb {
266	case verbUnhide:
267		clm := lookupClaimMod(cm, p.target)
268		if clm == nil || !clm.court {
269			return
270		}
271		clearCourtBitByMeta(tc, p.target, by)
272	case verbClear:
273		clearMetaBit(tc, p.target, by)
274	case verbHide:
275		setMetaBit(tc, p.target, by)
276	case verbSuspend:
277		suspendSet(tc, by)
278	case verbUnsuspend:
279		unsuspendSet(tc, by)
280	case verbNewset:
281		prop := cm.mustFolderProposal(p.target)
282		if folderNameTaken(cm, prop.name) {
283			panic("kourtv2: a folder by that name already exists")
284		}
285		if prop.parent != 0 {
286			if pf := cm.mustFolder(prop.parent); pf.retired || pf.purged {
287				panic("kourtv2: the parent heading is no longer in the tree")
288			}
289		}
290		fid := newFolderCore(cm, prop.name, prop.desc, prop.parent)
291		emitModAct(tc.id, 0, "folder-create", by)
292		chain.Emit("FolderCreated",
293			"court", tc.id, "by", "meta",
294			"folder", strconv.FormatUint(fid, 10),
295			"proposal", strconv.FormatUint(p.target, 10),
296			"height", eventHeight(),
297		)
298	case verbSetmods:
299		cand := cm.mustCandidate(p.target)
300		installModSet(tc, cm, cand, heightNow(), false)
301		chain.Emit("ModSetInstalled",
302			"court", tc.id, "by", "meta",
303			"candidate", strconv.FormatUint(cand.id, 10),
304			"height", eventHeight(),
305		)
306	}
307}
308func AppealParse(claimID uint64) (verb, court string, target uint64, valid bool) {
309	v := meta.parses.Get(beClaimKey(claimID))
310	if v == nil {
311		return "", "", 0, false
312	}
313	p := v.(*modParse)
314	return p.verb, p.court, p.target, p.valid
315}
316func AppealExecuted(claimID uint64) bool { return meta.executed.Has(beClaimKey(claimID)) }
317func AppealLatchHolder(verb, court string, target uint64) uint64 {
318	p := modParse{verb: verb, court: court, target: target}
319	if v := meta.latches.Get(latchKey(p)); v != nil {
320		return v.(uint64)
321	}
322	return 0
323}
324var franchise = bptree.NewBPTree32()
325func accrueFranchise(c *Court, who address, spent int64) {
326	if c.id == metaSlug || spent <= 0 {
327		return
328	}
329	k := who.String()
330	prev := int64(0)
331	if v := franchise.Get(k); v != nil {
332		prev = v.(int64)
333	}
334	sum, ok := overflow.Add64(prev, spent)
335	if !ok {
336		return
337	}
338	franchise.Set(k, sum)
339}
340func ClaimMetaFranchise(cur realm) int64 {
341	if !cur.IsCurrent() {
342		panic(errStaleRealm)
343	}
344	who := cur.Previous().Address()
345	k := who.String()
346	v := franchise.Get(k)
347	if v == nil {
348		return 0
349	}
350	owed := v.(int64)
351	if owed <= 0 {
352		return 0
353	}
354	mc := mustCourt(metaSlug)
355	touch(mc)
356	delta, used := mc.crv.Minted(mc.minted, owed)
357	if delta <= 0 {
358		return 0
359	}
360	mc.minted += delta
361	recordPrice(mc)
362	mc.coin.Mint(who, delta)
363	if used >= owed {
364		franchise.Remove(k)
365	} else {
366		franchise.Set(k, owed-used)
367	}
368	chain.Emit("FranchiseClaimed",
369		"who", who.String(),
370		"burned", strconv.FormatInt(used, 10),
371		"minted", strconv.FormatInt(delta, 10),
372	)
373	return delta
374}
375func FranchiseOf(who address) int64 {
376	if v := franchise.Get(who.String()); v != nil {
377		return v.(int64)
378	}
379	return 0
380}