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

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}