init.gno
1.86 Kb · 46 lines
1// Package init provides basic user registration.
2//
3// SECURITY: every public function in this package is genesis-only. The
4// realm exists to seed initial users into r/sys/users at chain genesis
5// and to register itself as a controller. After genesis (block height
6// > 0), no caller may use these functions.
7//
8// Without the genesis-only gate, the wide-open `RegisterUser` wrapper
9// would let any EOA land-grab any name (including reserved-sounding
10// names like "administrator" or "vitalik") to any address — for free,
11// without the namereg/v1 payment, blacklist, or canonical-collision
12// checks. The gate closes that bypass.
13//
14// Post-genesis user registration must go through a whitelisted
15// controller that enforces its own policy (e.g. r/sys/namereg/v1).
16package init
17
18import (
19 "chain"
20 "chain/runtime"
21
22 "gno.land/r/sys/users"
23)
24
25// Bootstrap registers this package as a controller in r/sys/users.
26// Genesis-only via AddControllerAtGenesis's own height==0 gate.
27func Bootstrap(_ realm) {
28 users.AddControllerAtGenesis(cross, chain.PackageAddress("gno.land/r/sys/users/init"))
29}
30
31// RegisterUser registers a new user in r/sys/users at chain genesis.
32// PANICS if called after genesis (height > 0).
33//
34// Uses RegisterUserIgnoreCanonical: the genesis seed set is curated, and
35// any deliberate confusable reservations (e.g. registering both `vitalik`
36// and `vital1k` to two different addresses) must not abort chain bring-
37// up. Decision #14 (later-wins) applies, so order in genesis_txs.jsonl
38// determines which name owns the canonical pointer when stems collide.
39func RegisterUser(_ realm, name string, addr address) {
40 if runtime.ChainHeight() != 0 {
41 panic("r/sys/users/init.RegisterUser: genesis-only; use a whitelisted controller post-genesis (e.g. r/sys/namereg/v1.Register)")
42 }
43 if err := users.RegisterUserIgnoreCanonical(cross, name, addr); err != nil {
44 panic(err)
45 }
46}