diff --git a/examples/gno.land/r/demo/upgradable/admin/entry.gno b/examples/gno.land/r/demo/upgradable/admin/entry.gno new file mode 100644 index 00000000000..aad6cab7834 --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/admin/entry.gno @@ -0,0 +1,15 @@ +package admin + +import ( + "std" +) + +var ReadCounter func() uint64 = nil +var UpdateCounter func() = nil +var DebugPrevRealm func() string = nil + +// ---------------------------------------------------------------------------- + +func DebugAdminPrevRealm() string { + return std.PrevRealm().Addr().String() +} diff --git a/examples/gno.land/r/demo/upgradable/admin/gno.mod b/examples/gno.land/r/demo/upgradable/admin/gno.mod new file mode 100644 index 00000000000..6b90ea4ec7a --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/admin/gno.mod @@ -0,0 +1,5 @@ +module gno.land/r/demo/upgradable/admin + +require ( + +) \ No newline at end of file diff --git a/examples/gno.land/r/demo/upgradable/admin/logic.gno b/examples/gno.land/r/demo/upgradable/admin/logic.gno new file mode 100644 index 00000000000..02deb87f06f --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/admin/logic.gno @@ -0,0 +1,21 @@ +package admin + +import ( + "std" +) + +type Logic interface { + ReadCounter() uint64 + UpdateCounter() + + DebugPrevRealm() string +} + +func RegisterLogic(l Logic, setStore func(Store)) { + ReadCounter = l.ReadCounter + UpdateCounter = l.UpdateCounter + DebugPrevRealm = l.DebugPrevRealm + + newStore := store() + setStore(newStore) +} \ No newline at end of file diff --git a/examples/gno.land/r/demo/upgradable/admin/store.gno b/examples/gno.land/r/demo/upgradable/admin/store.gno new file mode 100644 index 00000000000..049c5c0413d --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/admin/store.gno @@ -0,0 +1,15 @@ +package admin + +type Store interface { + GetCounter() uint64 + SetCounter(value uint64) +} + +var store func() Store = nil + +func RegisterStore(newStore func() Store) { + if store != nil { + panic("Store already registered") + } + store = newStore +} \ No newline at end of file diff --git a/examples/gno.land/r/demo/upgradable/logic/v1/counter.gno b/examples/gno.land/r/demo/upgradable/logic/v1/counter.gno new file mode 100644 index 00000000000..71ee1aba5ec --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/logic/v1/counter.gno @@ -0,0 +1,29 @@ +package v1 + +import ( + "std" + + "gno.land/r/demo/upgradable/admin" +) + +var store admin.Store = nil + +func Init() { + admin.RegisterLogic(&logic{}, func(_store admin.Store) { store = _store }) +} + +var _ admin.Logic = &logic{} + +type logic struct {} + +func (l *logic) ReadCounter() uint64 { + return store.GetCounter() +} + +func (l *logic) UpdateCounter() { + store.SetCounter(store.GetCounter() + 1) +} + +func (l *logic) DebugPrevRealm() string { + return std.PrevRealm().Addr().String() +} diff --git a/examples/gno.land/r/demo/upgradable/logic/v1/gno.mod b/examples/gno.land/r/demo/upgradable/logic/v1/gno.mod new file mode 100644 index 00000000000..20926ece721 --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/logic/v1/gno.mod @@ -0,0 +1,5 @@ +module gno.land/r/demo/upgradable/logic/v1 + +require ( + gno.land/r/demo/upgradable/admin v0.0.0-latest +) \ No newline at end of file diff --git a/examples/gno.land/r/demo/upgradable/logic/v2/counter.gno b/examples/gno.land/r/demo/upgradable/logic/v2/counter.gno new file mode 100644 index 00000000000..258a19d31b5 --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/logic/v2/counter.gno @@ -0,0 +1,29 @@ +package v2 + +import ( + "std" + + "gno.land/r/demo/upgradable/admin" +) + +var store admin.Store = nil + +func Init() { + admin.RegisterLogic(&logic{}, func(_store admin.Store) { store = _store }) +} + +var _ admin.Logic = &logic{} + +type logic struct {} + +func (l *logic) ReadCounter() uint64 { + return store.GetCounter() +} + +func (l *logic) UpdateCounter() { + store.SetCounter(store.GetCounter() + 2) +} + +func (l *logic) DebugPrevRealm() string { + return std.PrevRealm().Addr().String() +} diff --git a/examples/gno.land/r/demo/upgradable/logic/v2/gno.mod b/examples/gno.land/r/demo/upgradable/logic/v2/gno.mod new file mode 100644 index 00000000000..9a64cadebc6 --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/logic/v2/gno.mod @@ -0,0 +1,5 @@ +module gno.land/r/demo/upgradable/logic/v2 + +require ( + gno.land/r/demo/upgradable/admin v0.0.0-latest +) \ No newline at end of file diff --git a/examples/gno.land/r/demo/upgradable/store/gno.mod b/examples/gno.land/r/demo/upgradable/store/gno.mod new file mode 100644 index 00000000000..d9a886f687b --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/store/gno.mod @@ -0,0 +1,5 @@ +module gno.land/r/demo/upgradable/store + +require ( + gno.land/r/demo/upgradable/admin v0.0.0-latest +) \ No newline at end of file diff --git a/examples/gno.land/r/demo/upgradable/store/store.gno b/examples/gno.land/r/demo/upgradable/store/store.gno new file mode 100644 index 00000000000..de94cea8cc9 --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/store/store.gno @@ -0,0 +1,42 @@ +package store + +import ( + "std" + "fmt" + + "gno.land/r/demo/upgradable/admin" +) + +var counterValue uint64 + +var _ admin.Store = &store{} + +var currentStore *store + +type store struct {} + +func (s *store) GetCounter() uint64 { + if s != currentStore { + panic("Revoked store") + } + + return counterValue +} + +func (s *store) SetCounter(value uint64) { + if s != currentStore { + panic("Revoked store") + } + + counterValue = value +} + +func newStore() admin.Store { + currentStore = &store{} + + return currentStore +} + +func Init() { + admin.RegisterStore(newStore) +} \ No newline at end of file diff --git a/examples/gno.land/r/demo/upgradable/upgradable_testing/gno.mod b/examples/gno.land/r/demo/upgradable/upgradable_testing/gno.mod new file mode 100644 index 00000000000..a07133a38fb --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/upgradable_testing/gno.mod @@ -0,0 +1,8 @@ +module gno.land/r/demo/upgradable/upgradable_testing + +require ( + gno.land/r/demo/upgradable/admin v0.0.0-latest + gno.land/r/demo/upgradable/store v0.0.0-latest + gno.land/r/demo/upgradable/logic/v1 v0.0.0-latest + gno.land/r/demo/upgradable/logic/v2 v0.0.0-latest +) diff --git a/examples/gno.land/r/demo/upgradable/upgradable_testing/upgradable.gno b/examples/gno.land/r/demo/upgradable/upgradable_testing/upgradable.gno new file mode 100644 index 00000000000..a230de52619 --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/upgradable_testing/upgradable.gno @@ -0,0 +1 @@ +package upgradable_testing \ No newline at end of file diff --git a/examples/gno.land/r/demo/upgradable/upgradable_testing/upgradable_test.gno b/examples/gno.land/r/demo/upgradable/upgradable_testing/upgradable_test.gno new file mode 100644 index 00000000000..b7a938dbb63 --- /dev/null +++ b/examples/gno.land/r/demo/upgradable/upgradable_testing/upgradable_test.gno @@ -0,0 +1,35 @@ +package upgradable_testing + +import ( + "std" + "testing" + + "gno.land/p/demo/testutils" + "gno.land/p/demo/urequire" + + "gno.land/r/demo/upgradable/admin" + "gno.land/r/demo/upgradable/logic/v1" + "gno.land/r/demo/upgradable/logic/v2" + "gno.land/r/demo/upgradable/store" + +) + +func TestPackage(t *testing.T) { + alice := testutils.TestAddress("alice") + std.TestSetRealm(std.NewUserRealm(alice)) + std.TestSetOrigCaller(alice) // XXX: should not need this + + store.Init() + + v1.Init() + urequire.Equal(t, admin.ReadCounter(), uint64(0)) + admin.UpdateCounter() + urequire.Equal(t, admin.ReadCounter(), uint64(1)) + + v2.Init() + urequire.Equal(t, admin.ReadCounter(), uint64(1)) + admin.UpdateCounter() + urequire.Equal(t, admin.ReadCounter(), uint64(3)) + + urequire.Equal(t, admin.DebugPrevRealm(), admin.DebugAdminPrevRealm()) +} \ No newline at end of file