reserved.gno
3.00 Kb · 110 lines
1package nslogic
2
3import (
4 "strconv"
5
6 "gno.land/r/nym-mnsrehearsal001/nsdata/v1"
7)
8
9// GENERATED BY tools/gen-reserved.py FROM collections/reserved-labels.json.
10// Do not edit by hand: the site reads the same source, and a change made
11// in one place only is a label the site offers and the chain refuses.
12//
13// STRUCTURAL RULES ONLY. The wordlists live off chain, in that JSON,
14// because storage is 100 ugnot per byte and a ten-thousand-word
15// dictionary is about 57 GNOT paid forever to encode a marketing
16// decision that will change. This is the backstop against a bug in the
17// issuer, not the place the policy lives.
18//
19// THE NUMBERS ARE SETTABLE, the shape is not. A minimum length is a
20// promotion knob and belongs in the panel — redeploying this realm to
21// change a 5 to a 4 costs about 22 GNOT. So the lengths read from the
22// vault's globals and fall back to the values generated here; the
23// pattern rules are structural facts about what a handle looks like and
24// stay in code.
25
26const (
27 defaultFreeMinLength = 5
28 defaultFreeMaxLength = 63
29
30 keyFreeMin = "freemin"
31 keyFreeMax = "freemax"
32)
33
34// FreeMinLength is the shortest label the free tier will issue. Settable
35// from the panel, because which lengths are worth money is a commercial
36// judgement that moves.
37func FreeMinLength() int {
38 if v := nsdata.GetGlobal(keyFreeMin); v != "" {
39 if n, err := strconv.Atoi(v); err == nil && n > 0 && n <= 63 {
40 return n
41 }
42 }
43 return defaultFreeMinLength
44}
45
46func FreeMaxLength() int {
47 if v := nsdata.GetGlobal(keyFreeMax); v != "" {
48 if n, err := strconv.Atoi(v); err == nil && n > 0 && n <= 63 {
49 return n
50 }
51 }
52 return defaultFreeMaxLength
53}
54
55/*
56FreeLabelAllowed reports whether a label may be ISSUED on the free tier.
57
58ISSUED, and never renewed. This is called by GrantFreeName and by
59nothing else, deliberately: if the minimum length rises from three to
60five, somebody who already holds a three-character free name keeps it
61and keeps renewing it free. Tightening a rule must not reach backwards
62and take away what was already given — that is the single fastest way to
63make a giveaway cost more trust than it ever bought.
64
65A name that LAPSES and is registered again is a new issuance, and gets
66whatever the rules say that day. That is not retroactive; it is a
67different name event.
68*/
69func FreeLabelAllowed(label string) bool {
70 n := len(label)
71 if n < FreeMinLength() || n > FreeMaxLength() {
72 return false
73 }
74 // Pure digits: 1337, 420, years. Collectible, and no handle is one.
75 digits := true
76 for i := 0; i < n; i++ {
77 if label[i] < '0' || label[i] > '9' {
78 digits = false
79 break
80 }
81 }
82 if digits {
83 return false
84 }
85 // aaaa — every character the same.
86 same := true
87 for i := 1; i < n; i++ {
88 if label[i] != label[0] {
89 same = false
90 break
91 }
92 }
93 if same {
94 return false
95 }
96 // abab — a two-character cycle. Also collectible, also not a handle.
97 if n >= 4 {
98 cycle := true
99 for i := 2; i < n; i++ {
100 if label[i] != label[i-2] {
101 cycle = false
102 break
103 }
104 }
105 if cycle {
106 return false
107 }
108 }
109 return true
110}