Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

z_contract_authority_shape_filetest.gno

3.56 Kb · 94 lines
 1// PKGPATH: gno.land/r/example
 2//
 3// Executes the contract-identity gate from a real realm.
 4//
 5// Two reasons this cannot be a plain unit test in p/moul/authz:
 6//
 7//  1. Example_* functions that take parameters and have no "// Output:"
 8//     are never run by `gno test` — a sentinel panic inside one still
 9//     reports ok. So the package's headline example, the shape readers
10//     copy, is invisible to CI unless something else runs it.
11//  2. The gate cannot be simulated from inside the package. The VM mints
12//     a crossing frame's realm from the CALLEE's declaring package, so a
13//     closure declared in p/moul/authz always presents that package's
14//     address no matter what testing.SetRealm says. Only a realm can
15//     present its own.
16//
17// (2) is the same mechanism as the capability leak, seen from the other
18// side: it is what makes `rlm.Address()` inside a crossing frame
19// unconditionally the realm's own address — and therefore what makes
20// `NewContractAuthority(ownPath)` + `DoByCurrent` a comparison of the
21// realm to itself that can never reject.
22//
23// WHAT THIS FILE PINS. Both halves go red if the identity gate is
24// reverted to its pre-fix `proposer: NewAutoAcceptAuthority()` default:
25//
26//   - a principal that is NOT the contract is refused;
27//   - the contract itself is accepted, so the gate does not lock out the
28//     legitimate driver.
29//
30// It deliberately does NOT demonstrate `DoByCurrent` on an own-path
31// authority. That pairing is the anti-pattern NewContractAuthority's
32// godoc forbids: it succeeds here and it would equally succeed for a
33// hostile caller, so asserting it green would document the hole as the
34// recommended shape. A filetest is confined to one realm and so cannot
35// exhibit the foreign caller itself; the package-level negatives
36// (TestForeignFrameCannotDriveContractAuthority,
37// TestContractPathIsolation) and r/gnops/valopers' filetests cover that.
38package example
39
40import (
41	"chain"
42
43	"gno.land/p/moul/authz/v0"
44)
45
46var auth = authz.NewWithAuthority(
47	authz.NewContractAuthority(
48		"gno.land/r/example", // this realm's own path
49		func(_ string, action authz.PrivilegedAction) error { return action() },
50	),
51)
52
53var updated string
54
55// UpdateParams is the exported crossing entrypoint of the realm.
56//
57// DoByPrevious, not DoByCurrent: the principal is whoever crossed in, so
58// an unrelated realm calling this presents its own address and is
59// refused. Under DoByCurrent the principal would be this realm's own
60// address for every caller, and this entrypoint would be an
61// unauthenticated privileged write.
62//
63// Note what must NOT be added next to it: a function returning this
64// closure, or any other value carrying this frame. That is the leak.
65func UpdateParams(cur realm, v string) error {
66	return auth.DoByPrevious(0, cur, "update_params", func() error {
67		updated = v
68		return nil
69	})
70}
71
72func main(cur realm) {
73	// A principal that is not the contract is refused, and the action
74	// does not run. This is the assertion the pre-fix AutoAccept default
75	// could not make.
76	outsider := chain.PackageAddress("gno.land/r/outsider")
77	err := auth.Authority().Authorize(outsider, "update_params", func() error {
78		updated = "SHOULD-NOT-LAND"
79		return nil
80	})
81	println("outsider err:", err)
82	println("updated:", updated)
83
84	// The contract itself is accepted: main and UpdateParams are both in
85	// gno.land/r/example, so cur.Previous() is this realm.
86	println("contract err:", UpdateParams(cross(cur), "governed-value"))
87	println("updated:", updated)
88}
89
90// Output:
91// outsider err: unauthorized
92// updated:
93// contract err: undefined
94// updated: governed-value