-
Notifications
You must be signed in to change notification settings - Fork 383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add grc20reg that works... today #3135
Conversation
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Codecov ReportAll modified and coverable lines are covered by tests ✅ 📢 Thoughts on this report? Let us know! |
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
It seems to work, unless we consider the current behavior a bug that we want to fix. In that case, we can create gno object registries by avoiding the storage of remotely defined objects. Instead, we can store remotely defined functions that dynamically return the remote object when needed. I’m not a big fan of this indirection because I believe Go interfaces are excellent. However, since we fully preserve Go's type safety, I think it’s a good compromise that allows for greater independence between realms. The last checkbox in the original comment raises an open question about how we plan to manage realm deprovisionning in the future. One idea I have that would avoid the need to track which remote realms are storing a locally defined function (remote backref). We could implement a special rule in the VM so that if you:
This would mean we only need to check if the pointer is nil to manage custom error handling, or we could allow the VM to panic due to the missing pointer. |
Did you try to call mutating functions from the calling realm? |
You're right; the atomic swap wasn't tested, and I forgot to remove a "panic not implemented" blocker. However, the test output you shared isn't related to mutation. It's due to reusing the same "sender" and "recipient" addresses in independent tests. In other words, if you run a single unit test with And here a21ddd5 is the commit that removes the panic and adds the missing tests for atomic swap. It works. $> gno test -v ./examples/gno.land/r/demo/atomicswap
=== RUN TestNewCustomCoinSwap_Claim
--- PASS: TestNewCustomCoinSwap_Claim (0.00s)
=== RUN TestNewCustomCoinSwap_Refund
--- PASS: TestNewCustomCoinSwap_Refund (0.00s)
=== RUN TestNewCustomGRC20Swap_Claim
--- PASS: TestNewCustomGRC20Swap_Claim (0.00s)
=== RUN TestNewCustomGRC20Swap_Refund
--- PASS: TestNewCustomGRC20Swap_Refund (0.00s)
=== RUN TestNewGRC20Swap_Claim
--- PASS: TestNewGRC20Swap_Claim (0.00s)
=== RUN TestNewGRC20Swap_Refund
--- PASS: TestNewGRC20Swap_Refund (0.00s)
=== RUN TestRender
--- PASS: TestRender (0.00s)
ok ./examples/gno.land/r/demo/atomicswap 1.44s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks valid to me 👍
// PKGPATH: gno.land/r/crossrealm_test
package crossrealm_test
import (
"std"
crossrealm "gno.land/r/demo/tests/crossrealm"
)
type fooer struct {
v string
}
func (f *fooer) Foo() { println("hello " + f.v + " " + std.CurrentRealm().PkgPath()) }
func (f *fooer) Mutate() {
f.v = "b"
}
var f *fooer
func init() {
f = &fooer{v: "a"} // attach first
}
func main() {
crossrealm.SetFooer(f)
crossrealm.CallFooerFoo()
crossrealm.MutateFooer()
crossrealm.CallFooerFoo()
}
// Output:
// hello a gno.land/r/crossrealm_test
// hello b gno.land/r/crossrealm_test
// 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() {
println("hello " + f.s + " " + std.CurrentRealm().PkgPath())
}
func (f *fooer) Mutate() {}
func init() {
f := &fooer{s: "B"} // XXX, note this is incorrectly attached to "r/demo/crossrealm", by the next line.
fg := func() crossrealm.Fooer { return f }
crossrealm.SetFooerGetter(fg)
crossrealm.CallFooerGetterFoo()
f.s = "C" // XXX, so this cause a panic while modifying external realm obejct
crossrealm.CallFooerGetterFoo()
}
func main() {
print(".")
}
// Error:
// cannot modify external-realm or non-realm object |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
} | ||
|
||
// Error: | ||
// gno.land/r/crossrealm_test/main.gno:19:2: name CallFoo not declared |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error message doesn’t seem intended for this pattern. Consider modifying the code or simply removing the message entirely to eliminate any ambiguity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Signed-off-by: moul <[email protected]>
Signed-off-by: moul <[email protected]>
Not exactly—it's not just for convenience but because the behavior is fundamentally different. With cross-realm objects, we encounter ownership errors due to the constraints of realm isolation. However, by using the Getter pattern to store a pointer to a function (either top-level or lambda), we avoid these ownership issues entirely. This makes the Getter pattern a unique and powerful approach that enables interactions across realms in ways that aren’t possible with direct object storage.
👍 |
Merge RequirementsThe following requirements must be fulfilled before a pull request can be merged. These requirements are defined in this configuration file. Automated Checks🟢 Maintainers must be able to edit this pull request Details
Manual ChecksNo manual checks match this pull request. |
Signed-off-by: moul <[email protected]>
- [x] Switch to storing a `type XXX func() grc20.Token` instead of a `grc20.Token` directly. - [x] Implement `grc20reg`. - [x] Add new tests in `gnovm/tests` to demonstrate the current VM's management of the cross-realm feature and support potential changes in gnolang#2743. - [x] Create a demo in `atomicswap` or a similar application. (gnolang#2510 (comment)) - [x] Try using a `Token.Getter()` helper. (Works! f99654e) - [ ] Demonstrate how to manage "disappearing" functions during garbage collection by checking if the function pointer is nil or non-resolvable. Alternative to gnolang#2516 NOT(!) depending on gnolang#2743 --------- Signed-off-by: moul <[email protected]>
type XXX func() grc20.Token
instead of agrc20.Token
directly.grc20reg
.gnovm/tests
to demonstrate the current VM's management of the cross-realm feature and support potential changes in Gno Realm and Ownership Spec #2743.atomicswap
or a similar application. (feat: add r/demo/atomicswap #2510 (comment))Token.Getter()
helper. (Works! f99654e)Alternative to #2516
NOT(!) depending on #2743