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.

reserved.gno

3.00 Kb · 110 lines
  1package nslogic
  2
  3import (
  4	"strconv"
  5
  6	"gno.land/r/nym-mnsrehearsal001/nsdata/v2"
  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}