From 8a5ecbca09ba45cfa0bcaab4c0cdfe108792a278 Mon Sep 17 00:00:00 2001 From: Norman Meier Date: Fri, 25 Aug 2023 19:55:21 +0200 Subject: [PATCH 01/44] feat: grc20 registry Signed-off-by: Norman Meier --- examples/gno.land/r/demo/foo20/foo20.gno | 2 + examples/gno.land/r/demo/foo20/gno.mod | 1 + .../gno.land/r/demo/grc20_registry/gno.mod | 6 ++ .../r/demo/grc20_registry/grc20_registry.gno | 44 +++++++++++++++ .../grc20_registry/grc20_registry_test.gno | 55 +++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 examples/gno.land/r/demo/grc20_registry/gno.mod create mode 100644 examples/gno.land/r/demo/grc20_registry/grc20_registry.gno create mode 100644 examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno diff --git a/examples/gno.land/r/demo/foo20/foo20.gno b/examples/gno.land/r/demo/foo20/foo20.gno index 39ab9260d3a..fc28446717a 100644 --- a/examples/gno.land/r/demo/foo20/foo20.gno +++ b/examples/gno.land/r/demo/foo20/foo20.gno @@ -6,6 +6,7 @@ import ( "gno.land/p/demo/grc/grc20" "gno.land/p/demo/ufmt" + "gno.land/r/demo/grc20_registry" "gno.land/r/demo/users" ) @@ -16,6 +17,7 @@ var ( func init() { foo = grc20.NewAdminToken("Foo", "FOO", 4) + grc20_registry.Register(foo.GRC20()) foo.Mint(admin, 1000000*10000) // @administrator (1M) foo.Mint("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", 10000*10000) // @manfred (10k) } diff --git a/examples/gno.land/r/demo/foo20/gno.mod b/examples/gno.land/r/demo/foo20/gno.mod index 1dbe9e01e4f..7d199825d33 100644 --- a/examples/gno.land/r/demo/foo20/gno.mod +++ b/examples/gno.land/r/demo/foo20/gno.mod @@ -4,4 +4,5 @@ require ( "gno.land/p/demo/ufmt" v0.0.0-latest "gno.land/p/demo/grc/grc20" v0.0.0-latest "gno.land/r/demo/users" v0.0.0-latest + "gno.land/r/demo/grc20_registry" v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/grc20_registry/gno.mod b/examples/gno.land/r/demo/grc20_registry/gno.mod new file mode 100644 index 00000000000..8715926faf8 --- /dev/null +++ b/examples/gno.land/r/demo/grc20_registry/gno.mod @@ -0,0 +1,6 @@ +module gno.land/r/demo/grc20_registry + +require ( + "gno.land/p/demo/avl" v0.0.0-latest + "gno.land/p/demo/grc/grc20" v0.0.0-latest +) diff --git a/examples/gno.land/r/demo/grc20_registry/grc20_registry.gno b/examples/gno.land/r/demo/grc20_registry/grc20_registry.gno new file mode 100644 index 00000000000..8f0f6d10df2 --- /dev/null +++ b/examples/gno.land/r/demo/grc20_registry/grc20_registry.gno @@ -0,0 +1,44 @@ +package grc20_registry + +import ( + "std" + "strings" + + "gno.land/p/demo/avl" + "gno.land/p/demo/grc/grc20" +) + +var registry = avl.NewTree() // pkg path -> IGRC20 + +func Register(token grc20.IGRC20) { + caller := std.PrevRealm().PkgPath() + registry.Set(caller, token) +} + +func Get(pkgPath string) (grc20.IGRC20, bool) { + coinI, ok := registry.Get(pkgPath) + if !ok { + return nil, false + } + coin, ok := coinI.(grc20.IGRC20) + if !ok { + panic("internal error: registered object is not a GRC20 token") + } + return coin, true +} + +func Render(path string) string { + s := "# GRC20 Registry\n\n" + + "## Registered Tokens\n\n" + registry.Iterate("", "", func(pkgPath string, tokenI interface{}) bool { + token, ok := tokenI.(grc20.IGRC20) + pkgWebPath := strings.TrimPrefix(pkgPath, "gno.land") + if ok { + s += "- [" + token.GetName() + " (" + pkgPath + ")](" + pkgWebPath + ")\n" + } else { + s += "- [internal error: registered object is not a GRC20 token (" + pkgPath + ")](" + pkgWebPath + ")\n" + } + return false + }) + return s +} diff --git a/examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno b/examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno new file mode 100644 index 00000000000..3b1475c17d1 --- /dev/null +++ b/examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno @@ -0,0 +1,55 @@ +package grc20_registry + +import ( + "std" + "testing" + + "gno.land/p/demo/grc/grc20" +) + +func TestRegistry(t *testing.T) { + coin := &dummyImpl{} + realmAddr := std.CurrentRealm().PkgPath() + Register(coin) + regCoin, ok := Get(realmAddr) + if !ok { + t.Fatal("expected to find coin") + } + if coin.GetSymbol() != "TST" { + t.Fatal("expected coin to have symbol TST") + } + expected := `# GRC20 Registry + +## Registered Tokens + +* [TestToken ()]() +` + got := Render("") + if got != expected { + t.Fatalf("expected `%s`, got `%s`", expected, got) + } + + // we test this here because there is more chance to find a bug after a token has been registered + if _, ok := Get("0xdeadbeef"); ok { + t.Fatal("expected not to find coin") + } +} + +type dummyImpl struct{} + +// FIXME: this should fail. +var _ grc20.IGRC20 = (*dummyImpl)(nil) + +func (impl *dummyImpl) GetName() string { return "TestToken" } +func (impl *dummyImpl) GetSymbol() string { return "TST" } +func (impl *dummyImpl) GetDecimals() uint { panic("not implemented") } +func (impl *dummyImpl) TotalSupply() uint64 { panic("not implemented") } +func (impl *dummyImpl) BalanceOf(account std.Address) (uint64, error) { panic("not implemented") } +func (impl *dummyImpl) Transfer(to std.Address, amount uint64) error { panic("not implemented") } +func (impl *dummyImpl) Allowance(owner, spender std.Address) (uint64, error) { + panic("not implemented") +} +func (impl *dummyImpl) Approve(spender std.Address, amount uint64) error { panic("not implemented") } +func (impl *dummyImpl) TransferFrom(from, to std.Address, amount uint64) error { + panic("not implemented") +} From 9c5fcde65e0717b5f3bd6f0946ff790cb8b73514 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 18 Oct 2023 19:35:45 -0700 Subject: [PATCH 02/44] initial commit of receiver implied realm for pkg methods --- gnovm/pkg/gnolang/machine.go | 13 +++++++++++++ gnovm/pkg/gnolang/realm.go | 15 ++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 94232e014d2..f6b0d2ed4c1 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -1629,6 +1629,19 @@ func (m *Machine) PushFrameCall(cx *CallExpr, fv *FuncValue, recv TypedValue) { rlm := pv.GetRealm() if rlm != nil && m.Realm != rlm { m.Realm = rlm // enter new realm + } else if rlm == nil && recv.V != nil { // XXX maybe improve this part. + // maybe this is a bound method of a recv of a realm. + // in that case, inherit the realm of the receiver. + obj, ok := recv.V.(Object) + if ok { + recvOID := obj.GetObjectInfo().ID + if !recvOID.IsZero() { + recvPVOID := ObjectIDFromPkgID(recvOID.PkgID) + pv := m.Store.GetObject(recvPVOID).(*PackageValue) + rlm := pv.GetRealm() + m.Realm = rlm + } + } } } diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 567aea58284..66f3ff56edf 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -70,12 +70,21 @@ func (pid PkgID) Bytes() []byte { } func PkgIDFromPkgPath(path string) PkgID { + fmt.Printf("PkgPath %s -> PkgID %v", path, + PkgID{HashBytes([]byte(path))}) return PkgID{HashBytes([]byte(path))} } +// Returns the ObjectID of the PackageValue associated with path. func ObjectIDFromPkgPath(path string) ObjectID { + pkgID := PkgIDFromPkgPath(path) + return ObjectIDFromPkgID(pkgID) +} + +// Returns the ObjectID of the PackageValue associated with pkgID. +func ObjectIDFromPkgID(pkgID PkgID) ObjectID { return ObjectID{ - PkgID: PkgIDFromPkgPath(path), + PkgID: pkgID, NewTime: 1, // by realm logic. } } @@ -145,6 +154,10 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { return // do nothing. } if po.GetObjectID().PkgID != rlm.ID { + fmt.Println("PO", po.String()) + fmt.Println("PO.PKGID", po.GetObjectID().PkgID) + fmt.Println("rlm", rlm) + fmt.Println("rlm.ID", rlm.ID) panic("cannot modify external-realm or non-realm object") } // From here on, po is real (not new-real). From a9bee164dcd3ceec2e3c856a21c110a278712cd5 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 18 Oct 2023 20:16:54 -0700 Subject: [PATCH 03/44] deref receiver before checking if object --- gnovm/pkg/gnolang/machine.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index f6b0d2ed4c1..95f1a90fa2a 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -1632,7 +1632,18 @@ func (m *Machine) PushFrameCall(cx *CallExpr, fv *FuncValue, recv TypedValue) { } else if rlm == nil && recv.V != nil { // XXX maybe improve this part. // maybe this is a bound method of a recv of a realm. // in that case, inherit the realm of the receiver. - obj, ok := recv.V.(Object) + recvv := recv.V + // deref if pointer. + // XXX I guess we want to deref as much as possible. + for { + if pv, ok := recvv.(PointerValue); ok { + recvv = pv.Deref().V + } else { + break + } + } + // Now check if it is an object. + obj, ok := recvv.(Object) if ok { recvOID := obj.GetObjectInfo().ID if !recvOID.IsZero() { From bc47c25f45ebf691d3db4ec6015dba4bd9155d9c Mon Sep 17 00:00:00 2001 From: jaekwon Date: Wed, 18 Oct 2023 20:23:56 -0700 Subject: [PATCH 04/44] ... --- gnovm/pkg/gnolang/realm.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 66f3ff56edf..f4a4b17dcb5 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -70,8 +70,8 @@ func (pid PkgID) Bytes() []byte { } func PkgIDFromPkgPath(path string) PkgID { - fmt.Printf("PkgPath %s -> PkgID %v", path, - PkgID{HashBytes([]byte(path))}) + // fmt.Printf("PkgPath %s -> PkgID %v", path, + // PkgID{HashBytes([]byte(path))}) return PkgID{HashBytes([]byte(path))} } @@ -154,10 +154,10 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { return // do nothing. } if po.GetObjectID().PkgID != rlm.ID { - fmt.Println("PO", po.String()) - fmt.Println("PO.PKGID", po.GetObjectID().PkgID) - fmt.Println("rlm", rlm) - fmt.Println("rlm.ID", rlm.ID) + // fmt.Println("PO", po.String()) + // fmt.Println("PO.PKGID", po.GetObjectID().PkgID) + // fmt.Println("rlm", rlm) + // fmt.Println("rlm.ID", rlm.ID) panic("cannot modify external-realm or non-realm object") } // From here on, po is real (not new-real). From ec4d71734048712f1bf3ab7ceb6e8750c82e5314 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 19 Oct 2023 06:17:43 -0700 Subject: [PATCH 05/44] ... --- gnovm/pkg/gnolang/machine.go | 36 +++++++++++++--------------------- gnovm/pkg/gnolang/ownership.go | 1 + 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 95f1a90fa2a..8665e049e9f 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -1627,33 +1627,25 @@ func (m *Machine) PushFrameCall(cx *CallExpr, fv *FuncValue, recv TypedValue) { } m.Package = pv rlm := pv.GetRealm() - if rlm != nil && m.Realm != rlm { - m.Realm = rlm // enter new realm - } else if rlm == nil && recv.V != nil { // XXX maybe improve this part. - // maybe this is a bound method of a recv of a realm. - // in that case, inherit the realm of the receiver. - recvv := recv.V - // deref if pointer. - // XXX I guess we want to deref as much as possible. - for { - if pv, ok := recvv.(PointerValue); ok { - recvv = pv.Deref().V - } else { - break - } - } - // Now check if it is an object. - obj, ok := recvv.(Object) - if ok { + if rlm == nil && recv.IsDefined() { + // if bound method, get realm from receiver. + obj := recv.GetFirstObject(m.Store) + if obj == nil { + // panic("XXX not sure why this would be") + fmt.Println("XXX XXX", recv.String()) + } else { recvOID := obj.GetObjectInfo().ID if !recvOID.IsZero() { - recvPVOID := ObjectIDFromPkgID(recvOID.PkgID) - pv := m.Store.GetObject(recvPVOID).(*PackageValue) - rlm := pv.GetRealm() - m.Realm = rlm + recvPkgOID := ObjectIDFromPkgID(recvOID.PkgID) + pv := m.Store.GetObject(recvPkgOID).(*PackageValue) + rlm = pv.GetRealm() // done } } } + if rlm != nil && m.Realm != rlm { + // enter new realm + m.Realm = rlm + } } func (m *Machine) PushFrameGoNative(cx *CallExpr, fv *NativeValue) { diff --git a/gnovm/pkg/gnolang/ownership.go b/gnovm/pkg/gnolang/ownership.go index f2afc393d05..39f9af27ecb 100644 --- a/gnovm/pkg/gnolang/ownership.go +++ b/gnovm/pkg/gnolang/ownership.go @@ -332,6 +332,7 @@ func (tv *TypedValue) GetFirstObject(store Store) Object { // something in it; in that case, ignore the base. That will // likely require maybe a preparation step in persistence // ( or unlikely, a second type of ref-counting). + // XXX is there an issue with Base=nil pointers here cross realm? if cv.Base != nil { return cv.Base.(Object) } else { From 75b1d104ddd65d8135668a505c0ea9f78db0b5d4 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Thu, 19 Oct 2023 14:10:14 -0700 Subject: [PATCH 06/44] add realmtest --- .../demo/tests/p_crossrealm/p_crossrealm.gno | 24 +++++++++++++++ .../r/demo/tests/crossrealm/crossrealm.gno | 29 +++++++++++++++++++ gnovm/pkg/gnolang/machine.go | 6 +++- gnovm/tests/files/zrealm_crossrealm13.gno | 17 +++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno create mode 100644 examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno create mode 100644 gnovm/tests/files/zrealm_crossrealm13.gno diff --git a/examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno b/examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno new file mode 100644 index 00000000000..6d46203e98c --- /dev/null +++ b/examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno @@ -0,0 +1,24 @@ +package p_crossrealm + +type Stringer interface { + String() string +} + +type Container struct { + A int + B Stringer +} + +func (c *Container) Touch() *Container { + c.A += 1 + return c +} + +func (c *Container) Print() { + println("A:", c.A) + if c.B == nil { + println("B: undefined") + } else { + println("B:", c.B.String()) + } +} diff --git a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno new file mode 100644 index 00000000000..97273f642de --- /dev/null +++ b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno @@ -0,0 +1,29 @@ +package crossrealm + +import ( + "gno.land/p/demo/tests/p_crossrealm" + "gno.land/p/demo/ufmt" +) + +type LocalStruct struct { + A int +} + +func (ls *LocalStruct) String() string { + return ufmt.Sprintf("LocalStruct{%d}", ls.A) +} + +// local is saved locally in this realm +var local *LocalStruct + +func init() { + local = &LocalStruct{A: 123} +} + +// Make1 returns a local object wrapped by a p struct +func Make1() *p_crossrealm.Container { + return &p_crossrealm.Container{ + A: 1, + B: local, + } +} diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 8665e049e9f..b01c7e5ca80 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -221,7 +221,11 @@ func (m *Machine) RunMemPackage(memPkg *std.MemPackage, save bool) (*PackageNode } else { pn = NewPackageNode(Name(memPkg.Name), memPkg.Path, &FileSet{}) pv = pn.NewPackage() - m.Store.SetBlockNode(pn) + if true { // TODO finish SetBlockNode() + m.Store.SetBlockNode(pn) + } else { + // TODO m.Store.SetCacheBlockNode(pn) + } m.Store.SetCachePackage(pv) } m.SetActivePackage(pv) diff --git a/gnovm/tests/files/zrealm_crossrealm13.gno b/gnovm/tests/files/zrealm_crossrealm13.gno new file mode 100644 index 00000000000..23451e6f5d1 --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm13.gno @@ -0,0 +1,17 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + crossrealm "gno.land/r/demo/tests/crossrealm" +) + +func main() { + // even though we are running within a realm, + // we aren't storing the result of crossrealm.Make1(), + // so this should print fine. + crossrealm.Make1().Touch().Print() +} + +// Output: +// A: 2 +// B: LocalStruct{123} From 60162b99103b89cdd4114aadeff731f3ec67d42b Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 09:06:20 -0700 Subject: [PATCH 07/44] feat: add p/demo/fqname Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/fqname/fqname.gno | 54 +++++++++++++++++++ .../gno.land/p/demo/fqname/fqname_test.gno | 53 ++++++++++++++++++ examples/gno.land/p/demo/fqname/gno.mod | 3 ++ 3 files changed, 110 insertions(+) create mode 100644 examples/gno.land/p/demo/fqname/fqname.gno create mode 100644 examples/gno.land/p/demo/fqname/fqname_test.gno create mode 100644 examples/gno.land/p/demo/fqname/gno.mod diff --git a/examples/gno.land/p/demo/fqname/fqname.gno b/examples/gno.land/p/demo/fqname/fqname.gno new file mode 100644 index 00000000000..459aaccd664 --- /dev/null +++ b/examples/gno.land/p/demo/fqname/fqname.gno @@ -0,0 +1,54 @@ +// Package fqname provides utilities for handling fully qualified identifiers in +// Gno. A fully qualified identifier typically includes a package path followed +// by a dot (.) and then the name of a variable, function, type, or other +// package-level declaration. +package fqname + +import "strings" + +// Parse splits a fully qualified identifier into its package path and name +// components. It handles cases with and without slashes in the package path. +// +// pkgpath, name := fqname.Parse("gno.land/p/demo/avl.Tree") +// ufmt.Sprintf("Package: %s, Name: %s\n", id.Package, id.Name) +// // Output: Package: gno.land/p/demo/avl, Name: Tree +func Parse(fqname string) (pkgpath, name string) { + // Find the index of the last slash. + lastSlashIndex := strings.LastIndex(fqname, "/") + if lastSlashIndex == -1 { + // No slash found, handle it as a simple package name with dot notation. + dotIndex := strings.LastIndex(fqname, ".") + if dotIndex == -1 { + return fqname, "" + } + return fqname[:dotIndex], fqname[dotIndex+1:] + } + + // Get the part after the last slash. + afterSlash := fqname[lastSlashIndex+1:] + + // Check for a dot in the substring after the last slash. + dotIndex := strings.Index(afterSlash, ".") + if dotIndex == -1 { + // No dot found after the last slash + return fqname, "" + } + + // Split at the dot to separate the base and the suffix. + base := fqname[:lastSlashIndex+1+dotIndex] + suffix := afterSlash[dotIndex+1:] + + return base, suffix +} + +// Construct a qualified identifier. +// +// fqName := fqname.Construct("gno.land/r/demo/foo20", "GRC20") +// fmt.Println("Fully Qualified Name:", fqName) +// // Output: gno.land/r/demo/foo20.GRC20 +func Construct(pkgpath, name string) string { + if name == "" { + return pkgpath + } + return pkgpath + "." + name +} diff --git a/examples/gno.land/p/demo/fqname/fqname_test.gno b/examples/gno.land/p/demo/fqname/fqname_test.gno new file mode 100644 index 00000000000..57edefb07e3 --- /dev/null +++ b/examples/gno.land/p/demo/fqname/fqname_test.gno @@ -0,0 +1,53 @@ +package fqname + +import ( + "testing" + + "gno.land/p/demo/uassert" +) + +func TestParse(t *testing.T) { + tests := []struct { + input string + expectedPkgPath string + expectedName string + }{ + {"gno.land/p/demo/avl.Tree", "gno.land/p/demo/avl", "Tree"}, + {"gno.land/p/demo/avl", "gno.land/p/demo/avl", ""}, + {"gno.land/p/demo/avl.Tree.Node", "gno.land/p/demo/avl", "Tree.Node"}, + {"gno.land/p/demo/avl/nested.Package.Func", "gno.land/p/demo/avl/nested", "Package.Func"}, + {"path/filepath.Split", "path/filepath", "Split"}, + {"path.Split", "path", "Split"}, + {"path/filepath", "path/filepath", ""}, + {"path", "path", ""}, + {"", "", ""}, + } + + for _, tt := range tests { + pkgpath, name := Parse(tt.input) + uassert.Equal(t, tt.expectedPkgPath, pkgpath, "Package path did not match") + uassert.Equal(t, tt.expectedName, name, "Name did not match") + } +} + +func TestConstruct(t *testing.T) { + tests := []struct { + pkgpath string + name string + expected string + }{ + {"gno.land/r/demo/foo20", "GRC20", "gno.land/r/demo/foo20.GRC20"}, + {"gno.land/r/demo/foo20", "", "gno.land/r/demo/foo20"}, + {"path", "", "path"}, + {"path", "Split", "path.Split"}, + {"path/filepath", "", "path/filepath"}, + {"path/filepath", "Split", "path/filepath.Split"}, + {"", "JustName", ".JustName"}, + {"", "", ""}, + } + + for _, tt := range tests { + result := Construct(tt.pkgpath, tt.name) + uassert.Equal(t, tt.expected, result, "Constructed FQName did not match expected") + } +} diff --git a/examples/gno.land/p/demo/fqname/gno.mod b/examples/gno.land/p/demo/fqname/gno.mod new file mode 100644 index 00000000000..1282e262303 --- /dev/null +++ b/examples/gno.land/p/demo/fqname/gno.mod @@ -0,0 +1,3 @@ +module gno.land/p/demo/fqname + +require gno.land/p/demo/uassert v0.0.0-latest From 621a877a859a0e148c037e0f9c30049bba679c70 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 09:19:35 -0700 Subject: [PATCH 08/44] feat: add fqname.RenderLink Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/fqname/fqname.gno | 18 ++++++++++++++++ .../gno.land/p/demo/fqname/fqname_test.gno | 21 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/examples/gno.land/p/demo/fqname/fqname.gno b/examples/gno.land/p/demo/fqname/fqname.gno index 459aaccd664..09513d50341 100644 --- a/examples/gno.land/p/demo/fqname/fqname.gno +++ b/examples/gno.land/p/demo/fqname/fqname.gno @@ -52,3 +52,21 @@ func Construct(pkgpath, name string) string { } return pkgpath + "." + name } + +// RenderLink creates a formatted link for a fully qualified identifier. +// If the package path starts with "gno.land", it converts it to a markdown link. +// If the domain is different or missing, it returns the input as is. +func RenderLink(pkgPath, slug string) string { + if strings.HasPrefix(pkgPath, "gno.land") { + pkgLink := strings.TrimPrefix(pkgPath, "gno.land") + if slug != "" { + link := pkgPath + "." + slug + return "[" + pkgPath + "](" + pkgLink + ")." + slug + } + return "[" + pkgPath + "](" + pkgLink + ")" + } + if slug != "" { + return pkgPath + "." + slug + } + return pkgPath +} diff --git a/examples/gno.land/p/demo/fqname/fqname_test.gno b/examples/gno.land/p/demo/fqname/fqname_test.gno index 57edefb07e3..55a220776be 100644 --- a/examples/gno.land/p/demo/fqname/fqname_test.gno +++ b/examples/gno.land/p/demo/fqname/fqname_test.gno @@ -51,3 +51,24 @@ func TestConstruct(t *testing.T) { uassert.Equal(t, tt.expected, result, "Constructed FQName did not match expected") } } + +func TestRenderLink(t *testing.T) { + tests := []struct { + pkgPath string + slug string + expected string + }{ + {"gno.land/p/demo/avl", "Tree", "[gno.land/p/demo/avl](/p/demo/avl).Tree"}, + {"gno.land/p/demo/avl", "", "[gno.land/p/demo/avl](/p/demo/avl)"}, + {"github.com/a/b", "C", "github.com/a/b.C"}, + {"example.com/pkg", "Func", "example.com/pkg.Func"}, + {"gno.land/r/demo/foo20", "GRC20", "[gno.land/r/demo/foo20](/r/demo/foo20).GRC20"}, + {"gno.land/r/demo/foo20", "", "[gno.land/r/demo/foo20](/r/demo/foo20)"}, + {"", "", ""}, + } + + for _, tt := range tests { + result := RenderLink(tt.pkgPath, tt.slug) + uassert.Equal(t, tt.expected, result, "Rendered link did not match expected") + } +} From e545bfb5acf59f7a5dc5b6d369a0c6c41b5065f7 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 09:39:13 -0700 Subject: [PATCH 09/44] chore: refactor grc20_registry Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../gno.land/r/demo/grc20_registry/gno.mod | 7 ++- .../r/demo/grc20_registry/grc20_registry.gno | 51 ++++++++++------- .../grc20_registry/grc20_registry_test.gno | 56 +++++++++++-------- 3 files changed, 69 insertions(+), 45 deletions(-) diff --git a/examples/gno.land/r/demo/grc20_registry/gno.mod b/examples/gno.land/r/demo/grc20_registry/gno.mod index 8715926faf8..bf8820a0390 100644 --- a/examples/gno.land/r/demo/grc20_registry/gno.mod +++ b/examples/gno.land/r/demo/grc20_registry/gno.mod @@ -1,6 +1,9 @@ module gno.land/r/demo/grc20_registry require ( - "gno.land/p/demo/avl" v0.0.0-latest - "gno.land/p/demo/grc/grc20" v0.0.0-latest + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/fqname v0.0.0-latest + gno.land/p/demo/grc/grc20 v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/demo/urequire v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/grc20_registry/grc20_registry.gno b/examples/gno.land/r/demo/grc20_registry/grc20_registry.gno index 8f0f6d10df2..010dffbd477 100644 --- a/examples/gno.land/r/demo/grc20_registry/grc20_registry.gno +++ b/examples/gno.land/r/demo/grc20_registry/grc20_registry.gno @@ -2,43 +2,52 @@ package grc20_registry import ( "std" - "strings" "gno.land/p/demo/avl" + "gno.land/p/demo/fqname" "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/ufmt" ) var registry = avl.NewTree() // pkg path -> IGRC20 -func Register(token grc20.IGRC20) { - caller := std.PrevRealm().PkgPath() - registry.Set(caller, token) +func Register(token grc20.IGRC20, slug string) { + rlmPath := std.PrevRealm().PkgPath() + key := fqname.Construct(rlmPath, slug) + registry.Set(key, token) } -func Get(pkgPath string) (grc20.IGRC20, bool) { - coinI, ok := registry.Get(pkgPath) +func Get(key string) grc20.IGRC20 { + token, ok := registry.Get(key) if !ok { - return nil, false + return nil } - coin, ok := coinI.(grc20.IGRC20) - if !ok { - panic("internal error: registered object is not a GRC20 token") + return token.(grc20.IGRC20) +} + +func MustGet(key string) grc20.IGRC20 { + token := Get(key) + if token == nil { + panic("unknown token: " + key) } - return coin, true + return token } func Render(path string) string { - s := "# GRC20 Registry\n\n" + - "## Registered Tokens\n\n" - registry.Iterate("", "", func(pkgPath string, tokenI interface{}) bool { - token, ok := tokenI.(grc20.IGRC20) - pkgWebPath := strings.TrimPrefix(pkgPath, "gno.land") - if ok { - s += "- [" + token.GetName() + " (" + pkgPath + ")](" + pkgWebPath + ")\n" - } else { - s += "- [internal error: registered object is not a GRC20 token (" + pkgPath + ")](" + pkgWebPath + ")\n" - } + s := "" + + // TODO: add pagination + count := 0 + registry.Iterate("", "", func(key string, tokenI interface{}) bool { + count++ + token := tokenI.(grc20.IGRC20) + rlmPath, slug := fqname.Parse(key) + rlmLink := fqname.RenderLink(rlmPath, slug) + s += ufmt.Sprintf("- **%s** - %s\n", token.GetName(), rlmLink) return false }) + if count == 0 { + return "No registered token." + } return s } diff --git a/examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno b/examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno index 3b1475c17d1..c6d1e246154 100644 --- a/examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno +++ b/examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno @@ -5,34 +5,46 @@ import ( "testing" "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/urequire" ) func TestRegistry(t *testing.T) { - coin := &dummyImpl{} + std.TestSetRealm(std.NewCodeRealm("gno.land/r/demo/foo")) realmAddr := std.CurrentRealm().PkgPath() - Register(coin) - regCoin, ok := Get(realmAddr) - if !ok { - t.Fatal("expected to find coin") - } - if coin.GetSymbol() != "TST" { - t.Fatal("expected coin to have symbol TST") - } - expected := `# GRC20 Registry - -## Registered Tokens - -* [TestToken ()]() + tokenImpl := &dummyImpl{} + + // register + Register(tokenImpl, "") + regToken := Get(realmAddr) + urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil + urequire.Equal(t, regToken.GetSymbol(), "TST") + + expected := `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) ` got := Render("") - if got != expected { - t.Fatalf("expected `%s`, got `%s`", expected, got) - } - - // we test this here because there is more chance to find a bug after a token has been registered - if _, ok := Get("0xdeadbeef"); ok { - t.Fatal("expected not to find coin") - } + urequire.Equal(t, expected, got) + + // 404 + invalidToken := Get("0xdeadbeef") + urequire.True(t, invalidToken == nil) + + // register with a slug + Register(tokenImpl, "mySlug") + regToken = Get(realmAddr + ".mySlug") + urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil + urequire.Equal(t, regToken.GetSymbol(), "TST") + + // override + Register(tokenImpl, "") + regToken = Get(realmAddr + "") + urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil + urequire.Equal(t, regToken.GetSymbol(), "TST") + + expected = `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) +- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo).mySlug +` + got = Render("") + urequire.Equal(t, expected, got) } type dummyImpl struct{} From cdbe6da4894cd6cd179497b0c747bdc6b2a87c2d Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 09:45:30 -0700 Subject: [PATCH 10/44] chore: rename grc20reg Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/foo20/foo20.gno | 7 +++---- examples/gno.land/r/demo/foo20/gno.mod | 1 - .../gno.land/r/demo/{grc20_registry => grc20reg}/gno.mod | 2 +- .../grc20_registry.gno => grc20reg/grc20reg.gno} | 2 +- .../grc20_registry_test.gno => grc20reg/grc20reg_test.gno} | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) rename examples/gno.land/r/demo/{grc20_registry => grc20reg}/gno.mod (84%) rename examples/gno.land/r/demo/{grc20_registry/grc20_registry.gno => grc20reg/grc20reg.gno} (97%) rename examples/gno.land/r/demo/{grc20_registry/grc20_registry_test.gno => grc20reg/grc20reg_test.gno} (99%) diff --git a/examples/gno.land/r/demo/foo20/foo20.gno b/examples/gno.land/r/demo/foo20/foo20.gno index 89444c665e7..6a18d048ca0 100644 --- a/examples/gno.land/r/demo/foo20/foo20.gno +++ b/examples/gno.land/r/demo/foo20/foo20.gno @@ -6,10 +6,9 @@ import ( "gno.land/p/demo/grc/grc20" "gno.land/p/demo/ufmt" - "gno.land/r/demo/grc20_registry" - "gno.land/r/demo/users" - pusers "gno.land/p/demo/users" + "gno.land/r/demo/grc20reg" + "gno.land/r/demo/users" ) var ( @@ -19,7 +18,7 @@ var ( func init() { foo = grc20.NewAdminToken("Foo", "FOO", 4) - grc20_registry.Register(foo.GRC20()) + grc20reg.Register(foo.GRC20(), "") foo.Mint(admin, 1000000*10000) // @administrator (1M) foo.Mint("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", 10000*10000) // @manfred (10k) } diff --git a/examples/gno.land/r/demo/foo20/gno.mod b/examples/gno.land/r/demo/foo20/gno.mod index f5307735182..bf50c3b5202 100644 --- a/examples/gno.land/r/demo/foo20/gno.mod +++ b/examples/gno.land/r/demo/foo20/gno.mod @@ -5,6 +5,5 @@ require ( gno.land/p/demo/uassert v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest - gno.land/r/demo/grc20_registry v0.0.0-latest gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/grc20_registry/gno.mod b/examples/gno.land/r/demo/grc20reg/gno.mod similarity index 84% rename from examples/gno.land/r/demo/grc20_registry/gno.mod rename to examples/gno.land/r/demo/grc20reg/gno.mod index bf8820a0390..f02ee09c35a 100644 --- a/examples/gno.land/r/demo/grc20_registry/gno.mod +++ b/examples/gno.land/r/demo/grc20reg/gno.mod @@ -1,4 +1,4 @@ -module gno.land/r/demo/grc20_registry +module gno.land/r/demo/grc20reg require ( gno.land/p/demo/avl v0.0.0-latest diff --git a/examples/gno.land/r/demo/grc20_registry/grc20_registry.gno b/examples/gno.land/r/demo/grc20reg/grc20reg.gno similarity index 97% rename from examples/gno.land/r/demo/grc20_registry/grc20_registry.gno rename to examples/gno.land/r/demo/grc20reg/grc20reg.gno index 010dffbd477..b64a3f96347 100644 --- a/examples/gno.land/r/demo/grc20_registry/grc20_registry.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg.gno @@ -1,4 +1,4 @@ -package grc20_registry +package grc20reg import ( "std" diff --git a/examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno b/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno similarity index 99% rename from examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno rename to examples/gno.land/r/demo/grc20reg/grc20reg_test.gno index c6d1e246154..51bc20d3318 100644 --- a/examples/gno.land/r/demo/grc20_registry/grc20_registry_test.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno @@ -1,4 +1,4 @@ -package grc20_registry +package grc20reg import ( "std" From a65537bf67beb45ff72de4c7c9ba1afe4aeef60e Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 09:48:50 -0700 Subject: [PATCH 11/44] chore: emit event on registration Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/grc20reg/grc20reg.gno | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/gno.land/r/demo/grc20reg/grc20reg.gno b/examples/gno.land/r/demo/grc20reg/grc20reg.gno index b64a3f96347..acacc67afa8 100644 --- a/examples/gno.land/r/demo/grc20reg/grc20reg.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg.gno @@ -15,6 +15,11 @@ func Register(token grc20.IGRC20, slug string) { rlmPath := std.PrevRealm().PkgPath() key := fqname.Construct(rlmPath, slug) registry.Set(key, token) + std.Emit( + registerEvent, + "pkgpath", rlmPath, + "slug", slug, + ) } func Get(key string) grc20.IGRC20 { @@ -51,3 +56,5 @@ func Render(path string) string { } return s } + +const registerEvent = "register" From e8668f0ad1934d9b47a27a860dcbbdafccdcb194 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 14:24:31 -0700 Subject: [PATCH 12/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/foo20/foo20.gno | 4 +- .../gno.land/r/demo/grc20reg/grc20reg.gno | 6 +- .../gno.land/r/demo/grc20reg/tmp_proxy.gno | 57 +++++++++++++++++++ examples/gno.land/r/demo/wugnot/gno.mod | 1 + examples/gno.land/r/demo/wugnot/wugnot.gno | 9 ++- 5 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 examples/gno.land/r/demo/grc20reg/tmp_proxy.gno diff --git a/examples/gno.land/r/demo/foo20/foo20.gno b/examples/gno.land/r/demo/foo20/foo20.gno index 6a18d048ca0..5907fe197f6 100644 --- a/examples/gno.land/r/demo/foo20/foo20.gno +++ b/examples/gno.land/r/demo/foo20/foo20.gno @@ -18,7 +18,9 @@ var ( func init() { foo = grc20.NewAdminToken("Foo", "FOO", 4) - grc20reg.Register(foo.GRC20(), "") + pub := foo.GRC20() + proxy := grc20reg.Proxify(pub) + grc20reg.Register(proxy.GetName, "") foo.Mint(admin, 1000000*10000) // @administrator (1M) foo.Mint("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", 10000*10000) // @manfred (10k) } diff --git a/examples/gno.land/r/demo/grc20reg/grc20reg.gno b/examples/gno.land/r/demo/grc20reg/grc20reg.gno index acacc67afa8..b1572ce2c77 100644 --- a/examples/gno.land/r/demo/grc20reg/grc20reg.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg.gno @@ -11,10 +11,14 @@ import ( var registry = avl.NewTree() // pkg path -> IGRC20 +// func Register(getName func() string, slug string) { + func Register(token grc20.IGRC20, slug string) { + // proxy := tmpproxy{getName: getName} + proxy := Proxify(token) rlmPath := std.PrevRealm().PkgPath() key := fqname.Construct(rlmPath, slug) - registry.Set(key, token) + registry.Set(key, proxy) std.Emit( registerEvent, "pkgpath", rlmPath, diff --git a/examples/gno.land/r/demo/grc20reg/tmp_proxy.gno b/examples/gno.land/r/demo/grc20reg/tmp_proxy.gno new file mode 100644 index 00000000000..1b18b9064b8 --- /dev/null +++ b/examples/gno.land/r/demo/grc20reg/tmp_proxy.gno @@ -0,0 +1,57 @@ +package grc20reg + +import ( + "std" + + "gno.land/p/demo/grc/grc20" +) + +// FIXME; delete this file. +// we currently have a gnovm limitation: +// +// panic: cannot modify external-realm or non-realm object +type tmpproxy struct { + getName func() string + getSymbol func() string + getDecimals func() uint + totalSupply func() uint64 + balanceOf func(std.Address) (uint64, error) + transfer func(std.Address, uint64) error + allowance func(owner, spender std.Address) (uint64, error) + approve func(std.Address, uint64) error + transferFrom func(from, to std.Address, amount uint64) error +} + +func Proxify(input grc20.IGRC20) *tmpproxy { + return &tmpproxy{ + getName: input.GetName, + getSymbol: input.GetSymbol, + getDecimals: input.GetDecimals, + totalSupply: input.TotalSupply, + balanceOf: input.BalanceOf, + transfer: input.Transfer, + allowance: input.Allowance, + approve: input.Approve, + transferFrom: input.TransferFrom, + } +} + +var _ grc20.IGRC20 = (*tmpproxy)(nil) + +func (impl *tmpproxy) GetName() string { return impl.getName() } +func (impl *tmpproxy) GetSymbol() string { return impl.getSymbol() } +func (impl *tmpproxy) GetDecimals() uint { return impl.getDecimals() } +func (impl *tmpproxy) TotalSupply() uint64 { return impl.totalSupply() } +func (impl *tmpproxy) BalanceOf(account std.Address) (uint64, error) { return impl.balanceOf(account) } +func (impl *tmpproxy) Transfer(to std.Address, amount uint64) error { return impl.transfer(to, amount) } +func (impl *tmpproxy) Allowance(owner, spender std.Address) (uint64, error) { + return impl.allowance(owner, spender) +} + +func (impl *tmpproxy) Approve(spender std.Address, amount uint64) error { + return impl.approve(spender, amount) +} + +func (impl *tmpproxy) TransferFrom(from, to std.Address, amount uint64) error { + return impl.transferFrom(from, to, amount) +} diff --git a/examples/gno.land/r/demo/wugnot/gno.mod b/examples/gno.land/r/demo/wugnot/gno.mod index f076e90e068..c7081ce6963 100644 --- a/examples/gno.land/r/demo/wugnot/gno.mod +++ b/examples/gno.land/r/demo/wugnot/gno.mod @@ -4,5 +4,6 @@ require ( gno.land/p/demo/grc/grc20 v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/wugnot/wugnot.gno b/examples/gno.land/r/demo/wugnot/wugnot.gno index 4896d23499e..b6be85497d3 100644 --- a/examples/gno.land/r/demo/wugnot/wugnot.gno +++ b/examples/gno.land/r/demo/wugnot/wugnot.gno @@ -6,10 +6,9 @@ import ( "gno.land/p/demo/grc/grc20" "gno.land/p/demo/ufmt" - - "gno.land/r/demo/users" - pusers "gno.land/p/demo/users" + "gno.land/r/demo/grc20reg" + "gno.land/r/demo/users" ) var ( @@ -19,6 +18,10 @@ var ( WUGNOT = wugnot.GRC20() ) +func init() { + grc20reg.Register(WUGNOT, "") +} + const ( ugnotMinDeposit uint64 = 1000 wugnotMinDeposit uint64 = 1 From 3f83d0165da65a3c363834feba68eed438446b35 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 14:29:02 -0700 Subject: [PATCH 13/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/bar20/bar20.gno | 2 + examples/gno.land/r/demo/bar20/gno.mod | 1 + examples/gno.land/r/demo/foo20/foo20.gno | 4 +- .../r/demo/grc20factory/grc20factory.gno | 2 + .../gno.land/r/demo/grc20reg/grc20reg.gno | 8 +-- .../gno.land/r/demo/grc20reg/tmp_proxy.gno | 57 ------------------- 6 files changed, 8 insertions(+), 66 deletions(-) delete mode 100644 examples/gno.land/r/demo/grc20reg/tmp_proxy.gno diff --git a/examples/gno.land/r/demo/bar20/bar20.gno b/examples/gno.land/r/demo/bar20/bar20.gno index 7388d87d24d..d33fd266727 100644 --- a/examples/gno.land/r/demo/bar20/bar20.gno +++ b/examples/gno.land/r/demo/bar20/bar20.gno @@ -9,6 +9,7 @@ import ( "gno.land/p/demo/grc/grc20" "gno.land/p/demo/ufmt" + "gno.land/r/demo/grc20reg" ) var ( @@ -19,6 +20,7 @@ var ( func init() { banker = grc20.NewAdminToken("Bar", "BAR", 4) Token = banker.GRC20() + grc20reg.Register(token, "") } func Faucet() string { diff --git a/examples/gno.land/r/demo/bar20/gno.mod b/examples/gno.land/r/demo/bar20/gno.mod index fd804beb4c4..15f50259d74 100644 --- a/examples/gno.land/r/demo/bar20/gno.mod +++ b/examples/gno.land/r/demo/bar20/gno.mod @@ -4,4 +4,5 @@ require ( gno.land/p/demo/grc/grc20 v0.0.0-latest gno.land/p/demo/testutils v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/foo20/foo20.gno b/examples/gno.land/r/demo/foo20/foo20.gno index 5907fe197f6..45139ff33cf 100644 --- a/examples/gno.land/r/demo/foo20/foo20.gno +++ b/examples/gno.land/r/demo/foo20/foo20.gno @@ -18,11 +18,9 @@ var ( func init() { foo = grc20.NewAdminToken("Foo", "FOO", 4) - pub := foo.GRC20() - proxy := grc20reg.Proxify(pub) - grc20reg.Register(proxy.GetName, "") foo.Mint(admin, 1000000*10000) // @administrator (1M) foo.Mint("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", 10000*10000) // @manfred (10k) + grc20reg.Register(foo.GRC20(), "") } // method proxies as public functions. diff --git a/examples/gno.land/r/demo/grc20factory/grc20factory.gno b/examples/gno.land/r/demo/grc20factory/grc20factory.gno index 0146d945f0d..09262e78d1f 100644 --- a/examples/gno.land/r/demo/grc20factory/grc20factory.gno +++ b/examples/gno.land/r/demo/grc20factory/grc20factory.gno @@ -7,6 +7,7 @@ import ( "gno.land/p/demo/avl" "gno.land/p/demo/grc/grc20" + "gno.land/r/demo/grc20reg" ) // XXX: the p/grc20 library needs a refactor to change names (i.e., adminToken) @@ -36,6 +37,7 @@ func NewTokenWithAdmin(name, symbol string, decimals uint, initialMint uint64, a admin: admin, } tokens.Set(symbol, &t) + grc20reg.Register(newToken.GRC20(), symbol) } // method proxies as public functions. diff --git a/examples/gno.land/r/demo/grc20reg/grc20reg.gno b/examples/gno.land/r/demo/grc20reg/grc20reg.gno index b1572ce2c77..44f028f1081 100644 --- a/examples/gno.land/r/demo/grc20reg/grc20reg.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg.gno @@ -9,16 +9,12 @@ import ( "gno.land/p/demo/ufmt" ) -var registry = avl.NewTree() // pkg path -> IGRC20 - -// func Register(getName func() string, slug string) { +var registry = avl.NewTree() // rlmPath[.slug] -> IGRC20 func Register(token grc20.IGRC20, slug string) { - // proxy := tmpproxy{getName: getName} - proxy := Proxify(token) rlmPath := std.PrevRealm().PkgPath() key := fqname.Construct(rlmPath, slug) - registry.Set(key, proxy) + registry.Set(key, token) std.Emit( registerEvent, "pkgpath", rlmPath, diff --git a/examples/gno.land/r/demo/grc20reg/tmp_proxy.gno b/examples/gno.land/r/demo/grc20reg/tmp_proxy.gno deleted file mode 100644 index 1b18b9064b8..00000000000 --- a/examples/gno.land/r/demo/grc20reg/tmp_proxy.gno +++ /dev/null @@ -1,57 +0,0 @@ -package grc20reg - -import ( - "std" - - "gno.land/p/demo/grc/grc20" -) - -// FIXME; delete this file. -// we currently have a gnovm limitation: -// -// panic: cannot modify external-realm or non-realm object -type tmpproxy struct { - getName func() string - getSymbol func() string - getDecimals func() uint - totalSupply func() uint64 - balanceOf func(std.Address) (uint64, error) - transfer func(std.Address, uint64) error - allowance func(owner, spender std.Address) (uint64, error) - approve func(std.Address, uint64) error - transferFrom func(from, to std.Address, amount uint64) error -} - -func Proxify(input grc20.IGRC20) *tmpproxy { - return &tmpproxy{ - getName: input.GetName, - getSymbol: input.GetSymbol, - getDecimals: input.GetDecimals, - totalSupply: input.TotalSupply, - balanceOf: input.BalanceOf, - transfer: input.Transfer, - allowance: input.Allowance, - approve: input.Approve, - transferFrom: input.TransferFrom, - } -} - -var _ grc20.IGRC20 = (*tmpproxy)(nil) - -func (impl *tmpproxy) GetName() string { return impl.getName() } -func (impl *tmpproxy) GetSymbol() string { return impl.getSymbol() } -func (impl *tmpproxy) GetDecimals() uint { return impl.getDecimals() } -func (impl *tmpproxy) TotalSupply() uint64 { return impl.totalSupply() } -func (impl *tmpproxy) BalanceOf(account std.Address) (uint64, error) { return impl.balanceOf(account) } -func (impl *tmpproxy) Transfer(to std.Address, amount uint64) error { return impl.transfer(to, amount) } -func (impl *tmpproxy) Allowance(owner, spender std.Address) (uint64, error) { - return impl.allowance(owner, spender) -} - -func (impl *tmpproxy) Approve(spender std.Address, amount uint64) error { - return impl.approve(spender, amount) -} - -func (impl *tmpproxy) TransferFrom(from, to std.Address, amount uint64) error { - return impl.transferFrom(from, to, amount) -} From 10719e7cbb45d4457cce9aec54038e79e6fa8701 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 15:05:46 -0700 Subject: [PATCH 14/44] Revert "Merge remote-tracking branch 'origin/dev/jae/boundmethodrealm' into dev/moul/grc20reg" This reverts commit e1a79feba2a603be0d10b9edbf47d31b5d365910, reversing changes made to e8668f0ad1934d9b47a27a860dcbbdafccdcb194. --- .../demo/tests/p_crossrealm/p_crossrealm.gno | 24 --------------- .../r/demo/tests/crossrealm/crossrealm.gno | 29 ------------------- gnovm/pkg/gnolang/machine.go | 24 ++------------- gnovm/pkg/gnolang/realm.go | 15 +--------- gnovm/tests/files/zrealm_crossrealm13.gno | 17 ----------- 5 files changed, 3 insertions(+), 106 deletions(-) delete mode 100644 examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno delete mode 100644 examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno delete mode 100644 gnovm/tests/files/zrealm_crossrealm13.gno diff --git a/examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno b/examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno deleted file mode 100644 index 6d46203e98c..00000000000 --- a/examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno +++ /dev/null @@ -1,24 +0,0 @@ -package p_crossrealm - -type Stringer interface { - String() string -} - -type Container struct { - A int - B Stringer -} - -func (c *Container) Touch() *Container { - c.A += 1 - return c -} - -func (c *Container) Print() { - println("A:", c.A) - if c.B == nil { - println("B: undefined") - } else { - println("B:", c.B.String()) - } -} diff --git a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno deleted file mode 100644 index 97273f642de..00000000000 --- a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno +++ /dev/null @@ -1,29 +0,0 @@ -package crossrealm - -import ( - "gno.land/p/demo/tests/p_crossrealm" - "gno.land/p/demo/ufmt" -) - -type LocalStruct struct { - A int -} - -func (ls *LocalStruct) String() string { - return ufmt.Sprintf("LocalStruct{%d}", ls.A) -} - -// local is saved locally in this realm -var local *LocalStruct - -func init() { - local = &LocalStruct{A: 123} -} - -// Make1 returns a local object wrapped by a p struct -func Make1() *p_crossrealm.Container { - return &p_crossrealm.Container{ - A: 1, - B: local, - } -} diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 413ff006ec5..aa89b643ea6 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -279,11 +279,7 @@ func (m *Machine) runMemPackage(memPkg *std.MemPackage, save, overrides bool) (* } else { pn = NewPackageNode(Name(memPkg.Name), memPkg.Path, &FileSet{}) pv = pn.NewPackage() - if true { // TODO finish SetBlockNode() - m.Store.SetBlockNode(pn) - } else { - // TODO m.Store.SetCacheBlockNode(pn) - } + m.Store.SetBlockNode(pn) m.Store.SetCachePackage(pv) } m.SetActivePackage(pv) @@ -1744,24 +1740,8 @@ func (m *Machine) PushFrameCall(cx *CallExpr, fv *FuncValue, recv TypedValue) { } m.Package = pv rlm := pv.GetRealm() - if rlm == nil && recv.IsDefined() { - // if bound method, get realm from receiver. - obj := recv.GetFirstObject(m.Store) - if obj == nil { - // panic("XXX not sure why this would be") - fmt.Println("XXX XXX", recv.String()) - } else { - recvOID := obj.GetObjectInfo().ID - if !recvOID.IsZero() { - recvPkgOID := ObjectIDFromPkgID(recvOID.PkgID) - pv := m.Store.GetObject(recvPkgOID).(*PackageValue) - rlm = pv.GetRealm() // done - } - } - } if rlm != nil && m.Realm != rlm { - // enter new realm - m.Realm = rlm + m.Realm = rlm // enter new realm } } diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 093cc934658..3a55b2e14b4 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -70,21 +70,12 @@ func (pid PkgID) Bytes() []byte { } func PkgIDFromPkgPath(path string) PkgID { - // fmt.Printf("PkgPath %s -> PkgID %v", path, - // PkgID{HashBytes([]byte(path))}) return PkgID{HashBytes([]byte(path))} } -// Returns the ObjectID of the PackageValue associated with path. func ObjectIDFromPkgPath(path string) ObjectID { - pkgID := PkgIDFromPkgPath(path) - return ObjectIDFromPkgID(pkgID) -} - -// Returns the ObjectID of the PackageValue associated with pkgID. -func ObjectIDFromPkgID(pkgID PkgID) ObjectID { return ObjectID{ - PkgID: pkgID, + PkgID: PkgIDFromPkgPath(path), NewTime: 1, // by realm logic. } } @@ -154,10 +145,6 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { return // do nothing. } if po.GetObjectID().PkgID != rlm.ID { - // fmt.Println("PO", po.String()) - // fmt.Println("PO.PKGID", po.GetObjectID().PkgID) - // fmt.Println("rlm", rlm) - // fmt.Println("rlm.ID", rlm.ID) panic("cannot modify external-realm or non-realm object") } diff --git a/gnovm/tests/files/zrealm_crossrealm13.gno b/gnovm/tests/files/zrealm_crossrealm13.gno deleted file mode 100644 index 23451e6f5d1..00000000000 --- a/gnovm/tests/files/zrealm_crossrealm13.gno +++ /dev/null @@ -1,17 +0,0 @@ -// PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test - -import ( - crossrealm "gno.land/r/demo/tests/crossrealm" -) - -func main() { - // even though we are running within a realm, - // we aren't storing the result of crossrealm.Make1(), - // so this should print fine. - crossrealm.Make1().Touch().Print() -} - -// Output: -// A: 2 -// B: LocalStruct{123} From b8a8282dbaea40c09288d41dd8ecd734acef3a94 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 5 Jul 2024 15:34:34 -0700 Subject: [PATCH 15/44] override pv and rlm if method receiver has one --- gnovm/cmd/gno/run_test.go | 2 +- gnovm/pkg/gnolang/machine.go | 17 ++++++++++++++++- gnovm/pkg/gnolang/ownership.go | 5 ----- gnovm/pkg/gnolang/realm.go | 9 ++++++++- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/gnovm/cmd/gno/run_test.go b/gnovm/cmd/gno/run_test.go index 06f9a8dc3a5..79a873cdfe5 100644 --- a/gnovm/cmd/gno/run_test.go +++ b/gnovm/cmd/gno/run_test.go @@ -73,7 +73,7 @@ func TestRunApp(t *testing.T) { }, { args: []string{"run", "-debug-addr", "invalidhost:17538", "../../tests/integ/debugger/sample.gno"}, - errShouldContain: "listen tcp: lookup invalidhost", + errShouldContain: "listen tcp", }, { args: []string{"run", "../../tests/integ/invalid_assign/main.gno"}, diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 864384ea122..22a891da26f 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -1734,8 +1734,23 @@ func (m *Machine) PushFrameCall(cx *CallExpr, fv *FuncValue, recv TypedValue) { if pv == nil { panic(fmt.Sprintf("package value missing in store: %s", fv.PkgPath)) } - m.Package = pv rlm := pv.GetRealm() + if rlm == nil && recv.IsDefined() { + obj := recv.GetFirstObject(m.Store) + if obj == nil { + // could be a nil receiver. + // just ignore. + } else { + recvOID := obj.GetObjectInfo().ID + if !recvOID.IsZero() { + // override the pv and rlm with receiver's. + recvPkgOID := ObjectIDFromPkgID(recvOID.PkgID) + pv = m.Store.GetObject(recvPkgOID).(*PackageValue) + rlm = pv.GetRealm() // done + } + } + } + m.Package = pv if rlm != nil && m.Realm != rlm { m.Realm = rlm // enter new realm } diff --git a/gnovm/pkg/gnolang/ownership.go b/gnovm/pkg/gnolang/ownership.go index 24d70b5dd84..adc096c506b 100644 --- a/gnovm/pkg/gnolang/ownership.go +++ b/gnovm/pkg/gnolang/ownership.go @@ -328,11 +328,6 @@ func (oi *ObjectInfo) GetIsTransient() bool { func (tv *TypedValue) GetFirstObject(store Store) Object { switch cv := tv.V.(type) { case PointerValue: - // TODO: in the future, consider skipping the base if persisted - // ref-count would be 1, e.g. only this pointer refers to - // something in it; in that case, ignore the base. That will - // likely require maybe a preparation step in persistence - // ( or unlikely, a second type of ref-counting). return cv.Base.(Object) case *ArrayValue: return cv diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 3a55b2e14b4..3710524130a 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -73,9 +73,16 @@ func PkgIDFromPkgPath(path string) PkgID { return PkgID{HashBytes([]byte(path))} } +// Returns the ObjectID of the PackageValue associated with path. func ObjectIDFromPkgPath(path string) ObjectID { + pkgID := PkgIDFromPkgPath(path) + return ObjectIDFromPkgID(pkgID) +} + +// Returns the ObjectID of the PackageValue associated with pkgID. +func ObjectIDFromPkgID(pkgID PkgID) ObjectID { return ObjectID{ - PkgID: PkgIDFromPkgPath(path), + PkgID: pkgID, NewTime: 1, // by realm logic. } } From 1a86dbbe16d2c8489c4d20a287c91ab16fb0013c Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 15:34:56 -0700 Subject: [PATCH 16/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../gno.land/r/demo/grc20reg/grc20reg.gno | 39 ++++++++++++------- .../r/demo/grc20reg/grc20reg_test.gno | 13 ++++++- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/examples/gno.land/r/demo/grc20reg/grc20reg.gno b/examples/gno.land/r/demo/grc20reg/grc20reg.gno index 44f028f1081..c87f07e0af7 100644 --- a/examples/gno.land/r/demo/grc20reg/grc20reg.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg.gno @@ -39,22 +39,35 @@ func MustGet(key string) grc20.IGRC20 { } func Render(path string) string { - s := "" - - // TODO: add pagination - count := 0 - registry.Iterate("", "", func(key string, tokenI interface{}) bool { - count++ - token := tokenI.(grc20.IGRC20) + switch { + case path == "": // home + // TODO: add pagination + s := "" + count := 0 + registry.Iterate("", "", func(key string, tokenI interface{}) bool { + count++ + token := tokenI.(grc20.IGRC20) + rlmPath, slug := fqname.Parse(key) + rlmLink := fqname.RenderLink(rlmPath, slug) + s += ufmt.Sprintf("- **%s** - %s\n", token.GetName(), rlmLink) + return false + }) + if count == 0 { + return "No registered token." + } + return s + default: // specific token + key := path + token := MustGet(key) rlmPath, slug := fqname.Parse(key) rlmLink := fqname.RenderLink(rlmPath, slug) - s += ufmt.Sprintf("- **%s** - %s\n", token.GetName(), rlmLink) - return false - }) - if count == 0 { - return "No registered token." + s := ufmt.Sprintf("# %s\n", token.GetName()) + s += ufmt.Sprintf("- symbol: **%s**\n", token.GetSymbol()) + s += ufmt.Sprintf("- realm: %s\n", rlmLink) + s += ufmt.Sprintf("- decimals: %d\n", token.GetDecimals()) + s += ufmt.Sprintf("- total supply: %d\n", token.TotalSupply()) + return s } - return s } const registerEvent = "register" diff --git a/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno b/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno index 51bc20d3318..3e2c3ba896b 100644 --- a/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno @@ -45,6 +45,15 @@ func TestRegistry(t *testing.T) { ` got = Render("") urequire.Equal(t, expected, got) + + expected = `# TestToken +- symbol: **TST** +- realm: [gno.land/r/demo/foo](/r/demo/foo).mySlug +- decimals: 1337 +- total supply: 1234567 +` + got = Render("gno.land/r/demo/foo.mySlug") + urequire.Equal(t, expected, got) } type dummyImpl struct{} @@ -54,8 +63,8 @@ var _ grc20.IGRC20 = (*dummyImpl)(nil) func (impl *dummyImpl) GetName() string { return "TestToken" } func (impl *dummyImpl) GetSymbol() string { return "TST" } -func (impl *dummyImpl) GetDecimals() uint { panic("not implemented") } -func (impl *dummyImpl) TotalSupply() uint64 { panic("not implemented") } +func (impl *dummyImpl) GetDecimals() uint { return 1337 } +func (impl *dummyImpl) TotalSupply() uint64 { return 1234567 } func (impl *dummyImpl) BalanceOf(account std.Address) (uint64, error) { panic("not implemented") } func (impl *dummyImpl) Transfer(to std.Address, amount uint64) error { panic("not implemented") } func (impl *dummyImpl) Allowance(owner, spender std.Address) (uint64, error) { From 23f7173e816ae21c10170bb18e9da3300eee5822 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 5 Jul 2024 15:35:27 -0700 Subject: [PATCH 17/44] add tests --- .../demo/tests/p_crossrealm/p_crossrealm.gno | 24 +++++++ .../r/demo/tests/crossrealm/crossrealm.gno | 29 ++++++++ .../testdata/gno_test/realm_boundmethod.txtar | 71 +++++++++++++++++++ gnovm/pkg/gnolang/values.go | 2 - gnovm/tests/files/zrealm_crossrealm14.gno | 17 +++++ 5 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno create mode 100644 examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno create mode 100644 gnovm/cmd/gno/testdata/gno_test/realm_boundmethod.txtar create mode 100644 gnovm/tests/files/zrealm_crossrealm14.gno diff --git a/examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno b/examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno new file mode 100644 index 00000000000..6d46203e98c --- /dev/null +++ b/examples/gno.land/p/demo/tests/p_crossrealm/p_crossrealm.gno @@ -0,0 +1,24 @@ +package p_crossrealm + +type Stringer interface { + String() string +} + +type Container struct { + A int + B Stringer +} + +func (c *Container) Touch() *Container { + c.A += 1 + return c +} + +func (c *Container) Print() { + println("A:", c.A) + if c.B == nil { + println("B: undefined") + } else { + println("B:", c.B.String()) + } +} diff --git a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno new file mode 100644 index 00000000000..97273f642de --- /dev/null +++ b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno @@ -0,0 +1,29 @@ +package crossrealm + +import ( + "gno.land/p/demo/tests/p_crossrealm" + "gno.land/p/demo/ufmt" +) + +type LocalStruct struct { + A int +} + +func (ls *LocalStruct) String() string { + return ufmt.Sprintf("LocalStruct{%d}", ls.A) +} + +// local is saved locally in this realm +var local *LocalStruct + +func init() { + local = &LocalStruct{A: 123} +} + +// Make1 returns a local object wrapped by a p struct +func Make1() *p_crossrealm.Container { + return &p_crossrealm.Container{ + A: 1, + B: local, + } +} diff --git a/gnovm/cmd/gno/testdata/gno_test/realm_boundmethod.txtar b/gnovm/cmd/gno/testdata/gno_test/realm_boundmethod.txtar new file mode 100644 index 00000000000..9d935df74c2 --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_test/realm_boundmethod.txtar @@ -0,0 +1,71 @@ +# Set up GNOROOT in the current directory. +mkdir $WORK/gnovm +symlink $WORK/gnovm/stdlibs -> $GNOROOT/gnovm/stdlibs +env GNOROOT=$WORK + +gno test -v ./examples/gno.land/r/demo/realm2 + +stderr '=== RUN TestDo' +stderr '--- PASS: TestDo.*' + +stderr '=== RUN file/realm2_filetest.gno' +stderr '--- PASS: file/realm2_filetest.*' + +-- examples/gno.land/p/demo/counter/gno.mod -- +module gno.land/p/demo/counter + +-- examples/gno.land/p/demo/counter/counter.gno -- +package counter + +type Counter struct { + n int +} + +func (c *Counter) Inc() { + c.n++ +} + +-- examples/gno.land/r/demo/realm1/realm1.gno -- +package realm1 + +import "gno.land/p/demo/counter" + +var c = counter.Counter{} + +func GetCounter() *counter.Counter { + return &c +} + +-- examples/gno.land/r/demo/realm2/realm2.gno -- +package realm2 + +import ( + "gno.land/r/demo/realm1" +) + +func Do() { + realm1.GetCounter().Inc() +} + +-- examples/gno.land/r/demo/realm2/realm2_filetest.gno -- +// PKGPATH: gno.land/r/tests +package tests + +import "gno.land/r/demo/realm2" + +func main() { + realm2.Do() + println("OK") +} + +// Output: +// OK + +-- examples/gno.land/r/demo/realm2/realm2_test.gno -- +package realm2 + +import "testing" + +func TestDo(t *testing.T) { + Do() +} diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index d38c083428c..125ae13fbcf 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -192,7 +192,6 @@ const ( PointerIndexNative = -3 // Base is *NativeValue. ) -/* func (pv *PointerValue) GetBase(store Store) Object { switch cbase := pv.Base.(type) { case nil: @@ -207,7 +206,6 @@ func (pv *PointerValue) GetBase(store Store) Object { panic("should not happen") } } -*/ // cu: convert untyped; pass false for const definitions // TODO: document as something that enables into-native assignment. diff --git a/gnovm/tests/files/zrealm_crossrealm14.gno b/gnovm/tests/files/zrealm_crossrealm14.gno new file mode 100644 index 00000000000..23451e6f5d1 --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm14.gno @@ -0,0 +1,17 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + crossrealm "gno.land/r/demo/tests/crossrealm" +) + +func main() { + // even though we are running within a realm, + // we aren't storing the result of crossrealm.Make1(), + // so this should print fine. + crossrealm.Make1().Touch().Print() +} + +// Output: +// A: 2 +// B: LocalStruct{123} From b1254a744f23f6697387fe82be2e31c04c430963 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:11:31 -0700 Subject: [PATCH 18/44] chore: add missing gno.mod files Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/tests/p_crossrealm/gno.mod | 1 + examples/gno.land/r/demo/tests/crossrealm/gno.mod | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 examples/gno.land/p/demo/tests/p_crossrealm/gno.mod create mode 100644 examples/gno.land/r/demo/tests/crossrealm/gno.mod diff --git a/examples/gno.land/p/demo/tests/p_crossrealm/gno.mod b/examples/gno.land/p/demo/tests/p_crossrealm/gno.mod new file mode 100644 index 00000000000..8585cfd9c8d --- /dev/null +++ b/examples/gno.land/p/demo/tests/p_crossrealm/gno.mod @@ -0,0 +1 @@ +module gno.land/p/demo/tests/p_crossrealm diff --git a/examples/gno.land/r/demo/tests/crossrealm/gno.mod b/examples/gno.land/r/demo/tests/crossrealm/gno.mod new file mode 100644 index 00000000000..71a89ec2ec5 --- /dev/null +++ b/examples/gno.land/r/demo/tests/crossrealm/gno.mod @@ -0,0 +1,6 @@ +module gno.land/r/demo/tests/crossrealm + +require ( + gno.land/p/demo/tests/p_crossrealm v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest +) From d7508a0ad78e059a4824a6eb35f7c09ca9cce57c Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:25:59 -0700 Subject: [PATCH 19/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/bar20/bar20.gno | 2 +- examples/gno.land/r/demo/grc20reg/grc20reg.gno | 3 ++- examples/gno.land/r/demo/grc20reg/grc20reg_test.gno | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/r/demo/bar20/bar20.gno b/examples/gno.land/r/demo/bar20/bar20.gno index d33fd266727..f64c88d8763 100644 --- a/examples/gno.land/r/demo/bar20/bar20.gno +++ b/examples/gno.land/r/demo/bar20/bar20.gno @@ -20,7 +20,7 @@ var ( func init() { banker = grc20.NewAdminToken("Bar", "BAR", 4) Token = banker.GRC20() - grc20reg.Register(token, "") + grc20reg.Register(Token, "") } func Faucet() string { diff --git a/examples/gno.land/r/demo/grc20reg/grc20reg.gno b/examples/gno.land/r/demo/grc20reg/grc20reg.gno index c87f07e0af7..315b0e0449d 100644 --- a/examples/gno.land/r/demo/grc20reg/grc20reg.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg.gno @@ -49,7 +49,8 @@ func Render(path string) string { token := tokenI.(grc20.IGRC20) rlmPath, slug := fqname.Parse(key) rlmLink := fqname.RenderLink(rlmPath, slug) - s += ufmt.Sprintf("- **%s** - %s\n", token.GetName(), rlmLink) + infoLink := "/r/demo/grc20reg:" + key + s += ufmt.Sprintf("- **%s** - %s - [info](%s)\n", token.GetName(), rlmLink, infoLink) return false }) if count == 0 { diff --git a/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno b/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno index 3e2c3ba896b..3fa72e685cb 100644 --- a/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno @@ -19,7 +19,7 @@ func TestRegistry(t *testing.T) { urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil urequire.Equal(t, regToken.GetSymbol(), "TST") - expected := `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) + expected := `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) - [info](/r/demo/grc20reg:gno.land/r/demo/foo) ` got := Render("") urequire.Equal(t, expected, got) @@ -40,8 +40,8 @@ func TestRegistry(t *testing.T) { urequire.True(t, regToken != nil, "expected to find a token") // fixme: use urequire.NotNil urequire.Equal(t, regToken.GetSymbol(), "TST") - expected = `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) -- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo).mySlug + expected = `- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo) - [info](/r/demo/grc20reg:gno.land/r/demo/foo) +- **TestToken** - [gno.land/r/demo/foo](/r/demo/foo).mySlug - [info](/r/demo/grc20reg:gno.land/r/demo/foo.mySlug) ` got = Render("") urequire.Equal(t, expected, got) From 752d9e7c60687764d60f57d9b51c2ff1870f29bd Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:30:06 -0700 Subject: [PATCH 20/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/grc20factory/grc20factory.gno | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/gno.land/r/demo/grc20factory/grc20factory.gno b/examples/gno.land/r/demo/grc20factory/grc20factory.gno index 09262e78d1f..0163785865f 100644 --- a/examples/gno.land/r/demo/grc20factory/grc20factory.gno +++ b/examples/gno.land/r/demo/grc20factory/grc20factory.gno @@ -12,6 +12,10 @@ import ( // XXX: the p/grc20 library needs a refactor to change names (i.e., adminToken) +func init() { + NewToken("lorem ipsum", "LOREM", 4, 0xcafebabe) +} + type token struct { adminToken *grc20.AdminToken admin std.Address From 0bf2937b4940a5b5c8e9e0b1043962fe6a69670d Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:32:29 -0700 Subject: [PATCH 21/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/fqname/fqname.gno | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/gno.land/p/demo/fqname/fqname.gno b/examples/gno.land/p/demo/fqname/fqname.gno index 09513d50341..a877a041ef9 100644 --- a/examples/gno.land/p/demo/fqname/fqname.gno +++ b/examples/gno.land/p/demo/fqname/fqname.gno @@ -60,7 +60,6 @@ func RenderLink(pkgPath, slug string) string { if strings.HasPrefix(pkgPath, "gno.land") { pkgLink := strings.TrimPrefix(pkgPath, "gno.land") if slug != "" { - link := pkgPath + "." + slug return "[" + pkgPath + "](" + pkgLink + ")." + slug } return "[" + pkgPath + "](" + pkgLink + ")" From 9536cae52d319d06101381e9b01c27a5fa8b225a Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:34:43 -0700 Subject: [PATCH 22/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/foo20/gno.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/gno.land/r/demo/foo20/gno.mod b/examples/gno.land/r/demo/foo20/gno.mod index bf50c3b5202..d0042e71c15 100644 --- a/examples/gno.land/r/demo/foo20/gno.mod +++ b/examples/gno.land/r/demo/foo20/gno.mod @@ -5,5 +5,6 @@ require ( gno.land/p/demo/uassert v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/users v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest gno.land/r/demo/users v0.0.0-latest ) From 61a6e39a42c98781b02c71daccb435d9cc36ca9f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:39:25 -0700 Subject: [PATCH 23/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/grc20factory/gno.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/gno.land/r/demo/grc20factory/gno.mod b/examples/gno.land/r/demo/grc20factory/gno.mod index a430a1f9559..a9f04a702fb 100644 --- a/examples/gno.land/r/demo/grc20factory/gno.mod +++ b/examples/gno.land/r/demo/grc20factory/gno.mod @@ -3,4 +3,5 @@ module gno.land/r/demo/grc20factory require ( gno.land/p/demo/avl v0.0.0-latest gno.land/p/demo/grc/grc20 v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) From 10a5456868384c118b6703bbe91e19162e4b8dd1 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Fri, 5 Jul 2024 18:17:55 -0700 Subject: [PATCH 24/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/wugnot/wugnot.gno | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/examples/gno.land/r/demo/wugnot/wugnot.gno b/examples/gno.land/r/demo/wugnot/wugnot.gno index b6be85497d3..9c2e0b69465 100644 --- a/examples/gno.land/r/demo/wugnot/wugnot.gno +++ b/examples/gno.land/r/demo/wugnot/wugnot.gno @@ -91,17 +91,13 @@ func TotalSupply() uint64 { func BalanceOf(owner pusers.AddressOrName) uint64 { balance, err := wugnot.BalanceOf(users.Resolve(owner)) - if err != nil { - panic(err) - } + checkErr(err) return balance } func Allowance(owner, spender pusers.AddressOrName) uint64 { allowance, err := wugnot.Allowance(users.Resolve(owner), users.Resolve(spender)) - if err != nil { - panic(err) - } + checkErr(err) return allowance } @@ -111,22 +107,22 @@ func Allowance(owner, spender pusers.AddressOrName) uint64 { func Transfer(to pusers.AddressOrName, amount uint64) { caller := std.PrevRealm().Addr() err := wugnot.Transfer(caller, users.Resolve(to), amount) - if err != nil { - panic(err) - } + checkErr(err) } func Approve(spender pusers.AddressOrName, amount uint64) { caller := std.PrevRealm().Addr() err := wugnot.Approve(caller, users.Resolve(spender), amount) - if err != nil { - panic(err) - } + checkErr(err) } func TransferFrom(from, to pusers.AddressOrName, amount uint64) { caller := std.PrevRealm().Addr() err := wugnot.TransferFrom(caller, users.Resolve(from), users.Resolve(to), amount) + checkErr(err) +} + +func checkErr(err error) { if err != nil { panic(err) } From 6a41a93a8fb22025ddc9197705a69671743fecc1 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Fri, 5 Jul 2024 19:40:46 -0700 Subject: [PATCH 25/44] resave after init --- gnovm/pkg/gnolang/machine.go | 91 ++++++++++++++++++++++++++++++------ gnovm/tests/imports.go | 1 + 2 files changed, 78 insertions(+), 14 deletions(-) diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index d4c152f64a2..850da3d3c0f 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -284,14 +284,29 @@ func (m *Machine) runMemPackage(memPkg *std.MemPackage, save, overrides bool) (* } m.SetActivePackage(pv) // run files. - m.RunFiles(files.Files...) - // maybe save package value and mempackage. + updates := m.RunFileDecls(files.Files...) + // save package value and mempackage. + // XXX save condition will be removed once gonative is removed. + var throwaway *Realm if save { - // store package values and types - m.savePackageValuesAndTypes() + // store new package values and types + throwaway = m.saveNewPackageValuesAndTypes() + if throwaway != nil { + m.Realm = throwaway + } + } + // run init functions + m.runInitFromUpdates(pv, updates) + // save again after init. + if save { + m.resavePackageValues(throwaway) // store mempackage m.Store.AddMemPackage(memPkg) + if throwaway != nil { + m.Realm = nil + } } + return pn, pv } @@ -494,13 +509,27 @@ func (m *Machine) injectLocOnPanic() { } } -// Add files to the package's *FileSet and run them. -// This will also run each init function encountered. +// Convenience for tests. +// Production must not use this, because realm package init +// must happen after persistence and realm finalization, +// then changes from init persisted again. func (m *Machine) RunFiles(fns ...*FileNode) { - m.runFiles(fns...) + pv := m.Package + if pv == nil { + panic("RunFiles requires Machine.Package") + } + updates := m.runFileDecls(fns...) + m.runInitFromUpdates(pv, updates) +} + +// Add files to the package's *FileSet and run decls in them. +// This will also run each init function encountered. +// Returns the updated typed values of package. +func (m *Machine) RunFileDecls(fns ...*FileNode) []TypedValue { + return m.runFileDecls(fns...) } -func (m *Machine) runFiles(fns ...*FileNode) { +func (m *Machine) runFileDecls(fns ...*FileNode) []TypedValue { // Files' package names must match the machine's active one. // if there is one. for _, fn := range fns { @@ -628,11 +657,15 @@ func (m *Machine) runFiles(fns ...*FileNode) { } } - // Run new init functions. - // Go spec: "To ensure reproducible initialization - // behavior, build systems are encouraged to present - // multiple files belonging to the same package in - // lexical file name order to a compiler." + return updates +} + +// Run new init functions. +// Go spec: "To ensure reproducible initialization +// behavior, build systems are encouraged to present +// multiple files belonging to the same package in +// lexical file name order to a compiler." +func (m *Machine) runInitFromUpdates(pv *PackageValue, updates []TypedValue) { for _, tv := range updates { if tv.IsDefined() && tv.T.Kind() == FuncKind && tv.V != nil { fv, ok := tv.V.(*FuncValue) @@ -651,7 +684,10 @@ func (m *Machine) runFiles(fns ...*FileNode) { // Save the machine's package using realm finalization deep crawl. // Also saves declared types. -func (m *Machine) savePackageValuesAndTypes() { +// This happens before any init calls. +// Returns a throwaway realm package is not a realm, +// such as stdlibs or /p/ packages. +func (m *Machine) saveNewPackageValuesAndTypes() (throwaway *Realm) { // save package value and dependencies. pv := m.Package if pv.IsRealm() { @@ -664,6 +700,7 @@ func (m *Machine) savePackageValuesAndTypes() { rlm := NewRealm(pv.PkgPath) rlm.MarkNewReal(pv) rlm.FinalizeRealmTransaction(m.ReadOnly, m.Store) + throwaway = rlm } // save declared types. if bv, ok := pv.Block.(*Block); ok { @@ -675,6 +712,25 @@ func (m *Machine) savePackageValuesAndTypes() { } } } + return +} + +// Resave any changes to realm after init calls. +// Pass in the realm from m.saveNewPackageValuesAndTypes() +// in case a throwaway was created. +func (m *Machine) resavePackageValues(rlm *Realm) { + // save package value and dependencies. + pv := m.Package + if pv.IsRealm() { + rlm = pv.Realm + rlm.FinalizeRealmTransaction(m.ReadOnly, m.Store) + // re-save package realm info. + m.Store.SetPackageRealm(rlm) + } else { // use the throwaway realm. + rlm.FinalizeRealmTransaction(m.ReadOnly, m.Store) + } + // types were already saved, and should not change + // even after running the init function. } func (m *Machine) RunFunc(fn Name) { @@ -815,6 +871,13 @@ func (m *Machine) RunStatement(s Stmt) { // NOTE: to support realm persistence of types, must // first require the validation of blocknode locations. func (m *Machine) RunDeclaration(d Decl) { + if fd, ok := d.(*FuncDecl); ok && fd.Name == "init" { + // XXX or, consider running it, but why would this be needed? + // from a repl there is no need for init() functions. + // Also, there are complications with realms, where + // the realm must be persisted before init(), and persisted again. + panic("Machine.RunDeclaration cannot be used for init functions") + } // Preprocess input using package block. There should only // be one block right now, and it's a *PackageNode. pn := m.LastBlock().GetSource(m.Store).(*PackageNode) diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go index 86c81be9a18..2fa07fb0fb4 100644 --- a/gnovm/tests/imports.go +++ b/gnovm/tests/imports.go @@ -89,6 +89,7 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri // pkg := gno.NewPackageNode(gno.Name(memPkg.Name), memPkg.Path, nil) // pv := pkg.NewPackage() // m2.SetActivePackage(pv) + // XXX remove second arg 'false' and remove all gonative stuff. return m2.RunMemPackage(memPkg, false) } } From 4b3dabe71fbe55e90b89d424e2f20acbb8844a1f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 6 Jul 2024 08:04:31 -0700 Subject: [PATCH 26/44] chore(examples): make lint -> verbose Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile b/examples/Makefile index 578b4faf15b..cdc73ee6b3a 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -45,7 +45,7 @@ test: .PHONY: lint lint: - go run ../gnovm/cmd/gno lint $(OFFICIAL_PACKAGES) + go run ../gnovm/cmd/gno lint -v $(OFFICIAL_PACKAGES) .PHONY: test.sync test.sync: From bdb44bd604ad0c96af9a7006b17e5aa36205a378 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 6 Jul 2024 09:36:26 -0700 Subject: [PATCH 27/44] test(gnovm): add test for bounding issue --- examples/gno.land/r/demo/foo20/foo20.gno | 6 +++++ .../r/demo/tests/crossrealm/crossrealm.gno | 7 +++++ gnovm/tests/files/zrealm_crossrealm15.gno | 26 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 gnovm/tests/files/zrealm_crossrealm15.gno diff --git a/examples/gno.land/r/demo/foo20/foo20.gno b/examples/gno.land/r/demo/foo20/foo20.gno index 162454800e8..efdd0cacbb3 100644 --- a/examples/gno.land/r/demo/foo20/foo20.gno +++ b/examples/gno.land/r/demo/foo20/foo20.gno @@ -14,12 +14,18 @@ import ( var ( foo *grc20.AdminToken admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // TODO: helper to change admin + pub grc20.IGRC20 ) func init() { foo = grc20.NewAdminToken("Foo", "FOO", 4) foo.Mint(admin, 1000000*10000) // @administrator (1M) foo.Mint("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", 10000*10000) // @manfred (10k) +<<<<<<< Updated upstream +======= + pub = foo.GRC20() + grc20reg.Register(pub, "") +>>>>>>> Stashed changes } // method proxies as public functions. diff --git a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno index 97273f642de..0fdb5ff2308 100644 --- a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno +++ b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno @@ -27,3 +27,10 @@ func Make1() *p_crossrealm.Container { B: local, } } + +type Fooer interface{ Foo() } + +var fooer Fooer + +func SetFooer(f Fooer) { fooer = f } +func CallFoo() { fooer.Foo() } diff --git a/gnovm/tests/files/zrealm_crossrealm15.gno b/gnovm/tests/files/zrealm_crossrealm15.gno new file mode 100644 index 00000000000..16f01cf2701 --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm15.gno @@ -0,0 +1,26 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + crossrealm "gno.land/r/demo/tests/crossrealm" +) + +type fooer struct{} + +func (fooer) Foo() { println("hello") } + +var f *fooer + +func init() { + f = &fooer{} + crossrealm.SetFooer(f) + crossrealm.CallFoo() +} + +func main() { + print(".") +} + +// Output: +// hello +// . From 7cba9cab9f2b2f3ed8ec52883fc8185356ced9c7 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 6 Jul 2024 09:37:39 -0700 Subject: [PATCH 28/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/foo20/foo20.gno | 6 ------ gnovm/pkg/gnolang/realm.go | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/examples/gno.land/r/demo/foo20/foo20.gno b/examples/gno.land/r/demo/foo20/foo20.gno index efdd0cacbb3..162454800e8 100644 --- a/examples/gno.land/r/demo/foo20/foo20.gno +++ b/examples/gno.land/r/demo/foo20/foo20.gno @@ -14,18 +14,12 @@ import ( var ( foo *grc20.AdminToken admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // TODO: helper to change admin - pub grc20.IGRC20 ) func init() { foo = grc20.NewAdminToken("Foo", "FOO", 4) foo.Mint(admin, 1000000*10000) // @administrator (1M) foo.Mint("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", 10000*10000) // @manfred (10k) -<<<<<<< Updated upstream -======= - pub = foo.GRC20() - grc20reg.Register(pub, "") ->>>>>>> Stashed changes } // method proxies as public functions. diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 3710524130a..8ecdb3f4904 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -567,6 +567,24 @@ func (rlm *Realm) processNewEscapedMarks(store Store) { rlm.MarkDirty(po) } if eo.GetObjectID().IsZero() { + /* + println("@@@@@@@@1") + fmt.Printf("po: %v\n", po) + fmt.Printf("po.Info: %v\n", po.GetObjectInfo()) + fmt.Printf("po.Owner: %v\n", po.GetOwner()) + fmt.Printf("po.Hash: %v\n", po.GetHash()) + fmt.Printf("po.IsDeleted: %v\n", po.GetIsDeleted()) + fmt.Printf("po.IsDirty: %v\n", po.GetIsDirty()) + fmt.Printf("po.IsEscaped: %v\n", po.GetIsEscaped()) + fmt.Printf("po.IsNewDeleted: %v\n", po.GetIsNewDeleted()) + fmt.Printf("po.IsNewEscaped: %v\n", po.GetIsNewEscaped()) + fmt.Printf("po.IsOwned: %v\n", po.GetIsOwned()) + fmt.Printf("po.IsReal: %v\n", po.GetIsReal()) + fmt.Printf("po.IsNewReal: %v\n", po.GetIsNewReal()) + fmt.Printf("po.IsTransient: %v\n", po.GetIsTransient()) + println("@@@@@@@@2") + os.Exit(1) + */ panic("new escaped mark has no object ID") } // escaped has no owner. From 4ba7490ba18c2b6c35d4a984c571075dcdefcc1a Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 6 Jul 2024 09:38:11 -0700 Subject: [PATCH 29/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gnovm/pkg/gnolang/realm.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 8ecdb3f4904..3710524130a 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -567,24 +567,6 @@ func (rlm *Realm) processNewEscapedMarks(store Store) { rlm.MarkDirty(po) } if eo.GetObjectID().IsZero() { - /* - println("@@@@@@@@1") - fmt.Printf("po: %v\n", po) - fmt.Printf("po.Info: %v\n", po.GetObjectInfo()) - fmt.Printf("po.Owner: %v\n", po.GetOwner()) - fmt.Printf("po.Hash: %v\n", po.GetHash()) - fmt.Printf("po.IsDeleted: %v\n", po.GetIsDeleted()) - fmt.Printf("po.IsDirty: %v\n", po.GetIsDirty()) - fmt.Printf("po.IsEscaped: %v\n", po.GetIsEscaped()) - fmt.Printf("po.IsNewDeleted: %v\n", po.GetIsNewDeleted()) - fmt.Printf("po.IsNewEscaped: %v\n", po.GetIsNewEscaped()) - fmt.Printf("po.IsOwned: %v\n", po.GetIsOwned()) - fmt.Printf("po.IsReal: %v\n", po.GetIsReal()) - fmt.Printf("po.IsNewReal: %v\n", po.GetIsNewReal()) - fmt.Printf("po.IsTransient: %v\n", po.GetIsTransient()) - println("@@@@@@@@2") - os.Exit(1) - */ panic("new escaped mark has no object ID") } // escaped has no owner. From 621d59957e6e0380c74ed2160b7722d3b5682a61 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sat, 6 Jul 2024 09:59:04 -0700 Subject: [PATCH 30/44] chore: fixup --- gnovm/tests/files/zrealm_crossrealm15.gno | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gnovm/tests/files/zrealm_crossrealm15.gno b/gnovm/tests/files/zrealm_crossrealm15.gno index 16f01cf2701..f4e3d57b0fb 100644 --- a/gnovm/tests/files/zrealm_crossrealm15.gno +++ b/gnovm/tests/files/zrealm_crossrealm15.gno @@ -22,5 +22,7 @@ func main() { } // Output: -// hello -// . + +// Error: + +// Realm: From b0a1e1ffbbc1a5d641eb18e7816c12a76a5aedaa Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sat, 6 Jul 2024 16:22:38 -0700 Subject: [PATCH 31/44] allow passing in an object about to be persisted in the previous realm --- .../r/demo/tests/crossrealm/crossrealm.gno | 7 + gnovm/pkg/gnolang/realm.go | 20 +- gnovm/pkg/gnomod/file_test.go | 1 + gnovm/tests/file.go | 1 - gnovm/tests/files/zrealm_crossrealm15.gno | 30 + gnovm/tests/files/zrealm_crossrealm16.gno | 597 ++++++++++++++++++ 6 files changed, 653 insertions(+), 3 deletions(-) create mode 100644 gnovm/tests/files/zrealm_crossrealm15.gno create mode 100644 gnovm/tests/files/zrealm_crossrealm16.gno diff --git a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno index 97273f642de..0fdb5ff2308 100644 --- a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno +++ b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno @@ -27,3 +27,10 @@ func Make1() *p_crossrealm.Container { B: local, } } + +type Fooer interface{ Foo() } + +var fooer Fooer + +func SetFooer(f Fooer) { fooer = f } +func CallFoo() { fooer.Foo() } diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 3710524130a..df6100ee72f 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -171,6 +171,13 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { if co.GetIsEscaped() { // already escaped } else { + if !co.GetIsReal() { + // this can happen if a ref +1 + // new object gets passed into + // an external realm function. + co.SetIsNewReal(false) + rlm.MarkNewReal(co) + } rlm.MarkNewEscaped(co) } } else if co.GetIsReal() { @@ -375,6 +382,15 @@ func (rlm *Realm) processNewCreatedMarks(store Store) { // oo.SetIsNewReal(false) // skip if became deleted. continue + } else if oo.GetIsReal() && oo.GetObjectID().PkgID != rlm.ID { + // the object was new real in this realm, + // but another realm saved it before + // this realm started finalizing. + // if debug { XXX uncomment in the future + if oo.GetObjectID().PkgID == rlm.ID { + panic("should have been saved in another realm") + } + // } } else { rlm.incRefCreatedDescendants(store, oo) } @@ -442,7 +458,6 @@ func (rlm *Realm) incRefCreatedDescendants(store Store, oo Object) { // NOTE: do not unset owner here, // may become unescaped later // in processNewEscapedMarks(). - // NOTE: may already be escaped. rlm.MarkNewEscaped(child) } } else { @@ -569,6 +584,7 @@ func (rlm *Realm) processNewEscapedMarks(store Store) { if eo.GetObjectID().IsZero() { panic("new escaped mark has no object ID") } + // escaped has no owner. eo.SetOwner(nil) } @@ -1471,7 +1487,7 @@ func toRefValue(val Value) RefValue { } else if oo.GetIsEscaped() { if debug { if !oo.GetOwnerID().IsZero() { - panic("cannot convert escaped object to ref value without an owner ID") + panic("cannot convert escaped object to ref value with an owner ID") } } return RefValue{ diff --git a/gnovm/pkg/gnomod/file_test.go b/gnovm/pkg/gnomod/file_test.go index 7abfe16f340..7790e213c2f 100644 --- a/gnovm/pkg/gnomod/file_test.go +++ b/gnovm/pkg/gnomod/file_test.go @@ -16,6 +16,7 @@ import ( const testRemote string = "test3.gno.land:26657" +// XXX this test fails when the network is offline. func TestFetchDeps(t *testing.T) { for _, tc := range []struct { desc string diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index 8ab60145bd5..347a61ec8ee 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -307,7 +307,6 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { panic(fmt.Sprintf("fail on %s: got unexpected debug error(s): %v", path, gno.GetDebugErrors())) } // pnc is nil, errWanted empty, no gno debug errors - return nil } case "Output": // panic if got unexpected error diff --git a/gnovm/tests/files/zrealm_crossrealm15.gno b/gnovm/tests/files/zrealm_crossrealm15.gno new file mode 100644 index 00000000000..dc081dfc771 --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm15.gno @@ -0,0 +1,30 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + crossrealm "gno.land/r/demo/tests/crossrealm" +) + +type fooer struct{} + +func (fooer) Foo() { println("hello") } + +var f *fooer + +func init() { + f = &fooer{} + crossrealm.SetFooer(f) + crossrealm.CallFoo() +} + +func main() { + print(".") +} + +// Output: +// hello +// . + +// Error: + +// Realm: diff --git a/gnovm/tests/files/zrealm_crossrealm16.gno b/gnovm/tests/files/zrealm_crossrealm16.gno new file mode 100644 index 00000000000..db924432271 --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm16.gno @@ -0,0 +1,597 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + crossrealm "gno.land/r/demo/tests/crossrealm" +) + +type fooer struct{} + +func (fooer) Foo() { println("hello") } + +var f *fooer + +func main() { + f = &fooer{} + crossrealm.SetFooer(f) + crossrealm.CallFoo() + print(".") +} + +// Output: +// hello +// . + +// Error: + +// Realm: +// switchrealm["gno.land/r/demo/tests/crossrealm"] +// c[1712ac7adcfdc8e58a67e5615e20fb312394c4df:7]={ +// "Fields": [], +// "ObjectInfo": { +// "ID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:7", +// "ModTime": "0", +// "OwnerID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:6", +// "RefCount": "1" +// } +// } +// c[1712ac7adcfdc8e58a67e5615e20fb312394c4df:6]={ +// "ObjectInfo": { +// "ID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:6", +// "IsEscaped": true, +// "ModTime": "0", +// "RefCount": "2" +// }, +// "Value": { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.fooer" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "2aec554d4aaa9a1c37af933f8ca8d000088e4e7c", +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:7" +// } +// } +// } +// u[1712ac7adcfdc8e58a67e5615e20fb312394c4df:2]={ +// "Blank": {}, +// "ObjectInfo": { +// "ID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:2", +// "IsEscaped": true, +// "ModTime": "5", +// "RefCount": "2" +// }, +// "Parent": null, +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "0", +// "File": "", +// "Line": "0", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Values": [ +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.StructType", +// "Fields": [ +// { +// "Embedded": false, +// "Name": "A", +// "Tag": "", +// "Type": { +// "@type": "/gno.PrimitiveType", +// "value": "32" +// } +// } +// ], +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// }, +// "Methods": [ +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "ls", +// "Tag": "", +// "Type": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.LocalStruct" +// } +// } +// } +// ], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.PrimitiveType", +// "value": "16" +// } +// } +// ] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": null, +// "FileName": "crossrealm.gno", +// "IsMethod": true, +// "Name": "String", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "12", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "ls", +// "Tag": "", +// "Type": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.LocalStruct" +// } +// } +// } +// ], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.PrimitiveType", +// "value": "16" +// } +// } +// ] +// } +// } +// } +// ], +// "Name": "LocalStruct", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.InterfaceType", +// "Generic": "", +// "Methods": [ +// { +// "Embedded": false, +// "Name": "Foo", +// "Tag": "", +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// ], +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// }, +// "Methods": [], +// "Name": "Fooer", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:3" +// }, +// "FileName": "crossrealm.gno", +// "IsMethod": false, +// "Name": "init.2", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "19", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/p/demo/tests/p_crossrealm.Container" +// } +// } +// } +// ] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:3" +// }, +// "FileName": "crossrealm.gno", +// "IsMethod": false, +// "Name": "Make1", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "24", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/p/demo/tests/p_crossrealm.Container" +// } +// } +// } +// ] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "f", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.Fooer" +// } +// } +// ], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:3" +// }, +// "FileName": "crossrealm.gno", +// "IsMethod": false, +// "Name": "SetFooer", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "35", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "f", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.Fooer" +// } +// } +// ], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:3" +// }, +// "FileName": "crossrealm.gno", +// "IsMethod": false, +// "Name": "CallFoo", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "36", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.LocalStruct" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Hash": "a75fdb389fedfcbbaa7f446d528c1e149726347c", +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:4" +// }, +// "Index": "0", +// "TV": null +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.fooer" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:6" +// }, +// "Index": "0", +// "TV": null +// } +// } +// ] +// } +// switchrealm["gno.land/r/crossrealm_test"] +// u[f5a516808f8976c33939133293d598ce3bca4e8d:2]={ +// "Blank": {}, +// "ObjectInfo": { +// "ID": "f5a516808f8976c33939133293d598ce3bca4e8d:2", +// "IsEscaped": true, +// "ModTime": "3", +// "RefCount": "2" +// }, +// "Parent": null, +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "0", +// "File": "", +// "Line": "0", +// "PkgPath": "gno.land/r/crossrealm_test" +// } +// }, +// "Values": [ +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.StructType", +// "Fields": [], +// "PkgPath": "gno.land/r/crossrealm_test" +// }, +// "Methods": [ +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": ".recv", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.fooer" +// } +// } +// ], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": null, +// "FileName": "main.gno", +// "IsMethod": true, +// "Name": "Foo", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/crossrealm_test", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "main.gno", +// "Line": "10", +// "PkgPath": "gno.land/r/crossrealm_test" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": ".recv", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.fooer" +// } +// } +// ], +// "Results": [] +// } +// } +// } +// ], +// "Name": "fooer", +// "PkgPath": "gno.land/r/crossrealm_test" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "f5a516808f8976c33939133293d598ce3bca4e8d:3" +// }, +// "FileName": "main.gno", +// "IsMethod": false, +// "Name": "main", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/crossrealm_test", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "main.gno", +// "Line": "14", +// "PkgPath": "gno.land/r/crossrealm_test" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.fooer" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:6" +// }, +// "Index": "0", +// "TV": null +// } +// } +// ] +// } +// switchrealm["gno.land/r/demo/tests/crossrealm"] +// switchrealm["gno.land/r/crossrealm_test"] From cbf27535a6741619eb9f0e41567a0e8a0a860f45 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 7 Jul 2024 09:46:12 -0700 Subject: [PATCH 32/44] remove spurious lines --- gnovm/pkg/gnolang/realm.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index df6100ee72f..41a5e787667 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -382,15 +382,6 @@ func (rlm *Realm) processNewCreatedMarks(store Store) { // oo.SetIsNewReal(false) // skip if became deleted. continue - } else if oo.GetIsReal() && oo.GetObjectID().PkgID != rlm.ID { - // the object was new real in this realm, - // but another realm saved it before - // this realm started finalizing. - // if debug { XXX uncomment in the future - if oo.GetObjectID().PkgID == rlm.ID { - panic("should have been saved in another realm") - } - // } } else { rlm.incRefCreatedDescendants(store, oo) } From 5f647fbcaf8893085a3f7d29b8e19544af450822 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 7 Jul 2024 10:12:08 -0700 Subject: [PATCH 33/44] fix for all cases --- gnovm/pkg/gnolang/realm.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 41a5e787667..56b7fe458fb 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -171,13 +171,6 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { if co.GetIsEscaped() { // already escaped } else { - if !co.GetIsReal() { - // this can happen if a ref +1 - // new object gets passed into - // an external realm function. - co.SetIsNewReal(false) - rlm.MarkNewReal(co) - } rlm.MarkNewEscaped(co) } } else if co.GetIsReal() { @@ -573,7 +566,10 @@ func (rlm *Realm) processNewEscapedMarks(store Store) { rlm.MarkDirty(po) } if eo.GetObjectID().IsZero() { - panic("new escaped mark has no object ID") + // this can happen if a ref +1 + // new object gets passed into + // an external realm function. + rlm.assignNewObjectID(eo) } // escaped has no owner. From bd889f712e32a2f9dc55f0d061ec69ca37c033db Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 7 Jul 2024 10:23:27 -0700 Subject: [PATCH 34/44] reset new escape for both cases --- gnovm/pkg/gnolang/realm.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 56b7fe458fb..a1b7798ed46 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -171,6 +171,13 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { if co.GetIsEscaped() { // already escaped } else { + if !co.GetIsReal() { + // this can happen if a ref +1 + // new object gets passed into + // an external realm function. + co.SetIsNewReal(false) + rlm.MarkNewReal(co) + } rlm.MarkNewEscaped(co) } } else if co.GetIsReal() { @@ -442,6 +449,13 @@ func (rlm *Realm) incRefCreatedDescendants(store Store, oo Object) { // NOTE: do not unset owner here, // may become unescaped later // in processNewEscapedMarks(). + if !child.GetIsReal() { + // this can happen if a ref +1 + // new object gets passed into + // an external realm function. + child.SetIsNewReal(false) + rlm.MarkNewReal(child) + } rlm.MarkNewEscaped(child) } } else { From 00a2779d09981803e94379f4b97cff94158e67b2 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 7 Jul 2024 10:53:31 -0700 Subject: [PATCH 35/44] optimized fix --- gnovm/pkg/gnolang/ownership.go | 35 ++++++++++++++------------- gnovm/pkg/gnolang/realm.go | 44 +++++++++++++++++++++------------- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/gnovm/pkg/gnolang/ownership.go b/gnovm/pkg/gnolang/ownership.go index 511b44bfc73..a4a3a8dcf74 100644 --- a/gnovm/pkg/gnolang/ownership.go +++ b/gnovm/pkg/gnolang/ownership.go @@ -140,11 +140,12 @@ type ObjectInfo struct { RefCount int // for persistence. deleted/gc'd if 0. IsEscaped bool `json:",omitempty"` // hash in iavl. // MemRefCount int // consider for optimizations. - isDirty bool - isDeleted bool - isNewReal bool - isNewEscaped bool - isNewDeleted bool + isDirty bool + isDeleted bool + isNewReal bool + isNewEscaped bool + isNewDeleted bool + lastNewRealRealm PkgID // XXX huh? owner Object // mem reference to owner. @@ -154,17 +155,19 @@ type ObjectInfo struct { // Note that "owner" is nil. func (oi *ObjectInfo) Copy() ObjectInfo { return ObjectInfo{ - ID: oi.ID, - Hash: oi.Hash.Copy(), - OwnerID: oi.OwnerID, - ModTime: oi.ModTime, - RefCount: oi.RefCount, - IsEscaped: oi.IsEscaped, - isDirty: oi.isDirty, - isDeleted: oi.isDeleted, - isNewReal: oi.isNewReal, - isNewEscaped: oi.isNewEscaped, - isNewDeleted: oi.isNewDeleted, + ID: oi.ID, + Hash: oi.Hash.Copy(), + OwnerID: oi.OwnerID, + ModTime: oi.ModTime, + RefCount: oi.RefCount, + IsEscaped: oi.IsEscaped, + // XXX do the following need copying too? + isDirty: oi.isDirty, + isDeleted: oi.isDeleted, + isNewReal: oi.isNewReal, + isNewEscaped: oi.isNewEscaped, + isNewDeleted: oi.isNewDeleted, + lastNewRealRealm: oi.lastNewRealRealm, } } diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index a1b7798ed46..082b6297b17 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -171,14 +171,7 @@ func (rlm *Realm) DidUpdate(po, xo, co Object) { if co.GetIsEscaped() { // already escaped } else { - if !co.GetIsReal() { - // this can happen if a ref +1 - // new object gets passed into - // an external realm function. - co.SetIsNewReal(false) - rlm.MarkNewReal(co) - } - rlm.MarkNewEscaped(co) + rlm.MarkNewEscapedCheckCrossRealm(co) } } else if co.GetIsReal() { rlm.MarkDirty(co) @@ -272,6 +265,24 @@ func (rlm *Realm) MarkNewDeleted(oo Object) { rlm.newDeleted = append(rlm.newDeleted, oo) } +func (rlm *Realm) MarkNewEscapedCheckCrossRealm(oo Object) { + oi := oo.GetObjectInfo() + if !oi.GetIsReal() { + // this can happen if a ref +1 + // new object gets passed into + // an external realm function. + if oi.lastNewRealRealm == rlm.ID { + // we already marked as new real here + // and appended to newCreated, skip. + } else { + oi.lastNewRealRealm = rlm.ID + oi.SetIsNewReal(false) + rlm.MarkNewReal(oo) + } + } + rlm.MarkNewEscaped(oo) +} + func (rlm *Realm) MarkNewEscaped(oo Object) { if debug { if !oo.GetIsNewReal() && !oo.GetIsReal() { @@ -366,7 +377,13 @@ func (rlm *Realm) FinalizeRealmTransaction(readonly bool, store Store) { // and get assigned ids. func (rlm *Realm) processNewCreatedMarks(store Store) { // Create new objects and their new descendants. - for _, oo := range rlm.newCreated { + // NOTE: the following range does not work + // because incRefCreatedDescendants may append to newCreated + // for the case when new escapes are found to have crossed. + // XXX write test. + // for _, oo := range rlm.newCreated { + for i := 0; i < len(rlm.newCreated); i++ { + oo := rlm.newCreated[i] if debug { if oo.GetIsDirty() { panic("new created mark cannot be dirty") @@ -449,14 +466,7 @@ func (rlm *Realm) incRefCreatedDescendants(store Store, oo Object) { // NOTE: do not unset owner here, // may become unescaped later // in processNewEscapedMarks(). - if !child.GetIsReal() { - // this can happen if a ref +1 - // new object gets passed into - // an external realm function. - child.SetIsNewReal(false) - rlm.MarkNewReal(child) - } - rlm.MarkNewEscaped(child) + rlm.MarkNewEscapedCheckCrossRealm(child) } } else { panic("child reference count should be greater than zero after increasing") From 3a498f69bf209a1c279e5bb05033aac1007cfb10 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 7 Jul 2024 11:08:06 -0700 Subject: [PATCH 36/44] optimize --- gnovm/pkg/gnolang/ownership.go | 28 +++++++++++++++------------- gnovm/pkg/gnolang/realm.go | 28 ++++++++++------------------ 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/gnovm/pkg/gnolang/ownership.go b/gnovm/pkg/gnolang/ownership.go index a4a3a8dcf74..015d7a59907 100644 --- a/gnovm/pkg/gnolang/ownership.go +++ b/gnovm/pkg/gnolang/ownership.go @@ -140,12 +140,12 @@ type ObjectInfo struct { RefCount int // for persistence. deleted/gc'd if 0. IsEscaped bool `json:",omitempty"` // hash in iavl. // MemRefCount int // consider for optimizations. - isDirty bool - isDeleted bool - isNewReal bool - isNewEscaped bool - isNewDeleted bool - lastNewRealRealm PkgID + isDirty bool + isDeleted bool + isNewReal bool + isNewEscaped bool + isNewDeleted bool + lastNewRealEscapedRealm PkgID // XXX huh? owner Object // mem reference to owner. @@ -161,13 +161,15 @@ func (oi *ObjectInfo) Copy() ObjectInfo { ModTime: oi.ModTime, RefCount: oi.RefCount, IsEscaped: oi.IsEscaped, - // XXX do the following need copying too? - isDirty: oi.isDirty, - isDeleted: oi.isDeleted, - isNewReal: oi.isNewReal, - isNewEscaped: oi.isNewEscaped, - isNewDeleted: oi.isNewDeleted, - lastNewRealRealm: oi.lastNewRealRealm, + /* + // XXX do the following need copying too? + isDirty: oi.isDirty, + isDeleted: oi.isDeleted, + isNewReal: oi.isNewReal, + isNewEscaped: oi.isNewEscaped, + isNewDeleted: oi.isNewDeleted, + lastNewRealEscapedRealm: oi.lastNewRealEscapedRealm, + */ } } diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 082b6297b17..5eedb36bbd9 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -102,7 +102,6 @@ type Realm struct { created []Object // about to become real. updated []Object // real objects that were modified. deleted []Object // real objects that became deleted. - escaped []Object // real objects with refcount > 1. } // Creates a blank new realm with counter 0. @@ -267,18 +266,18 @@ func (rlm *Realm) MarkNewDeleted(oo Object) { func (rlm *Realm) MarkNewEscapedCheckCrossRealm(oo Object) { oi := oo.GetObjectInfo() + if oi.lastNewRealEscapedRealm == rlm.ID { + // already processed for this realm, + // see below. + return + } if !oi.GetIsReal() { // this can happen if a ref +1 // new object gets passed into // an external realm function. - if oi.lastNewRealRealm == rlm.ID { - // we already marked as new real here - // and appended to newCreated, skip. - } else { - oi.lastNewRealRealm = rlm.ID - oi.SetIsNewReal(false) - rlm.MarkNewReal(oo) - } + oi.lastNewRealEscapedRealm = rlm.ID + oi.SetIsNewReal(false) + rlm.MarkNewReal(oo) } rlm.MarkNewEscaped(oo) } @@ -318,8 +317,7 @@ func (rlm *Realm) FinalizeRealmTransaction(readonly bool, store Store) { len(rlm.newDeleted) > 0 || len(rlm.created) > 0 || len(rlm.updated) > 0 || - len(rlm.deleted) > 0 || - len(rlm.escaped) > 0 { + len(rlm.deleted) > 0 { panic("realm updates in readonly transaction") } return @@ -335,8 +333,7 @@ func (rlm *Realm) FinalizeRealmTransaction(readonly bool, store Store) { ensureUniq(rlm.updated) if false || rlm.created != nil || - rlm.deleted != nil || - rlm.escaped != nil { + rlm.deleted != nil { panic("realm should not have created, deleted, or escaped marks before beginning finalization") } } @@ -355,7 +352,6 @@ func (rlm *Realm) FinalizeRealmTransaction(readonly bool, store Store) { rlm.markDirtyAncestors(store) if debug { ensureUniq(rlm.created, rlm.updated, rlm.deleted) - ensureUniq(rlm.escaped) } // save all the created and updated objects. // hash calculation is done along the way, @@ -546,7 +542,6 @@ func (rlm *Realm) decRefDeletedDescendants(store Store, oo Object) { // objects get their original owners marked dirty (to be further // marked via markDirtyAncestors). func (rlm *Realm) processNewEscapedMarks(store Store) { - escaped := make([]Object, 0, len(rlm.newEscaped)) // These are those marked by MarkNewEscaped(), // regardless of whether new-real or was real, // but is always newly escaped, @@ -572,7 +567,6 @@ func (rlm *Realm) processNewEscapedMarks(store Store) { // we do that upon actually persisting // the hash index. // eo.SetIsNewEscaped(false) - escaped = append(escaped, eo) // add to escaped, and mark dirty previous owner. po := getOwner(store, eo) @@ -601,7 +595,6 @@ func (rlm *Realm) processNewEscapedMarks(store Store) { } } } - rlm.escaped = escaped // XXX is this actually used? } //---------------------------------------- @@ -816,7 +809,6 @@ func (rlm *Realm) clearMarks() { rlm.created = nil rlm.updated = nil rlm.deleted = nil - rlm.escaped = nil } //---------------------------------------- From 60b99ccec391ea420a8806b1d744719dfbd69009 Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 7 Jul 2024 11:33:51 -0700 Subject: [PATCH 37/44] add test for crossrealm new escaped internal objects --- gnovm/pkg/gnolang/realm.go | 9 +- gnovm/tests/files/zrealm_crossrealm17.gno | 680 ++++++++++++++++++++++ 2 files changed, 683 insertions(+), 6 deletions(-) create mode 100644 gnovm/tests/files/zrealm_crossrealm17.gno diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 5eedb36bbd9..5b046da53ac 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -376,8 +376,7 @@ func (rlm *Realm) processNewCreatedMarks(store Store) { // NOTE: the following range does not work // because incRefCreatedDescendants may append to newCreated // for the case when new escapes are found to have crossed. - // XXX write test. - // for _, oo := range rlm.newCreated { + // BAD: for _, oo := range rlm.newCreated { for i := 0; i < len(rlm.newCreated); i++ { oo := rlm.newCreated[i] if debug { @@ -583,11 +582,9 @@ func (rlm *Realm) processNewEscapedMarks(store Store) { // exists, mark dirty. rlm.MarkDirty(po) } + // TODO: move to if debug { } once proven. if eo.GetObjectID().IsZero() { - // this can happen if a ref +1 - // new object gets passed into - // an external realm function. - rlm.assignNewObjectID(eo) + panic("new escaped object has no object ID") } // escaped has no owner. diff --git a/gnovm/tests/files/zrealm_crossrealm17.gno b/gnovm/tests/files/zrealm_crossrealm17.gno new file mode 100644 index 00000000000..cb794c380d3 --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm17.gno @@ -0,0 +1,680 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + crossrealm "gno.land/r/demo/tests/crossrealm" +) + +type container struct{ *fooer } + +func (container) Foo() { println("hello container") } + +type fooer struct{} + +var f *fooer + +func main() { + f = &fooer{} + c := &container{f} + crossrealm.SetFooer(c) + crossrealm.CallFoo() + print(".") +} + +// Output: +// hello container +// . + +// Error: + +// Realm: +// switchrealm["gno.land/r/demo/tests/crossrealm"] +// c[1712ac7adcfdc8e58a67e5615e20fb312394c4df:7]={ +// "Fields": [ +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.fooer" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:8" +// }, +// "Index": "0", +// "TV": null +// } +// } +// ], +// "ObjectInfo": { +// "ID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:7", +// "ModTime": "0", +// "OwnerID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:6", +// "RefCount": "1" +// } +// } +// c[1712ac7adcfdc8e58a67e5615e20fb312394c4df:6]={ +// "ObjectInfo": { +// "ID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:6", +// "ModTime": "0", +// "OwnerID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:2", +// "RefCount": "1" +// }, +// "Value": { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.container" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "2e88a06ae991c0b638c9dd94a2d80b19e476d114", +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:7" +// } +// } +// } +// c[1712ac7adcfdc8e58a67e5615e20fb312394c4df:9]={ +// "Fields": [], +// "ObjectInfo": { +// "ID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:9", +// "ModTime": "0", +// "OwnerID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:8", +// "RefCount": "1" +// } +// } +// c[1712ac7adcfdc8e58a67e5615e20fb312394c4df:8]={ +// "ObjectInfo": { +// "ID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:8", +// "IsEscaped": true, +// "ModTime": "0", +// "RefCount": "2" +// }, +// "Value": { +// "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.fooer" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "e521635fd7846ccea2a330e7c114af77db07ee27", +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:9" +// } +// } +// } +// u[1712ac7adcfdc8e58a67e5615e20fb312394c4df:2]={ +// "Blank": {}, +// "ObjectInfo": { +// "ID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:2", +// "IsEscaped": true, +// "ModTime": "5", +// "RefCount": "2" +// }, +// "Parent": null, +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "0", +// "File": "", +// "Line": "0", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Values": [ +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.StructType", +// "Fields": [ +// { +// "Embedded": false, +// "Name": "A", +// "Tag": "", +// "Type": { +// "@type": "/gno.PrimitiveType", +// "value": "32" +// } +// } +// ], +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// }, +// "Methods": [ +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "ls", +// "Tag": "", +// "Type": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.LocalStruct" +// } +// } +// } +// ], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.PrimitiveType", +// "value": "16" +// } +// } +// ] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": null, +// "FileName": "crossrealm.gno", +// "IsMethod": true, +// "Name": "String", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "12", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "ls", +// "Tag": "", +// "Type": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.LocalStruct" +// } +// } +// } +// ], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.PrimitiveType", +// "value": "16" +// } +// } +// ] +// } +// } +// } +// ], +// "Name": "LocalStruct", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.InterfaceType", +// "Generic": "", +// "Methods": [ +// { +// "Embedded": false, +// "Name": "Foo", +// "Tag": "", +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// ], +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// }, +// "Methods": [], +// "Name": "Fooer", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:3" +// }, +// "FileName": "crossrealm.gno", +// "IsMethod": false, +// "Name": "init.2", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "19", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/p/demo/tests/p_crossrealm.Container" +// } +// } +// } +// ] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:3" +// }, +// "FileName": "crossrealm.gno", +// "IsMethod": false, +// "Name": "Make1", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "24", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/p/demo/tests/p_crossrealm.Container" +// } +// } +// } +// ] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "f", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.Fooer" +// } +// } +// ], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:3" +// }, +// "FileName": "crossrealm.gno", +// "IsMethod": false, +// "Name": "SetFooer", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "35", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "f", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.Fooer" +// } +// } +// ], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:3" +// }, +// "FileName": "crossrealm.gno", +// "IsMethod": false, +// "Name": "CallFoo", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/demo/tests/crossrealm", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "crossrealm.gno", +// "Line": "36", +// "PkgPath": "gno.land/r/demo/tests/crossrealm" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.LocalStruct" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Hash": "a75fdb389fedfcbbaa7f446d528c1e149726347c", +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:4" +// }, +// "Index": "0", +// "TV": null +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.container" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Hash": "7041ec66b0edbe5faaa7e8e9baa1b2a862887964", +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:6" +// }, +// "Index": "0", +// "TV": null +// } +// } +// ] +// } +// switchrealm["gno.land/r/crossrealm_test"] +// u[f5a516808f8976c33939133293d598ce3bca4e8d:2]={ +// "Blank": {}, +// "ObjectInfo": { +// "ID": "f5a516808f8976c33939133293d598ce3bca4e8d:2", +// "IsEscaped": true, +// "ModTime": "3", +// "RefCount": "2" +// }, +// "Parent": null, +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "0", +// "File": "", +// "Line": "0", +// "PkgPath": "gno.land/r/crossrealm_test" +// } +// }, +// "Values": [ +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.StructType", +// "Fields": [ +// { +// "Embedded": true, +// "Name": "fooer", +// "Tag": "", +// "Type": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.fooer" +// } +// } +// } +// ], +// "PkgPath": "gno.land/r/crossrealm_test" +// }, +// "Methods": [ +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": ".recv", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.container" +// } +// } +// ], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": null, +// "FileName": "main.gno", +// "IsMethod": true, +// "Name": "Foo", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/crossrealm_test", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "main.gno", +// "Line": "10", +// "PkgPath": "gno.land/r/crossrealm_test" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": ".recv", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.container" +// } +// } +// ], +// "Results": [] +// } +// } +// } +// ], +// "Name": "container", +// "PkgPath": "gno.land/r/crossrealm_test" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.TypeType" +// }, +// "V": { +// "@type": "/gno.TypeValue", +// "Type": { +// "@type": "/gno.DeclaredType", +// "Base": { +// "@type": "/gno.StructType", +// "Fields": [], +// "PkgPath": "gno.land/r/crossrealm_test" +// }, +// "Methods": [], +// "Name": "fooer", +// "PkgPath": "gno.land/r/crossrealm_test" +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "f5a516808f8976c33939133293d598ce3bca4e8d:3" +// }, +// "FileName": "main.gno", +// "IsMethod": false, +// "Name": "main", +// "NativeName": "", +// "NativePkg": "", +// "PkgPath": "gno.land/r/crossrealm_test", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "Column": "1", +// "File": "main.gno", +// "Line": "16", +// "PkgPath": "gno.land/r/crossrealm_test" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.PointerType", +// "Elt": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/crossrealm_test.fooer" +// } +// }, +// "V": { +// "@type": "/gno.PointerValue", +// "Base": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "1712ac7adcfdc8e58a67e5615e20fb312394c4df:8" +// }, +// "Index": "0", +// "TV": null +// } +// } +// ] +// } +// switchrealm["gno.land/r/demo/tests/crossrealm"] +// switchrealm["gno.land/r/crossrealm_test"] From 03e838bfc0d7db06e2f36367f7068c5af9a57fd9 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sun, 7 Jul 2024 13:49:58 -0500 Subject: [PATCH 38/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- .../r/demo/tests/crossrealm/crossrealm.gno | 7 ++-- gnovm/tests/files/zrealm_crossrealm16.gno | 26 +++++++++++++-- gnovm/tests/files/zrealm_crossrealm17.gno | 26 +++++++++++++-- gnovm/tests/files/zrealm_crossrealm18.gno | 33 +++++++++++++++++++ 4 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 gnovm/tests/files/zrealm_crossrealm18.gno diff --git a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno index 0fdb5ff2308..acb040c1ca8 100644 --- a/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno +++ b/examples/gno.land/r/demo/tests/crossrealm/crossrealm.gno @@ -32,5 +32,8 @@ type Fooer interface{ Foo() } var fooer Fooer -func SetFooer(f Fooer) { fooer = f } -func CallFoo() { fooer.Foo() } +func SetFooer(f Fooer) Fooer { + fooer = f + return fooer +} +func CallFoo() { fooer.Foo() } diff --git a/gnovm/tests/files/zrealm_crossrealm16.gno b/gnovm/tests/files/zrealm_crossrealm16.gno index db924432271..f2720c54769 100644 --- a/gnovm/tests/files/zrealm_crossrealm16.gno +++ b/gnovm/tests/files/zrealm_crossrealm16.gno @@ -325,7 +325,17 @@ func main() { // } // } // ], -// "Results": [] +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.Fooer" +// } +// } +// ] // }, // "V": { // "@type": "/gno.FuncValue", @@ -363,7 +373,17 @@ func main() { // } // } // ], -// "Results": [] +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.Fooer" +// } +// } +// ] // } // } // }, @@ -392,7 +412,7 @@ func main() { // "Location": { // "Column": "1", // "File": "crossrealm.gno", -// "Line": "36", +// "Line": "39", // "PkgPath": "gno.land/r/demo/tests/crossrealm" // } // }, diff --git a/gnovm/tests/files/zrealm_crossrealm17.gno b/gnovm/tests/files/zrealm_crossrealm17.gno index cb794c380d3..298655f7291 100644 --- a/gnovm/tests/files/zrealm_crossrealm17.gno +++ b/gnovm/tests/files/zrealm_crossrealm17.gno @@ -376,7 +376,17 @@ func main() { // } // } // ], -// "Results": [] +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.Fooer" +// } +// } +// ] // }, // "V": { // "@type": "/gno.FuncValue", @@ -414,7 +424,17 @@ func main() { // } // } // ], -// "Results": [] +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests/crossrealm.Fooer" +// } +// } +// ] // } // } // }, @@ -443,7 +463,7 @@ func main() { // "Location": { // "Column": "1", // "File": "crossrealm.gno", -// "Line": "36", +// "Line": "39", // "PkgPath": "gno.land/r/demo/tests/crossrealm" // } // }, diff --git a/gnovm/tests/files/zrealm_crossrealm18.gno b/gnovm/tests/files/zrealm_crossrealm18.gno new file mode 100644 index 00000000000..45441d4572d --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm18.gno @@ -0,0 +1,33 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + crossrealm "gno.land/r/demo/tests/crossrealm" +) + +type fooer struct{} + +func (fooer) Foo() { println("hello") } + +var f crossrealm.Fooer = crossrealm.SetFooer(&fooer{}) + +func init() { + crossrealm.CallFoo() +} + +func main() { + crossrealm.CallFoo() + print(".") +} + +// Output: +// hello +// hello +// . + +// Error: + +// Realm: +// switchrealm["gno.land/r/crossrealm_test"] +// switchrealm["gno.land/r/demo/tests/crossrealm"] +// switchrealm["gno.land/r/crossrealm_test"] From 71b74f42c918ec6e44e50ef299e322efb003d07f Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sun, 7 Jul 2024 13:53:22 -0500 Subject: [PATCH 39/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gnovm/tests/files/zrealm_crossrealm15.gno | 6 ++++-- gnovm/tests/files/zrealm_crossrealm16.gno | 10 ++++++---- gnovm/tests/files/zrealm_crossrealm17.gno | 10 ++++++---- gnovm/tests/files/zrealm_crossrealm18.gno | 8 +++++--- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/gnovm/tests/files/zrealm_crossrealm15.gno b/gnovm/tests/files/zrealm_crossrealm15.gno index dc081dfc771..c2c5575bfcd 100644 --- a/gnovm/tests/files/zrealm_crossrealm15.gno +++ b/gnovm/tests/files/zrealm_crossrealm15.gno @@ -2,12 +2,14 @@ package crossrealm_test import ( + "std" + crossrealm "gno.land/r/demo/tests/crossrealm" ) type fooer struct{} -func (fooer) Foo() { println("hello") } +func (fooer) Foo() { println("hello " + std.CurrentRealm().PkgPath()) } var f *fooer @@ -22,7 +24,7 @@ func main() { } // Output: -// hello +// hello gno.land/r/crossrealm_test // . // Error: diff --git a/gnovm/tests/files/zrealm_crossrealm16.gno b/gnovm/tests/files/zrealm_crossrealm16.gno index f2720c54769..47797631975 100644 --- a/gnovm/tests/files/zrealm_crossrealm16.gno +++ b/gnovm/tests/files/zrealm_crossrealm16.gno @@ -2,12 +2,14 @@ package crossrealm_test import ( + "std" + crossrealm "gno.land/r/demo/tests/crossrealm" ) type fooer struct{} -func (fooer) Foo() { println("hello") } +func (fooer) Foo() { println("hello " + std.CurrentRealm().PkgPath()) } var f *fooer @@ -19,7 +21,7 @@ func main() { } // Output: -// hello +// hello gno.land/r/crossrealm_test // . // Error: @@ -529,7 +531,7 @@ func main() { // "Location": { // "Column": "1", // "File": "main.gno", -// "Line": "10", +// "Line": "12", // "PkgPath": "gno.land/r/crossrealm_test" // } // }, @@ -581,7 +583,7 @@ func main() { // "Location": { // "Column": "1", // "File": "main.gno", -// "Line": "14", +// "Line": "16", // "PkgPath": "gno.land/r/crossrealm_test" // } // }, diff --git a/gnovm/tests/files/zrealm_crossrealm17.gno b/gnovm/tests/files/zrealm_crossrealm17.gno index 298655f7291..d0f488d86b2 100644 --- a/gnovm/tests/files/zrealm_crossrealm17.gno +++ b/gnovm/tests/files/zrealm_crossrealm17.gno @@ -2,12 +2,14 @@ package crossrealm_test import ( + "std" + crossrealm "gno.land/r/demo/tests/crossrealm" ) type container struct{ *fooer } -func (container) Foo() { println("hello container") } +func (container) Foo() { println("hello container " + std.CurrentRealm().PkgPath()) } type fooer struct{} @@ -22,7 +24,7 @@ func main() { } // Output: -// hello container +// hello container gno.land/r/crossrealm_test // . // Error: @@ -593,7 +595,7 @@ func main() { // "Location": { // "Column": "1", // "File": "main.gno", -// "Line": "10", +// "Line": "12", // "PkgPath": "gno.land/r/crossrealm_test" // } // }, @@ -664,7 +666,7 @@ func main() { // "Location": { // "Column": "1", // "File": "main.gno", -// "Line": "16", +// "Line": "18", // "PkgPath": "gno.land/r/crossrealm_test" // } // }, diff --git a/gnovm/tests/files/zrealm_crossrealm18.gno b/gnovm/tests/files/zrealm_crossrealm18.gno index 45441d4572d..cc46e3df514 100644 --- a/gnovm/tests/files/zrealm_crossrealm18.gno +++ b/gnovm/tests/files/zrealm_crossrealm18.gno @@ -2,12 +2,14 @@ package crossrealm_test import ( + "std" + crossrealm "gno.land/r/demo/tests/crossrealm" ) type fooer struct{} -func (fooer) Foo() { println("hello") } +func (fooer) Foo() { println("hello " + std.CurrentRealm().PkgPath()) } var f crossrealm.Fooer = crossrealm.SetFooer(&fooer{}) @@ -21,8 +23,8 @@ func main() { } // Output: -// hello -// hello +// hello gno.land/r/crossrealm_test +// hello gno.land/r/crossrealm_test // . // Error: From 4ca57af51b3a0350c9204478999bbf76c036313d Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sun, 7 Jul 2024 15:46:49 -0500 Subject: [PATCH 40/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- gnovm/stdlibs/math/overflow/overflow.gno | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gnovm/stdlibs/math/overflow/overflow.gno b/gnovm/stdlibs/math/overflow/overflow.gno index 9bdeff0720f..0bc2e03a522 100644 --- a/gnovm/stdlibs/math/overflow/overflow.gno +++ b/gnovm/stdlibs/math/overflow/overflow.gno @@ -223,7 +223,7 @@ func Div8p(a, b int8) int8 { func Quo8(a, b int8) (int8, int8, bool) { if b == 0 { return 0, 0, false - } else if b == -1 && a == math.MinInt8 { + } else if b == -1 && a == int8(math.MinInt8) { return 0, 0, false } c := a / b @@ -313,7 +313,7 @@ func Div16p(a, b int16) int16 { func Quo16(a, b int16) (int16, int16, bool) { if b == 0 { return 0, 0, false - } else if b == -1 && a == math.MinInt16 { + } else if b == -1 && a == int16(math.MinInt16) { return 0, 0, false } c := a / b @@ -403,7 +403,7 @@ func Div32p(a, b int32) int32 { func Quo32(a, b int32) (int32, int32, bool) { if b == 0 { return 0, 0, false - } else if b == -1 && a == math.MinInt32 { + } else if b == -1 && a == int32(math.MinInt32) { return 0, 0, false } c := a / b From a91c84a6c67e4cf3c4b1e159b560c1adceb5b0bf Mon Sep 17 00:00:00 2001 From: jaekwon Date: Sun, 7 Jul 2024 16:05:33 -0700 Subject: [PATCH 41/44] change realm to receiver's --- examples/gno.land/r/demo/tests/tests.gno | 2 + gnovm/pkg/gnolang/machine.go | 54 +++++++++----- gnovm/tests/files/zrealm_crossrealm16.gno | 3 +- gnovm/tests/files/zrealm_crossrealm17.gno | 3 +- .../files/zrealm_crossrealm19_stdlibs.gno | 37 ++++++++++ .../files/zrealm_crossrealm3_stdlibs.gno | 11 ++- .../files/zrealm_crossrealm4_stdlibs.gno | 12 ++-- .../files/zrealm_crossrealm5_stdlibs.gno | 8 +-- gnovm/tests/files/zrealm_tests0_stdlibs.gno | 70 +++++++++++-------- 9 files changed, 133 insertions(+), 67 deletions(-) create mode 100644 gnovm/tests/files/zrealm_crossrealm19_stdlibs.gno diff --git a/examples/gno.land/r/demo/tests/tests.gno b/examples/gno.land/r/demo/tests/tests.gno index 773412c3db9..2489a2214ba 100644 --- a/examples/gno.land/r/demo/tests/tests.gno +++ b/examples/gno.land/r/demo/tests/tests.gno @@ -49,6 +49,8 @@ type TestRealmObject struct { Field string } +var TestRealmObjectValue TestRealmObject + func ModifyTestRealmObject(t *TestRealmObject) { t.Field += "_modified" } diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index 850da3d3c0f..c8afd774ab9 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -36,8 +36,8 @@ func (e Exception) Sprint(m *Machine) string { type Machine struct { // State - Ops []Op // main operations - NumOps int + Ops []Op // operations stack + NumOps int // number of operations Values []TypedValue // buffer of values to be operated on NumValues int // number of values Exprs []Expr // pending expressions @@ -47,9 +47,9 @@ type Machine struct { Package *PackageValue // active package Realm *Realm // active realm Alloc *Allocator // memory allocations - Exceptions []Exception - NumResults int // number of results returned - Cycles int64 // number of "cpu" cycles + Exceptions []Exception // exceptions stack + NumResults int // number of results returned + Cycles int64 // number of "cpu" cycles performed Debugger Debugger @@ -199,6 +199,7 @@ func (m *Machine) Release() { machinePool.Put(m) } +// Convenience for initial setup of the machine. func (m *Machine) SetActivePackage(pv *PackageValue) { if err := m.CheckEmpty(); err != nil { panic(errors.Wrap(err, "set package when machine not empty")) @@ -210,6 +211,14 @@ func (m *Machine) SetActivePackage(pv *PackageValue) { } } +func (m *Machine) setCurrentPackage(pv *PackageValue) { + m.Package = pv + rlm := pv.GetRealm() + if rlm != nil { + m.Realm = rlm + } +} + //---------------------------------------- // top level Run* methods. @@ -1797,29 +1806,36 @@ func (m *Machine) PushFrameCall(cx *CallExpr, fv *FuncValue, recv TypedValue) { m.Printf("+F %#v\n", fr) } m.Frames = append(m.Frames, fr) - pv := fv.GetPackage(m.Store) - if pv == nil { - panic(fmt.Sprintf("package value missing in store: %s", fv.PkgPath)) - } - rlm := pv.GetRealm() - if rlm == nil && recv.IsDefined() { + if recv.IsDefined() { + // If the receiver is defined, we enter the receiver's realm. obj := recv.GetFirstObject(m.Store) if obj == nil { // could be a nil receiver. - // just ignore. + // set package and realm of function. + pv := fv.GetPackage(m.Store) + if pv == nil { + panic(fmt.Sprintf("package value missing in store: %s", fv.PkgPath)) + } + m.setCurrentPackage(pv) // maybe new realm } else { recvOID := obj.GetObjectInfo().ID - if !recvOID.IsZero() { + if recvOID.IsZero() { + // receiver isn't owned yet. + // just continue with current package and realm. + // XXX is this reasonable? + } else { // override the pv and rlm with receiver's. recvPkgOID := ObjectIDFromPkgID(recvOID.PkgID) - pv = m.Store.GetObject(recvPkgOID).(*PackageValue) - rlm = pv.GetRealm() // done + pv := m.Store.GetObject(recvPkgOID).(*PackageValue) + m.setCurrentPackage(pv) // maybe new realm } } - } - m.Package = pv - if rlm != nil && m.Realm != rlm { - m.Realm = rlm // enter new realm + } else { + pv := fv.GetPackage(m.Store) + if pv == nil { + panic(fmt.Sprintf("package value missing in store: %s", fv.PkgPath)) + } + m.setCurrentPackage(pv) // maybe new realm } } diff --git a/gnovm/tests/files/zrealm_crossrealm16.gno b/gnovm/tests/files/zrealm_crossrealm16.gno index db924432271..0fef0148b7d 100644 --- a/gnovm/tests/files/zrealm_crossrealm16.gno +++ b/gnovm/tests/files/zrealm_crossrealm16.gno @@ -443,6 +443,7 @@ func main() { // } // ] // } +// switchrealm["gno.land/r/demo/tests/crossrealm"] // switchrealm["gno.land/r/crossrealm_test"] // u[f5a516808f8976c33939133293d598ce3bca4e8d:2]={ // "Blank": {}, @@ -593,5 +594,3 @@ func main() { // } // ] // } -// switchrealm["gno.land/r/demo/tests/crossrealm"] -// switchrealm["gno.land/r/crossrealm_test"] diff --git a/gnovm/tests/files/zrealm_crossrealm17.gno b/gnovm/tests/files/zrealm_crossrealm17.gno index cb794c380d3..b3cdfc885ca 100644 --- a/gnovm/tests/files/zrealm_crossrealm17.gno +++ b/gnovm/tests/files/zrealm_crossrealm17.gno @@ -494,6 +494,7 @@ func main() { // } // ] // } +// switchrealm["gno.land/r/demo/tests/crossrealm"] // switchrealm["gno.land/r/crossrealm_test"] // u[f5a516808f8976c33939133293d598ce3bca4e8d:2]={ // "Blank": {}, @@ -676,5 +677,3 @@ func main() { // } // ] // } -// switchrealm["gno.land/r/demo/tests/crossrealm"] -// switchrealm["gno.land/r/crossrealm_test"] diff --git a/gnovm/tests/files/zrealm_crossrealm19_stdlibs.gno b/gnovm/tests/files/zrealm_crossrealm19_stdlibs.gno new file mode 100644 index 00000000000..6a51623f7bc --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm19_stdlibs.gno @@ -0,0 +1,37 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + "std" + + crossrealm "gno.land/r/demo/tests/crossrealm" +) + +type fooer struct { + s string +} + +func (f *fooer) Foo() { + f.s = "B" + println("hello " + f.s + " " + std.CurrentRealm().PkgPath()) +} + +var f *fooer + +func init() { + f = &fooer{s: "A"} + crossrealm.SetFooer(f) + crossrealm.CallFoo() +} + +func main() { + print(".") +} + +// Output: +// hello B gno.land/r/demo/tests/crossrealm +// . + +// Error: + +// Realm: diff --git a/gnovm/tests/files/zrealm_crossrealm3_stdlibs.gno b/gnovm/tests/files/zrealm_crossrealm3_stdlibs.gno index 6aa9c5247d8..105066c5ba7 100644 --- a/gnovm/tests/files/zrealm_crossrealm3_stdlibs.gno +++ b/gnovm/tests/files/zrealm_crossrealm3_stdlibs.gno @@ -13,10 +13,15 @@ func init() { } func main() { - // NOTE: but it is invalid to modify it using an external realm function. + // NOTE: it is valid to modify it using an external realm function, + // because the receiver makes the function run under this realm. somevalue.Modify() println(somevalue) + // we can even modify it directly. + somevalue.Field = "test_modified_directly" + println(somevalue) } -// Error: -// cannot modify external-realm or non-realm object +// Output: +// (struct{("test_modified" string)} gno.land/r/demo/tests.TestRealmObject) +// (struct{("test_modified_directly" string)} gno.land/r/demo/tests.TestRealmObject) diff --git a/gnovm/tests/files/zrealm_crossrealm4_stdlibs.gno b/gnovm/tests/files/zrealm_crossrealm4_stdlibs.gno index 6aa9c5247d8..ed73b7ad6bb 100644 --- a/gnovm/tests/files/zrealm_crossrealm4_stdlibs.gno +++ b/gnovm/tests/files/zrealm_crossrealm4_stdlibs.gno @@ -5,18 +5,18 @@ import ( "gno.land/r/demo/tests" ) -// NOTE: it is valid to persist external realm types. -var somevalue tests.TestRealmObject +// NOTE: it is valid to persist a pointer to an external object +var somevalue *tests.TestRealmObject func init() { - somevalue.Field = "test" + somevalue = &tests.TestRealmObjectValue } func main() { - // NOTE: but it is invalid to modify it using an external realm function. + // NOTE: it is valid to modify it using the external realm function. somevalue.Modify() println(somevalue) } -// Error: -// cannot modify external-realm or non-realm object +// Output: +// &(struct{("_modified" string)} gno.land/r/demo/tests.TestRealmObject) diff --git a/gnovm/tests/files/zrealm_crossrealm5_stdlibs.gno b/gnovm/tests/files/zrealm_crossrealm5_stdlibs.gno index 6aa9c5247d8..c7560b21463 100644 --- a/gnovm/tests/files/zrealm_crossrealm5_stdlibs.gno +++ b/gnovm/tests/files/zrealm_crossrealm5_stdlibs.gno @@ -6,15 +6,15 @@ import ( ) // NOTE: it is valid to persist external realm types. -var somevalue tests.TestRealmObject +var somevalue *tests.TestRealmObject func init() { - somevalue.Field = "test" + somevalue = &tests.TestRealmObjectValue } func main() { - // NOTE: but it is invalid to modify it using an external realm function. - somevalue.Modify() + // NOTE: but it is invalid to modify it directly. + somevalue.Field = "test" println(somevalue) } diff --git a/gnovm/tests/files/zrealm_tests0_stdlibs.gno b/gnovm/tests/files/zrealm_tests0_stdlibs.gno index 70ac3dd810d..5cd57c71a4a 100644 --- a/gnovm/tests/files/zrealm_tests0_stdlibs.gno +++ b/gnovm/tests/files/zrealm_tests0_stdlibs.gno @@ -23,7 +23,7 @@ func main() { // Realm: // switchrealm["gno.land/r/demo/tests"] -// c[0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:18]={ +// c[0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:19]={ // "Fields": [ // { // "T": { @@ -37,17 +37,17 @@ func main() { // } // ], // "ObjectInfo": { -// "ID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:18", +// "ID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:19", // "ModTime": "0", -// "OwnerID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:17", +// "OwnerID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:18", // "RefCount": "1" // } // } -// c[0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:17]={ +// c[0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:18]={ // "ObjectInfo": { -// "ID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:17", +// "ID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:18", // "ModTime": "0", -// "OwnerID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:16", +// "OwnerID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:17", // "RefCount": "1" // }, // "Value": { @@ -57,12 +57,12 @@ func main() { // }, // "V": { // "@type": "/gno.RefValue", -// "Hash": "d3d6ffa52602f2bc976051d79294d219750aca64", -// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:18" +// "Hash": "6b9b731f6118c2419f23ba57e1481679f17f4a8f", +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:19" // } // } // } -// c[0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:16]={ +// c[0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:17]={ // "Data": null, // "List": [ // { @@ -77,8 +77,8 @@ func main() { // "@type": "/gno.PointerValue", // "Base": { // "@type": "/gno.RefValue", -// "Hash": "4ea1e08156f3849b74a0f41f92cd4b48fb94926b", -// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:11" +// "Hash": "148d314678615253ee2032d7ecff6b144b474baf", +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:12" // }, // "Index": "0", // "TV": null @@ -96,8 +96,8 @@ func main() { // "@type": "/gno.PointerValue", // "Base": { // "@type": "/gno.RefValue", -// "Hash": "ce86ea1156e75a44cd9d7ba2261819b100aa4ed1", -// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:14" +// "Hash": "fa414e1770821b8deb8e6d46d97828c47f7d5fa5", +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:15" // }, // "Index": "0", // "TV": null @@ -115,8 +115,8 @@ func main() { // "@type": "/gno.PointerValue", // "Base": { // "@type": "/gno.RefValue", -// "Hash": "b66192fbd8a8dde79b6f854b5cc3c4cc965cfd92", -// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:17" +// "Hash": "aaa64d049cf8660d689780acac9f546f270eaa4e", +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:18" // }, // "Index": "0", // "TV": null @@ -124,7 +124,7 @@ func main() { // } // ], // "ObjectInfo": { -// "ID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:16", +// "ID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:17", // "ModTime": "0", // "OwnerID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:2", // "RefCount": "1" @@ -135,7 +135,7 @@ func main() { // "ObjectInfo": { // "ID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:2", // "IsEscaped": true, -// "ModTime": "15", +// "ModTime": "16", // "RefCount": "5" // }, // "Parent": null, @@ -400,7 +400,7 @@ func main() { // "Location": { // "Column": "1", // "File": "tests.gno", -// "Line": "56", +// "Line": "58", // "PkgPath": "gno.land/r/demo/tests" // } // }, @@ -1197,7 +1197,7 @@ func main() { // "Location": { // "Column": "1", // "File": "tests.gno", -// "Line": "52", +// "Line": "54", // "PkgPath": "gno.land/r/demo/tests" // } // }, @@ -1246,7 +1246,7 @@ func main() { // "Location": { // "Column": "1", // "File": "tests.gno", -// "Line": "74", +// "Line": "76", // "PkgPath": "gno.land/r/demo/tests" // } // }, @@ -1282,7 +1282,7 @@ func main() { // "Location": { // "Column": "1", // "File": "tests.gno", -// "Line": "79", +// "Line": "81", // "PkgPath": "gno.land/r/demo/tests" // } // }, @@ -1318,7 +1318,7 @@ func main() { // "Location": { // "Column": "1", // "File": "tests.gno", -// "Line": "87", +// "Line": "89", // "PkgPath": "gno.land/r/demo/tests" // } // }, @@ -1364,7 +1364,7 @@ func main() { // "Location": { // "Column": "1", // "File": "tests.gno", -// "Line": "91", +// "Line": "93", // "PkgPath": "gno.land/r/demo/tests" // } // }, @@ -1420,7 +1420,7 @@ func main() { // "Location": { // "Column": "1", // "File": "tests.gno", -// "Line": "95", +// "Line": "97", // "PkgPath": "gno.land/r/demo/tests" // } // }, @@ -1477,7 +1477,7 @@ func main() { // "Location": { // "Column": "1", // "File": "tests.gno", -// "Line": "99", +// "Line": "101", // "PkgPath": "gno.land/r/demo/tests" // } // }, @@ -1512,8 +1512,8 @@ func main() { // "@type": "/gno.SliceValue", // "Base": { // "@type": "/gno.RefValue", -// "Hash": "ad25f70f66c8c53042afd1377e5ff5ab744bf1a5", -// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:16" +// "Hash": "3c58838c5667649add1ff8ee48a1cdc187fcd2ef", +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:17" // }, // "Length": "3", // "Maxcap": "3", @@ -1563,6 +1563,17 @@ func main() { // }, // { // "T": { +// "@type": "/gno.RefType", +// "ID": "gno.land/r/demo/tests.TestRealmObject" +// }, +// "V": { +// "@type": "/gno.RefValue", +// "Hash": "5e56ba76fc0add1a3a67f7a8b6709f4f27215f93", +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:10" +// } +// }, +// { +// "T": { // "@type": "/gno.PointerType", // "Elt": { // "@type": "/gno.RefType", @@ -1590,10 +1601,7 @@ func main() { // } // ] // } -// d[0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:13] -// switchrealm["gno.land/r/demo/tests_foo"] -// switchrealm["gno.land/r/demo/tests_foo"] -// switchrealm["gno.land/r/demo/tests_foo"] +// d[0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:14] // switchrealm["gno.land/r/demo/tests_foo"] // switchrealm["gno.land/r/demo/tests"] // switchrealm["gno.land/r/demo/tests_test"] From f48048bd9c6c96ceae53d68c9b4e0831817c1baf Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sun, 7 Jul 2024 21:54:23 -0500 Subject: [PATCH 42/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/bar20/bar20.gno | 2 +- examples/gno.land/r/demo/bar20/gno.mod | 2 +- examples/gno.land/r/demo/grc20factory/gno.mod | 2 +- examples/gno.land/r/demo/grc20factory/grc20factory.gno | 2 +- examples/gno.land/r/demo/wugnot/wugnot.gno | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/r/demo/bar20/bar20.gno b/examples/gno.land/r/demo/bar20/bar20.gno index a3d05b9212c..3aaec94041a 100644 --- a/examples/gno.land/r/demo/bar20/bar20.gno +++ b/examples/gno.land/r/demo/bar20/bar20.gno @@ -20,7 +20,7 @@ var ( func init() { banker = grc20.NewBanker("Bar", "BAR", 4) Token = banker.Token() - grc20reg.Register(Token, "") + grc20reg.Register(Token, "") } func Faucet() string { diff --git a/examples/gno.land/r/demo/bar20/gno.mod b/examples/gno.land/r/demo/bar20/gno.mod index 7443c5eb9e6..9fb0f083e1b 100644 --- a/examples/gno.land/r/demo/bar20/gno.mod +++ b/examples/gno.land/r/demo/bar20/gno.mod @@ -4,6 +4,6 @@ require ( gno.land/p/demo/grc/grc20 v0.0.0-latest gno.land/p/demo/testutils v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest - gno.land/r/demo/grc20reg v0.0.0-latest gno.land/p/demo/urequire v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/grc20factory/gno.mod b/examples/gno.land/r/demo/grc20factory/gno.mod index 6c815d3c680..db0000d998c 100644 --- a/examples/gno.land/r/demo/grc20factory/gno.mod +++ b/examples/gno.land/r/demo/grc20factory/gno.mod @@ -3,7 +3,7 @@ module gno.land/r/demo/grc20factory require ( gno.land/p/demo/avl v0.0.0-latest gno.land/p/demo/grc/grc20 v0.0.0-latest - gno.land/r/demo/grc20reg v0.0.0-latest gno.land/p/demo/ownable v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/demo/grc20reg v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/grc20factory/grc20factory.gno b/examples/gno.land/r/demo/grc20factory/grc20factory.gno index cc531a0e128..5fe0687984a 100644 --- a/examples/gno.land/r/demo/grc20factory/grc20factory.gno +++ b/examples/gno.land/r/demo/grc20factory/grc20factory.gno @@ -6,9 +6,9 @@ import ( "gno.land/p/demo/avl" "gno.land/p/demo/grc/grc20" - "gno.land/r/demo/grc20reg" "gno.land/p/demo/ownable" "gno.land/p/demo/ufmt" + "gno.land/r/demo/grc20reg" ) var instances avl.Tree // symbol -> instance diff --git a/examples/gno.land/r/demo/wugnot/wugnot.gno b/examples/gno.land/r/demo/wugnot/wugnot.gno index 7178abd4587..67d7779105f 100644 --- a/examples/gno.land/r/demo/wugnot/wugnot.gno +++ b/examples/gno.land/r/demo/wugnot/wugnot.gno @@ -7,7 +7,7 @@ import ( "gno.land/p/demo/grc/grc20" "gno.land/p/demo/ufmt" pusers "gno.land/p/demo/users" - "gno.land/r/demo/grc20reg" + "gno.land/r/demo/grc20reg" "gno.land/r/demo/users" ) From 90730568925135a324fc5758a5138d4954ab6274 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sun, 7 Jul 2024 22:05:05 -0500 Subject: [PATCH 43/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/r/demo/grc20reg/grc20reg.gno | 12 ++++++------ .../gno.land/r/demo/grc20reg/grc20reg_test.gno | 18 ++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/examples/gno.land/r/demo/grc20reg/grc20reg.gno b/examples/gno.land/r/demo/grc20reg/grc20reg.gno index 315b0e0449d..5009f7d8086 100644 --- a/examples/gno.land/r/demo/grc20reg/grc20reg.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg.gno @@ -9,9 +9,9 @@ import ( "gno.land/p/demo/ufmt" ) -var registry = avl.NewTree() // rlmPath[.slug] -> IGRC20 +var registry = avl.NewTree() // rlmPath[.slug] -> Token -func Register(token grc20.IGRC20, slug string) { +func Register(token grc20.Token, slug string) { rlmPath := std.PrevRealm().PkgPath() key := fqname.Construct(rlmPath, slug) registry.Set(key, token) @@ -22,15 +22,15 @@ func Register(token grc20.IGRC20, slug string) { ) } -func Get(key string) grc20.IGRC20 { +func Get(key string) grc20.Token { token, ok := registry.Get(key) if !ok { return nil } - return token.(grc20.IGRC20) + return token.(grc20.Token) } -func MustGet(key string) grc20.IGRC20 { +func MustGet(key string) grc20.Token { token := Get(key) if token == nil { panic("unknown token: " + key) @@ -46,7 +46,7 @@ func Render(path string) string { count := 0 registry.Iterate("", "", func(key string, tokenI interface{}) bool { count++ - token := tokenI.(grc20.IGRC20) + token := tokenI.(grc20.Token) rlmPath, slug := fqname.Parse(key) rlmLink := fqname.RenderLink(rlmPath, slug) infoLink := "/r/demo/grc20reg:" + key diff --git a/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno b/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno index 3fa72e685cb..83f639de0c4 100644 --- a/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno +++ b/examples/gno.land/r/demo/grc20reg/grc20reg_test.gno @@ -59,17 +59,15 @@ func TestRegistry(t *testing.T) { type dummyImpl struct{} // FIXME: this should fail. -var _ grc20.IGRC20 = (*dummyImpl)(nil) +var _ grc20.Token = (*dummyImpl)(nil) -func (impl *dummyImpl) GetName() string { return "TestToken" } -func (impl *dummyImpl) GetSymbol() string { return "TST" } -func (impl *dummyImpl) GetDecimals() uint { return 1337 } -func (impl *dummyImpl) TotalSupply() uint64 { return 1234567 } -func (impl *dummyImpl) BalanceOf(account std.Address) (uint64, error) { panic("not implemented") } -func (impl *dummyImpl) Transfer(to std.Address, amount uint64) error { panic("not implemented") } -func (impl *dummyImpl) Allowance(owner, spender std.Address) (uint64, error) { - panic("not implemented") -} +func (impl *dummyImpl) GetName() string { return "TestToken" } +func (impl *dummyImpl) GetSymbol() string { return "TST" } +func (impl *dummyImpl) GetDecimals() uint { return 1337 } +func (impl *dummyImpl) TotalSupply() uint64 { return 1234567 } +func (impl *dummyImpl) BalanceOf(account std.Address) uint64 { panic("not implemented") } +func (impl *dummyImpl) Transfer(to std.Address, amount uint64) error { panic("not implemented") } +func (impl *dummyImpl) Allowance(owner, spender std.Address) uint64 { panic("not implemented") } func (impl *dummyImpl) Approve(spender std.Address, amount uint64) error { panic("not implemented") } func (impl *dummyImpl) TransferFrom(from, to std.Address, amount uint64) error { panic("not implemented") From 67e53538c9dcc65d92e8c9f85808e94758055498 Mon Sep 17 00:00:00 2001 From: moul <94029+moul@users.noreply.github.com> Date: Sun, 7 Jul 2024 22:30:16 -0500 Subject: [PATCH 44/44] chore: fixup Signed-off-by: moul <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/grc/grc20/token.gno | 43 ------------------- examples/gno.land/r/demo/foo20/foo20_test.gno | 15 ++++++- 2 files changed, 13 insertions(+), 45 deletions(-) diff --git a/examples/gno.land/p/demo/grc/grc20/token.gno b/examples/gno.land/p/demo/grc/grc20/token.gno index e13599e90bb..7f3b784932a 100644 --- a/examples/gno.land/p/demo/grc/grc20/token.gno +++ b/examples/gno.land/p/demo/grc/grc20/token.gno @@ -2,8 +2,6 @@ package grc20 import ( "std" - - "gno.land/p/demo/grc/exts" ) // token implements the Token interface. @@ -45,44 +43,3 @@ func (t *token) TransferFrom(from, to std.Address, amount uint64) error { } return t.banker.Transfer(from, to, amount) } - -type Token2 interface { - exts.TokenMetadata - - // Returns the amount of tokens in existence. - TotalSupply() uint64 - - // Returns the amount of tokens owned by `account`. - BalanceOf(account std.Address) uint64 - - // Moves `amount` tokens from the caller's account to `to`. - // - // Returns an error if the operation failed. - Transfer(to std.Address, amount uint64) error - - // Returns the remaining number of tokens that `spender` will be - // allowed to spend on behalf of `owner` through {transferFrom}. This is - // zero by default. - // - // This value changes when {approve} or {transferFrom} are called. - Allowance(owner, spender std.Address) uint64 - - // Sets `amount` as the allowance of `spender` over the caller's tokens. - // - // Returns an error if the operation failed. - // - // IMPORTANT: Beware that changing an allowance with this method brings the risk - // that someone may use both the old and the new allowance by unfortunate - // transaction ordering. One possible solution to mitigate this race - // condition is to first reduce the spender's allowance to 0 and set the - // desired value afterwards: - // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - Approve(spender std.Address, amount uint64) error - - // Moves `amount` tokens from `from` to `to` using the - // allowance mechanism. `amount` is then deducted from the caller's - // allowance. - // - // Returns an error if the operation failed. - TransferFrom(from, to std.Address, amount uint64) error -} diff --git a/examples/gno.land/r/demo/foo20/foo20_test.gno b/examples/gno.land/r/demo/foo20/foo20_test.gno index 77c99d0525e..91b4a5ede3f 100644 --- a/examples/gno.land/r/demo/foo20/foo20_test.gno +++ b/examples/gno.land/r/demo/foo20/foo20_test.gno @@ -71,10 +71,21 @@ func TestErrConditions(t *testing.T) { fn func() } - std.TestSetOrigCaller(users.Resolve(admin)) + banker.Mint(std.Address(admin), 10000) { tests := []test{ - {"Transfer(admin, 1)", "cannot send transfer to self", func() { Transfer(admin, 1) }}, + {"Transfer(admin, 1)", "cannot send transfer to self", func() { + // XXX: should replace with: + // Transfer(admin, 1) + // but there is currently a limitation in + // manipulating the frame stack and simulate + // calling this package from an outside point of + // view. + adminAddr := std.Address(admin) + if err := banker.Transfer(adminAddr, adminAddr, 1); err != nil { + panic(err) + } + }}, {"Approve(empty, 1))", "invalid address", func() { Approve(empty, 1) }}, } for _, tc := range tests {