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.

proxy_test.gno

7.33 Kb · 220 lines
  1package config
  2
  3import (
  4	"testing"
  5
  6	"chain"
  7
  8	"gno.land/p/nt/uassert/v0"
  9)
 10
 11// v2Path is a plausible next version. Nothing is deployed there; the tests
 12// only need the address the path resolves to, which is what an incoming
 13// relayed call is actually compared against.
 14const v2Path = "gno.land/r/nym-moultest123/config/v2"
 15
 16func v2Addr() address { return chain.PackageAddress(v2Path) }
 17
 18func TestAllowAndRevokeProxy(cur realm, t *testing.T) {
 19	resetSettings()
 20	uassert.Equal(t, 0, len(ListProxies()))
 21	uassert.False(t, IsProxy(v2Addr()))
 22
 23	testing.SetRealm(testing.NewUserRealm(originAddr))
 24	AllowProxy(cross(cur), v2Path)
 25
 26	uassert.True(t, IsProxy(v2Addr()))
 27	uassert.Equal(t, 1, len(ListProxies()))
 28	uassert.Equal(t, v2Path, ListProxies()[0])
 29
 30	testing.SetRealm(testing.NewUserRealm(originAddr))
 31	RevokeProxy(cross(cur), v2Path)
 32	uassert.False(t, IsProxy(v2Addr()))
 33	uassert.Equal(t, 0, len(ListProxies()))
 34}
 35
 36func TestProxyRegistrationIsManagerOnly(cur realm, t *testing.T) {
 37	resetSettings()
 38
 39	testing.SetRealm(testing.NewUserRealm(nonManagerAddr))
 40	uassert.AbortsContains(t, cur, "unauthorized", func() {
 41		AllowProxy(cross(cur), v2Path)
 42	})
 43	uassert.False(t, IsProxy(v2Addr()), "a rejected registration leaves nothing behind")
 44}
 45
 46// TestProxyPathMustBeASiblingVersion keeps a fat-fingered AllowProxy from
 47// becoming a standing write grant to an unrelated realm.
 48func TestProxyPathMustBeASiblingVersion(cur realm, t *testing.T) {
 49	resetSettings()
 50
 51	bad := []string{
 52		"gno.land/r/someone/evil",
 53		"gno.land/r/nym-moultest123/home",
 54		"gno.land/r/nym-moultest123/configuration/v2", // prefix-adjacent, not a sibling
 55		"gno.land/r/nym-moultest123/config/v",         // no number
 56		"gno.land/r/nym-moultest123/config/vnext",
 57		"gno.land/r/nym-moultest123/config/v2/sub",
 58		"",
 59	}
 60	for _, path := range bad {
 61		testing.SetRealm(testing.NewUserRealm(originAddr))
 62		uassert.AbortsContains(t, cur, "must be a later version", func() {
 63			AllowProxy(cross(cur), path)
 64		})
 65	}
 66	uassert.Equal(t, 0, len(ListProxies()))
 67}
 68
 69func TestRevokeUnknownProxyAborts(cur realm, t *testing.T) {
 70	resetSettings()
 71	testing.SetRealm(testing.NewUserRealm(originAddr))
 72	uassert.AbortsWithMessage(t, cur, "no such proxy: "+v2Path, func() {
 73		RevokeProxy(cross(cur), v2Path)
 74	})
 75}
 76
 77// TestRelayNeedsRegistration is the first of the relay's two checks: without
 78// it, any realm could claim to be acting for any principal.
 79func TestRelayNeedsRegistration(cur realm, t *testing.T) {
 80	resetSettings()
 81
 82	testing.SetRealm(testing.NewCodeRealm(v2Path))
 83	uassert.AbortsContains(t, cur, "not a registered proxy", func() {
 84		SetAs(cross(cur), originAddr, "some.key", "value")
 85	})
 86	uassert.Equal(t, 0, Size())
 87}
 88
 89// TestRelayStillChecksThePrincipal is the second check, and the reason a proxy
 90// is not simply an unconditional bypass: the member list stays the single
 91// answer to "who may change config", for every version at once.
 92func TestRelayStillChecksThePrincipal(cur realm, t *testing.T) {
 93	resetSettings()
 94	testing.SetRealm(testing.NewUserRealm(originAddr))
 95	AllowProxy(cross(cur), v2Path)
 96
 97	testing.SetRealm(testing.NewCodeRealm(v2Path))
 98	uassert.AbortsContains(t, cur, "unauthorized", func() {
 99		SetAs(cross(cur), nonManagerAddr, "some.key", "value")
100	})
101	uassert.Equal(t, 0, Size())
102
103	// An empty principal is not a wildcard.
104	testing.SetRealm(testing.NewCodeRealm(v2Path))
105	uassert.AbortsContains(t, cur, "no principal", func() {
106		SetAs(cross(cur), "", "some.key", "value")
107	})
108}
109
110// TestRelayWritesTheSameState is the property the whole version chain exists
111// for: a write arriving through a later version lands in exactly the store
112// that a direct write lands in, so v1 and v2 readers never disagree.
113func TestRelayWritesTheSameState(cur realm, t *testing.T) {
114	resetSettings()
115	testing.SetRealm(testing.NewUserRealm(originAddr))
116	AllowProxy(cross(cur), v2Path)
117
118	testing.SetRealm(testing.NewCodeRealm(v2Path))
119	SetAs(cross(cur), originAddr, KeyMygnoscanURL, "https://scan.example.com")
120
121	uassert.Equal(t, "https://scan.example.com", Get(KeyMygnoscanURL))
122	uassert.Equal(t, "https://scan.example.com", MygnoscanURL(),
123		"the typed accessor sees the relayed write too")
124
125	testing.SetRealm(testing.NewCodeRealm(v2Path))
126	UnsetAs(cross(cur), originAddr, KeyMygnoscanURL)
127	uassert.False(t, Has(KeyMygnoscanURL))
128}
129
130// TestRelayValidatesLikeTheDirectPath: a relay is a different door, not a
131// different set of rules. Key shape and value grammar are checked identically.
132func TestRelayValidatesLikeTheDirectPath(cur realm, t *testing.T) {
133	resetSettings()
134	testing.SetRealm(testing.NewUserRealm(originAddr))
135	AllowProxy(cross(cur), v2Path)
136
137	testing.SetRealm(testing.NewCodeRealm(v2Path))
138	uassert.AbortsContains(t, cur, "invalid key", func() {
139		SetAs(cross(cur), originAddr, "Bad Key", "value")
140	})
141
142	testing.SetRealm(testing.NewCodeRealm(v2Path))
143	uassert.AbortsContains(t, cur, "invalid pause value", func() {
144		SetAs(cross(cur), originAddr, KeyPause, "yes")
145	})
146}
147
148// TestRevokedProxyCannotWrite: revocation is the emergency brake on the relay
149// itself, so it has to bite immediately.
150func TestRevokedProxyCannotWrite(cur realm, t *testing.T) {
151	resetSettings()
152	testing.SetRealm(testing.NewUserRealm(originAddr))
153	AllowProxy(cross(cur), v2Path)
154
155	testing.SetRealm(testing.NewCodeRealm(v2Path))
156	SetAs(cross(cur), originAddr, "some.key", "before")
157
158	testing.SetRealm(testing.NewUserRealm(originAddr))
159	RevokeProxy(cross(cur), v2Path)
160
161	testing.SetRealm(testing.NewCodeRealm(v2Path))
162	uassert.AbortsContains(t, cur, "not a registered proxy", func() {
163		SetAs(cross(cur), originAddr, "some.key", "after")
164	})
165	uassert.Equal(t, "before", Get("some.key"))
166}
167
168// TestManagerChangesReachTheRelay is what makes one member list serve every
169// version: adding a manager here works through v2 with no further deploys.
170func TestManagerChangesReachTheRelay(cur realm, t *testing.T) {
171	resetSettings()
172	testing.SetRealm(testing.NewUserRealm(originAddr))
173	AllowProxy(cross(cur), v2Path)
174
175	testing.SetRealm(testing.NewCodeRealm(v2Path))
176	uassert.AbortsContains(t, cur, "unauthorized", func() {
177		SetAs(cross(cur), manager1Addr, "some.key", "value")
178	})
179
180	testing.SetRealm(testing.NewUserRealm(originAddr))
181	uassert.NoError(t, AddManager(cross(cur), manager1Addr))
182
183	testing.SetRealm(testing.NewCodeRealm(v2Path))
184	SetAs(cross(cur), manager1Addr, "some.key", "value")
185	uassert.Equal(t, "value", Get("some.key"))
186}
187
188// ExampleRender_proxies pins the section that only exists once a later version
189// is registered, which is the state this realm spends most of its life NOT in.
190func ExampleRender_proxies() {
191	resetSettings()
192	proxies.Set(v2Path, chain.PackageAddress(v2Path))
193	print(Render(""))
194	// Output:
195	// # gno.land/r/nym-moultest123/config
196	//
197	// moul's settings, read by his other realms. rev 0 · 0 setting(s)
198	//
199	// ## Settings
200	//
201	// _none set; every reader is on its built-in default_
202	//
203	// ## Pause
204	//
205	// _running; no global pause_
206	//
207	// ## Authority
208	//
209	// `member_authority[g1daexjemfde047h6lta047h6lta047h6ld2pug6]`
210	//
211	// ## Proxies
212	//
213	// Later versions of this realm that may relay a write:
214	//
215	// - `gno.land/r/nym-moultest123/config/v2`
216	//
217	// ---
218	//
219	// [explorer](https://mygnoscan.moul.p2p.team/realm/r/nym-moultest123/config/v1) · [source](https://mygnoscan.moul.p2p.team/realm/r/nym-moultest123/config/v1?tab=source) · [calls](https://mygnoscan.moul.p2p.team/realm/r/nym-moultest123/config/v1?tab=calls) · [deps](https://mygnoscan.moul.p2p.team/realm/r/nym-moultest123/config/v1?tab=deps)
220}