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

upgrade.gno

3.02 Kb · 79 lines
 1package governance
 2
 3import (
 4	"gno.land/r/gnoswap/access/v1"
 5)
 6
 7// RegisterInitializer registers a version-specific initializer. Each version
 8// (e.g. v1, v2) calls this function from its init body to plug itself into
 9// the proxy.
10//
11// The initializer constructs the version's IGovernance from the supplied
12// IGovernanceStore and GovStakerAccessor. It receives a realm value that
13// resolves to the governance proxy realm — the only address with write
14// permission on the shared KV store — so any per-version store bootstrap
15// performed inside the initializer passes the proxy's authorization check.
16//
17// Security: Only contracts within the domain path can register initializers.
18// Each package path can only register once to prevent duplicate registrations.
19// Parameters:
20//   - cur: Current realm context; callers use cross(cur) when crossing into this realm.
21//   - initializer: Callback that receives the proxy-authorized realm context, governance store, and staker accessor and returns the versioned implementation.
22func RegisterInitializer(cur realm, initializer func(_ int, rlm realm, governanceStore IGovernanceStore, stakerAccessor GovStakerAccessor) IGovernance) {
23	// `cur` captured here is the governance crossing frame. The wrapping
24	// closure forwards it to the version initializer so any store writes
25	// the initializer performs run under the proxy's identity rather than
26	// the version package's, which would fail the kvStore ACL.
27	initializerFunc := func(_ int, rlm realm, domainStore any) any {
28		access.AssertIsRlmCurrent(0, rlm)
29
30		currentGovernanceStore, ok := domainStore.(IGovernanceStore)
31		if !ok {
32			panic("domainStore is not an IGovernanceStore")
33		}
34		return initializer(0, rlm, currentGovernanceStore, newGovStakerAccessor())
35	}
36
37	err := versionManager.RegisterInitializer(0, cur, initializerFunc)
38	if err != nil {
39		panic(err)
40	}
41
42	err = updateImplementation()
43	if err != nil {
44		panic(err)
45	}
46}
47
48// UpgradeImpl switches the active governance implementation to a different version.
49// This function allows seamless upgrades from one version to another without
50// data migration or downtime.
51//
52// Security: Only admin or governance can perform upgrades.
53// The new implementation must have been previously registered via RegisterInitializer.
54// Parameters:
55//   - cur: Current realm context; callers use cross(cur) when crossing into this realm.
56//   - targetPackagePath: Registered implementation package path to activate.
57func UpgradeImpl(cur realm, targetPackagePath string) {
58	// Ensure only admin or governance can perform upgrades
59	prev := cur.Previous()
60	access.AssertIsAdminOrGovernance(prev.Address())
61
62	err := versionManager.ChangeImplementation(0, cur, targetPackagePath)
63	if err != nil {
64		panic(err)
65	}
66
67	err = updateImplementation()
68	if err != nil {
69		panic(err)
70	}
71}
72
73// GetImplementationPackagePath returns the package path of the currently active implementation.
74//
75// Returns:
76//   - packagePath: package path of the active implementation
77func GetImplementationPackagePath() string {
78	return versionManager.GetCurrentPackagePath()
79}