From 12292de1056544d5e1be9d57a9591bf2f6b50e53 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Mon, 3 Apr 2023 19:22:34 +0100 Subject: [PATCH 01/25] feat(stdlibs): add std.GetCaller --- .../p/demo/tests/subtests/subtests.gno | 17 +++ examples/gno.land/p/demo/tests/tests.gno | 19 +++ .../gno.land/r/demo/tests/fake20/fake20.gno | 122 ++++++++++++++++++ .../r/demo/tests/phishing/phishing.gno | 4 + .../r/demo/tests/subtests/subtests.gno | 17 +++ examples/gno.land/r/demo/tests/tests.gno | 30 ++++- .../r/demo/tests/unsaferealm/unsaferealm.gno | 52 ++++++++ .../tests/unsaferealm/unsaferealm_test.gno | 9 ++ gnovm/pkg/gnolang/frame.go | 4 +- gnovm/stdlibs/stdlibs.go | 38 ++++++ gnovm/tests/files/zrealm_crossrealm11.gno | 73 +++++++++++ .../zrealm_crossrealm_exploit1_stdlibs.gno | 60 +++++++++ 12 files changed, 443 insertions(+), 2 deletions(-) create mode 100644 examples/gno.land/p/demo/tests/subtests/subtests.gno create mode 100644 examples/gno.land/r/demo/tests/fake20/fake20.gno create mode 100644 examples/gno.land/r/demo/tests/phishing/phishing.gno create mode 100644 examples/gno.land/r/demo/tests/subtests/subtests.gno create mode 100644 examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno create mode 100644 examples/gno.land/r/demo/tests/unsaferealm/unsaferealm_test.gno create mode 100644 gnovm/tests/files/zrealm_crossrealm11.gno create mode 100644 gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno diff --git a/examples/gno.land/p/demo/tests/subtests/subtests.gno b/examples/gno.land/p/demo/tests/subtests/subtests.gno new file mode 100644 index 00000000000..c85549a7992 --- /dev/null +++ b/examples/gno.land/p/demo/tests/subtests/subtests.gno @@ -0,0 +1,17 @@ +package subtests + +import ( + "std" +) + +func CurrentRealmPath() string { + return std.CurrentRealmPath() +} + +func GetCaller() std.Address { + return std.GetCaller() +} + +func Exec(fn func()) { + fn() +} diff --git a/examples/gno.land/p/demo/tests/tests.gno b/examples/gno.land/p/demo/tests/tests.gno index 858605b88f5..0496a457262 100644 --- a/examples/gno.land/p/demo/tests/tests.gno +++ b/examples/gno.land/p/demo/tests/tests.gno @@ -4,6 +4,7 @@ import ( "std" "gno.land/r/demo/tests" + psubtests "gno.land/p/demo/tests/subtests" ) // IncCounter demonstrates that it's possible to call a realm function from @@ -51,3 +52,21 @@ func ModifyTestRealmObject2b() { func ModifyTestRealmObject2c() { SomeValue3.Field = "modified" } + +func GetCaller() std.Address { + return std.GetCaller() +} + +func GetSubtestsCaller() std.Address { + return psubtests.GetCaller() +} + +func PrintCallers() { + println("p/TEST : ORIGCALL:", std.GetOrigCaller()) + println("p/TEST : PKG ADDR:", std.GetOrigPkgAddr()) + println("p/TEST : CALLER :", std.GetCaller()) +} + +func Exec(fn func()) { + fn() +} diff --git a/examples/gno.land/r/demo/tests/fake20/fake20.gno b/examples/gno.land/r/demo/tests/fake20/fake20.gno new file mode 100644 index 00000000000..493f234bc0f --- /dev/null +++ b/examples/gno.land/r/demo/tests/fake20/fake20.gno @@ -0,0 +1,122 @@ +package fake20 + +import ( + "std" + "strings" + + "gno.land/p/demo/grc/grc20" + "gno.land/p/demo/ufmt" +) + +var ( + foo *grc20.AdminToken + admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // TODO: helper to change admin +) + +func Init() { + foo = grc20.NewAdminToken("Fake", "FAKE", 4) + foo.Mint(admin, 1000000*10000) // @administrator (1M) + foo.Mint("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", 10000*10000) // @manfred (10k) + foo.Mint("g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf", 10000*10000) // @gno.land/r/demo/tests/unsaferealm +} + +func init() { + Init() +} + + +// method proxies as public functions. +// + +// getters. + +func GetCaller() std.Address { + return std.GetCallerAt(1) + // return std.GetOrigPkgAddr() +} + +func TotalSupply() uint64 { + return foo.TotalSupply() +} + +func BalanceOf(owner std.Address) uint64 { + balance, err := foo.BalanceOf(owner) + if err != nil { + panic(err) + } + return balance +} + +func Allowance(owner, spender std.Address) uint64 { + allowance, err := foo.Allowance(owner, spender) + if err != nil { + panic(err) + } + return allowance +} + +// setters. + +func Transfer(to std.Address, amount uint64) { + caller := std.GetCaller() + println("transfering", amount, "from:", caller, "to:", to) + foo.Transfer(caller, to, amount) +} + +func Approve(spender std.Address, amount uint64) { + caller := std.GetCaller() + foo.Approve(caller, spender, amount) +} + +func TransferFrom(from, to std.Address, amount uint64) { + caller := std.GetCaller() + foo.TransferFrom(caller, from, to, amount) +} + +// faucet. + +func Faucet() { + // FIXME: add limits? + // FIXME: add payment in gnot? + caller := std.GetCaller() + foo.Mint(caller, 1000*10000) // 1k +} + +// administration. + +func Mint(address std.Address, amount uint64) { + caller := std.GetCaller() + assertIsAdmin(caller) + foo.Mint(address, amount) +} + +func Burn(address std.Address, amount uint64) { + caller := std.GetCaller() + assertIsAdmin(caller) + foo.Burn(address, amount) +} + +// render. +// + +func Render(path string) string { + parts := strings.Split(path, "/") + c := len(parts) + + switch { + case path == "": + return foo.RenderHome() + case c == 2 && parts[0] == "balance": + owner := std.Address(parts[1]) + balance, _ := foo.BalanceOf(owner) + return ufmt.Sprintf("%d\n", balance) + default: + return "404\n" + } +} + +func assertIsAdmin(address std.Address) { + if address != admin { + panic("restricted access") + } +} diff --git a/examples/gno.land/r/demo/tests/phishing/phishing.gno b/examples/gno.land/r/demo/tests/phishing/phishing.gno new file mode 100644 index 00000000000..d3970459b80 --- /dev/null +++ b/examples/gno.land/r/demo/tests/phishing/phishing.gno @@ -0,0 +1,4 @@ +package phising + +func GetMillionaire() { +} diff --git a/examples/gno.land/r/demo/tests/subtests/subtests.gno b/examples/gno.land/r/demo/tests/subtests/subtests.gno new file mode 100644 index 00000000000..c85549a7992 --- /dev/null +++ b/examples/gno.land/r/demo/tests/subtests/subtests.gno @@ -0,0 +1,17 @@ +package subtests + +import ( + "std" +) + +func CurrentRealmPath() string { + return std.CurrentRealmPath() +} + +func GetCaller() std.Address { + return std.GetCaller() +} + +func Exec(fn func()) { + fn() +} diff --git a/examples/gno.land/r/demo/tests/tests.gno b/examples/gno.land/r/demo/tests/tests.gno index b5ee9c0a301..1bef4c12162 100644 --- a/examples/gno.land/r/demo/tests/tests.gno +++ b/examples/gno.land/r/demo/tests/tests.gno @@ -1,6 +1,10 @@ package tests -import "std" +import ( + "std" + + "gno.land/r/demo/tests/subtests" +) var counter int @@ -69,3 +73,27 @@ func ModTestNodes() { func PrintTestNodes() { println(gTestNode2.Child.Name) } + +func GetCaller() std.Address { + return std.GetCaller() +} + +func GetSubtestsCaller() std.Address { + return subtests.GetCaller() +} + +func ExecFromTest() { + Exec(func() { + println("xxx -> r/demo/tests -> r/demo/tests.Exec:", std.GetCaller()) + }) +} + +func Exec(fn func()) { + fn() +} + +func PrintCallers() { + println("p/TEST : ORIGCALL:", std.GetOrigCaller()) + println("p/TEST : PKG ADDR:", std.GetOrigPkgAddr()) + println("p/TEST : CALLER :", std.GetCaller()) +} diff --git a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno new file mode 100644 index 00000000000..d5c5ef63944 --- /dev/null +++ b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno @@ -0,0 +1,52 @@ +package unsaferealm + +import ( + "std" + + "gno.land/p/demo/grc/grc20" +) + +var ( + foo *grc20.AdminToken + Owner = std.Address("g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf") +) + +func init() { + foo = grc20.NewAdminToken("Fake", "FAKE", 4) + + // std.TestDerivePkgAddr("gno.land/r/demo/tests/unsaferealm") + // foo.Mint("g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf", 1000000*10000) + foo.Mint(Owner, 1000000*10000) + // foo.Mint(std.GetOrigPkgAddr(), 1000000*10000) +} + +/* +** Some grc20 functions + */ + +func GetCaller() std.Address { + return std.GetCallerAt(1) +} + +func BalanceOf(owner std.Address) uint64 { + balance, err := foo.BalanceOf(owner) + if err != nil { + panic(err) + } + + return balance +} + +func Transfer(to std.Address, amount uint64) { + caller := std.GetCaller() + println("transfering", amount, "from:", caller, "to:", to) + foo.Transfer(caller, to, amount) +} + +/* +** Realm unsafe functions + */ + +func Do(fn func()) { + fn() +} diff --git a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm_test.gno b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm_test.gno new file mode 100644 index 00000000000..988dd16c238 --- /dev/null +++ b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm_test.gno @@ -0,0 +1,9 @@ +package unsaferealm + +import ( + "testing" +) + +func TestUnsafeRealm(t *testing.T) { + println("Hello") +} diff --git a/gnovm/pkg/gnolang/frame.go b/gnovm/pkg/gnolang/frame.go index 7e3dc92dd4a..7f87fa26097 100644 --- a/gnovm/pkg/gnolang/frame.go +++ b/gnovm/pkg/gnolang/frame.go @@ -1,6 +1,8 @@ package gnolang -import "fmt" +import ( + "fmt" +) //---------------------------------------- // (runtime) Frame diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 95803558d06..0492f777d3f 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -286,6 +286,44 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { m.PushValue(res0) }, ) + pn.DefineNative("GetCaller", + gno.Flds( // params + ), + gno.Flds( // results + "", "Address", + ), + func(m *gno.Machine) { + ctx := m.Context.(ExecContext) + + lastCaller := ctx.OrigCaller + + if m.NumFrames() <= 2 { + lastCaller = ctx.OrigCaller + } else { + + for i := m.NumFrames() - 1; i > 0; i-- { + frameA := m.Frames[i] + frameB := m.Frames[i-1] + if !frameB.LastPackage.IsRealm() { + continue + } + if !frameA.LastPackage.IsRealm() && !frameB.LastPackage.IsRealm() { + continue + } + lastCaller = frameB.LastPackage.GetPkgAddr().Bech32() + break + } + } + res0 := gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(lastCaller), + ) + addrT := store.GetType(gno.DeclaredTypeID("std", "Address")) + res0.T = addrT + m.PushValue(res0) + }, + ) pn.DefineNative("GetOrigPkgAddr", gno.Flds( // params ), diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno new file mode 100644 index 00000000000..b3a485b9e41 --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -0,0 +1,73 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + "std" + + ptests "gno.land/p/demo/tests" + rtests "gno.land/r/demo/tests" +) + +func Exec(fn func()) { + fn() +} + +func main() { + println(`[DEBUG] + user1.gno: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm + crossrealm_test: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p + gno.land/p/demo/tests: g1lc7c8nv62nqyyhhxe88tpxx786gwq68prx3f6e + gno.land/r/demo/tests: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq + `) + + println("user1.gno -> r/crossrealm_test:", std.GetCaller()) + + println("user1.gno -> r/crossrealm_test -> p/demo/tests:", ptests.GetCaller()) + + println("user1.gno -> r/crossrealm_test -> r/demo/tests:", rtests.GetCaller()) + + println("user1.gno -> r/crossrealm_test -> r/demo/tests -> r/demo/tests/subtests", rtests.GetSubtestsCaller()) + + println("user1.gno -> r/crossrealm_test -> p/demo/tests -> p/demo/tests/subtests", ptests.GetSubtestsCaller()) + + // let's try to exploit an unsafe realm + rtests.Exec(func() { + // caller is `r/demo/tests` + println("user1.gno -> r/crossrealm_test -> r/demo/tests.Exec", std.GetCaller()) + + + // NOTE(WARNING): this one is a weird behaviour, because the caller returned is crossrealm_test + // caller is `crossrealm_test` + println("/!\\ user1.gno -> r/crossrealm_test -> r/demo/tests.Exec -> p/demo/tests:", ptests.GetCaller()) + }) + + ptests.Exec(func() { + println("user1.gno -> r/crossrealm_test -> p/demo/tests.Exec: ", std.GetCaller()) + println("user1.gno -> r/crossrealm_test -> p/demo/tests.Exec -> p/demo/tests:", ptests.GetCaller()) + }) + + rtests.ExecFromTest() + + Exec(func() { + println("user1.gno -> r/crossrealm_test.Exec:", std.GetCaller()) + }) +} + +// Output: +// [DEBUG] +// user1.gno: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// crossrealm_test: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// gno.land/p/demo/tests: g1lc7c8nv62nqyyhhxe88tpxx786gwq68prx3f6e +// gno.land/r/demo/tests: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq +// +// user1.gno -> r/crossrealm_test: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// user1.gno -> r/crossrealm_test -> p/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// user1.gno -> r/crossrealm_test -> r/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// user1.gno -> r/crossrealm_test -> r/demo/tests -> r/demo/tests/subtests g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq +// user1.gno -> r/crossrealm_test -> p/demo/tests -> p/demo/tests/subtests g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// user1.gno -> r/crossrealm_test -> r/demo/tests.Exec g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq +// /!\ user1.gno -> r/crossrealm_test -> r/demo/tests.Exec -> p/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// user1.gno -> r/crossrealm_test -> p/demo/tests.Exec: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// user1.gno -> r/crossrealm_test -> p/demo/tests.Exec -> p/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// xxx -> r/demo/tests -> r/demo/tests.Exec: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq +// user1.gno -> r/crossrealm_test.Exec: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p diff --git a/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno b/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno new file mode 100644 index 00000000000..d2fb8fc7564 --- /dev/null +++ b/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno @@ -0,0 +1,60 @@ +// PKGPATH: gno.land/r/crossrealm_test +package crossrealm_test + +import ( + "std" + + "gno.land/r/demo/tests" + "gno.land/r/demo/tests/unsaferealm" + "gno.land/r/demo/tests/fake20" +) + +func main() { + println("crossrealm caller :", std.GetCaller(), "balance:", unsaferealm.BalanceOf(std.GetCaller())) + println("unsaferealm caller:", unsaferealm.GetCaller(), "balance:", unsaferealm.BalanceOf(unsaferealm.GetCaller())) + println("fake20 caller :", fake20.GetCaller(), "balance:", unsaferealm.BalanceOf(fake20.GetCaller())) + println("======================") + + addr := std.GetCaller() + // println("balance:", unsaferealm.BalanceOf(addr)) + + // Test to exploit from the Do function steal money from unsaferealm treasury + unsaferealm.Do(func() { + println("transfering 1.", std.GetCaller()) + unsaferealm.Transfer(addr, 100000) + }) + + println("balance:", unsaferealm.BalanceOf(addr)) + println("======================") + + // Test to exploit from the Do function steal money from unsaferealm treasury + unsaferealm.Do(func() { + println("transfering 2.", std.GetCaller()) + fake20.Transfer(addr, 100000) + unsaferealm.Do(func() { + fake20.Transfer(addr, 100000) + }) + }) + + println("======================") + println("crossrealm caller :", std.GetCaller(), "balance:", unsaferealm.BalanceOf(std.GetCaller())) + println("unsaferealm caller:", unsaferealm.GetCaller(), "balance:", unsaferealm.BalanceOf(unsaferealm.GetCaller())) + println("fake20 caller :", fake20.GetCaller(), "balance:", unsaferealm.BalanceOf(fake20.GetCaller())) +} + +// Output: +// crossrealm caller : g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm balance: 0 +// unsaferealm caller: g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf balance: 10000000000 +// fake20 caller : g1zjzuzhywuxrk3cdvm7ma33vu4x2xyunxhzslu9 balance: 0 +// ====================== +// transfering 1. g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf +// transfering 100000 from: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p to: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// balance: 0 +// ====================== +// transfering 2. g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf +// transfering 100000 from: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p to: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// transfering 100000 from: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p to: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// ====================== +// crossrealm caller : g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm balance: 0 +// unsaferealm caller: g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf balance: 10000000000 +// fake20 caller : g1zjzuzhywuxrk3cdvm7ma33vu4x2xyunxhzslu9 balance: 0 From 7dbbd9b66d531614054465062db03e92a16bf5af Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Wed, 5 Apr 2023 11:44:17 +0200 Subject: [PATCH 02/25] fix: add GetCaller in stdshim --- gnovm/stdlibs/stdlibs.go | 1 - gnovm/stdlibs/stdshim/stdshim.gno | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 0492f777d3f..9a226cc14ef 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -300,7 +300,6 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { if m.NumFrames() <= 2 { lastCaller = ctx.OrigCaller } else { - for i := m.NumFrames() - 1; i > 0; i-- { frameA := m.Frames[i] frameB := m.Frames[i-1] diff --git a/gnovm/stdlibs/stdshim/stdshim.gno b/gnovm/stdlibs/stdshim/stdshim.gno index 3cea10d572d..b2585d7493b 100644 --- a/gnovm/stdlibs/stdshim/stdshim.gno +++ b/gnovm/stdlibs/stdshim/stdshim.gno @@ -36,6 +36,12 @@ func GetOrigSend() Coins { return Coins{} } +func GetCaller() Address { + panic(shimWarn) + return Address("") +} + + func GetOrigCaller() Address { panic(shimWarn) return Address("") From 4ce2d2fbeaadce7f4bc5200241a52ade10ca6c9e Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Fri, 21 Apr 2023 13:10:48 +0100 Subject: [PATCH 03/25] fix: tests --- gnovm/tests/files/zrealm_tests0.gno | 254 ++++++++++++++++++++++++++-- 1 file changed, 243 insertions(+), 11 deletions(-) diff --git a/gnovm/tests/files/zrealm_tests0.gno b/gnovm/tests/files/zrealm_tests0.gno index 9eaf7fb9a96..8dabbc35d74 100644 --- a/gnovm/tests/files/zrealm_tests0.gno +++ b/gnovm/tests/files/zrealm_tests0.gno @@ -245,7 +245,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "38", +// "Line": "42", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -301,7 +301,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "38", +// "Line": "42", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -523,7 +523,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "7", +// "Line": "11", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -567,7 +567,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "11", +// "Line": "15", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -621,7 +621,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "15", +// "Line": "19", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -665,7 +665,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "19", +// "Line": "23", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -709,7 +709,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "23", +// "Line": "27", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -766,7 +766,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "34", +// "Line": "38", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -813,7 +813,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "56", +// "Line": "60", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -847,7 +847,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "61", +// "Line": "65", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -881,7 +881,239 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "69", +// "Line": "73", +// "Nonce": "0", +// "PkgPath": "gno.land/r/demo/tests" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "std.Address" +// } +// } +// ] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" +// }, +// "FileName": "tests.gno", +// "IsMethod": false, +// "Name": "GetCaller", +// "PkgPath": "gno.land/r/demo/tests", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "File": "tests.gno", +// "Line": "77", +// "Nonce": "0", +// "PkgPath": "gno.land/r/demo/tests" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "std.Address" +// } +// } +// ] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "std.Address" +// } +// } +// ] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" +// }, +// "FileName": "tests.gno", +// "IsMethod": false, +// "Name": "GetSubtestsCaller", +// "PkgPath": "gno.land/r/demo/tests", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "File": "tests.gno", +// "Line": "81", +// "Nonce": "0", +// "PkgPath": "gno.land/r/demo/tests" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [ +// { +// "Embedded": false, +// "Name": "", +// "Tag": "", +// "Type": { +// "@type": "/gno.RefType", +// "ID": "std.Address" +// } +// } +// ] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" +// }, +// "FileName": "tests.gno", +// "IsMethod": false, +// "Name": "ExecFromTest", +// "PkgPath": "gno.land/r/demo/tests", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "File": "tests.gno", +// "Line": "85", +// "Nonce": "0", +// "PkgPath": "gno.land/r/demo/tests" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "fn", +// "Tag": "", +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// ], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" +// }, +// "FileName": "tests.gno", +// "IsMethod": false, +// "Name": "Exec", +// "PkgPath": "gno.land/r/demo/tests", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "File": "tests.gno", +// "Line": "91", +// "Nonce": "0", +// "PkgPath": "gno.land/r/demo/tests" +// } +// }, +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [ +// { +// "Embedded": false, +// "Name": "fn", +// "Tag": "", +// "Type": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// } +// } +// ], +// "Results": [] +// } +// } +// }, +// { +// "T": { +// "@type": "/gno.FuncType", +// "Params": [], +// "Results": [] +// }, +// "V": { +// "@type": "/gno.FuncValue", +// "Closure": { +// "@type": "/gno.RefValue", +// "Escaped": true, +// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" +// }, +// "FileName": "tests.gno", +// "IsMethod": false, +// "Name": "PrintCallers", +// "PkgPath": "gno.land/r/demo/tests", +// "Source": { +// "@type": "/gno.RefNode", +// "BlockNode": null, +// "Location": { +// "File": "tests.gno", +// "Line": "95", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } From 13de845d2073dc1e3ea50262c07d1f67cfb1e822 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Fri, 21 Apr 2023 15:55:40 +0100 Subject: [PATCH 04/25] chore: fix nil --- gnovm/stdlibs/stdlibs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 9a226cc14ef..9d15e3f5237 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -303,7 +303,7 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { for i := m.NumFrames() - 1; i > 0; i-- { frameA := m.Frames[i] frameB := m.Frames[i-1] - if !frameB.LastPackage.IsRealm() { + if frameB.LastPackage == nil || !frameB.LastPackage.IsRealm() { continue } if !frameA.LastPackage.IsRealm() && !frameB.LastPackage.IsRealm() { From 970894effdd1a206e66b22cd53128b28aaf0c83a Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Fri, 21 Apr 2023 18:48:08 +0100 Subject: [PATCH 05/25] chore: change algo --- examples/gno.land/p/demo/tests/tests.gno | 5 ++++ gnovm/stdlibs/stdlibs.go | 35 ++++++++++++++--------- gnovm/tests/files/zrealm_crossrealm11.gno | 16 ++++++----- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/examples/gno.land/p/demo/tests/tests.gno b/examples/gno.land/p/demo/tests/tests.gno index 0496a457262..b99ed2ac4b8 100644 --- a/examples/gno.land/p/demo/tests/tests.gno +++ b/examples/gno.land/p/demo/tests/tests.gno @@ -4,6 +4,7 @@ import ( "std" "gno.land/r/demo/tests" + rtests "gno.land/r/demo/tests" psubtests "gno.land/p/demo/tests/subtests" ) @@ -70,3 +71,7 @@ func PrintCallers() { func Exec(fn func()) { fn() } + +func GetRealmGetCaller() std.Address { + return rtests.GetCaller() +} diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 9d15e3f5237..a5f286229ef 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -297,22 +297,31 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { lastCaller := ctx.OrigCaller - if m.NumFrames() <= 2 { - lastCaller = ctx.OrigCaller - } else { - for i := m.NumFrames() - 1; i > 0; i-- { - frameA := m.Frames[i] - frameB := m.Frames[i-1] - if frameB.LastPackage == nil || !frameB.LastPackage.IsRealm() { - continue - } - if !frameA.LastPackage.IsRealm() && !frameB.LastPackage.IsRealm() { - continue - } - lastCaller = frameB.LastPackage.GetPkgAddr().Bech32() + var currentFrame *gno.Frame = nil + + realms := []crypto.Bech32Address{} + for i := m.NumFrames() - 1; i > 0; i-- { + fr := m.Frames[i] + + if fr.LastPackage == nil || !fr.LastPackage.IsRealm() { + continue + } + if currentFrame == nil { + currentFrame = &fr + } + realms = append(realms, fr.LastPackage.GetPkgAddr().Bech32()) + + if len(realms) > 3 { break } } + + if len(realms) > 1 { + lastCaller = realms[1] + } else { + lastCaller = ctx.OrigCaller + } + res0 := gno.Go2GnoValue( m.Alloc, m.Store, diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno index b3a485b9e41..12c85ada064 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -4,6 +4,7 @@ package crossrealm_test import ( "std" + testfoo "gno.land/r/demo/tests_foo" ptests "gno.land/p/demo/tests" rtests "gno.land/r/demo/tests" ) @@ -30,15 +31,15 @@ func main() { println("user1.gno -> r/crossrealm_test -> p/demo/tests -> p/demo/tests/subtests", ptests.GetSubtestsCaller()) + println("user1.gno -> r/crossrealm_test -> p/demo/tests -> r/demo/tests", ptests.GetRealmGetCaller()) + + // let's try to exploit an unsafe realm rtests.Exec(func() { // caller is `r/demo/tests` println("user1.gno -> r/crossrealm_test -> r/demo/tests.Exec", std.GetCaller()) - - // NOTE(WARNING): this one is a weird behaviour, because the caller returned is crossrealm_test - // caller is `crossrealm_test` - println("/!\\ user1.gno -> r/crossrealm_test -> r/demo/tests.Exec -> p/demo/tests:", ptests.GetCaller()) + println("user1.gno -> r/crossrealm_test -> r/demo/tests.Exec -> p/demo/tests:", ptests.GetCaller()) }) ptests.Exec(func() { @@ -61,12 +62,13 @@ func main() { // gno.land/r/demo/tests: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq // // user1.gno -> r/crossrealm_test: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// user1.gno -> r/crossrealm_test -> p/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// user1.gno -> r/crossrealm_test -> p/demo/tests: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm // user1.gno -> r/crossrealm_test -> r/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p // user1.gno -> r/crossrealm_test -> r/demo/tests -> r/demo/tests/subtests g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq -// user1.gno -> r/crossrealm_test -> p/demo/tests -> p/demo/tests/subtests g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// user1.gno -> r/crossrealm_test -> p/demo/tests -> p/demo/tests/subtests g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// user1.gno -> r/crossrealm_test -> p/demo/tests -> r/demo/tests g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p // user1.gno -> r/crossrealm_test -> r/demo/tests.Exec g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq -// /!\ user1.gno -> r/crossrealm_test -> r/demo/tests.Exec -> p/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// user1.gno -> r/crossrealm_test -> r/demo/tests.Exec -> p/demo/tests: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq // user1.gno -> r/crossrealm_test -> p/demo/tests.Exec: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p // user1.gno -> r/crossrealm_test -> p/demo/tests.Exec -> p/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p // xxx -> r/demo/tests -> r/demo/tests.Exec: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq From 5cf8a7bd7d008729f16cfacf519a6754755d379a Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Mon, 24 Apr 2023 11:04:44 +0100 Subject: [PATCH 06/25] fix: format --- examples/gno.land/p/demo/tests/tests.gno | 2 +- examples/gno.land/r/demo/tests/fake20/fake20.gno | 1 - examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno | 2 +- gnovm/stdlibs/stdshim/stdshim.gno | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/gno.land/p/demo/tests/tests.gno b/examples/gno.land/p/demo/tests/tests.gno index b99ed2ac4b8..59dcbe43df5 100644 --- a/examples/gno.land/p/demo/tests/tests.gno +++ b/examples/gno.land/p/demo/tests/tests.gno @@ -3,9 +3,9 @@ package tests import ( "std" + psubtests "gno.land/p/demo/tests/subtests" "gno.land/r/demo/tests" rtests "gno.land/r/demo/tests" - psubtests "gno.land/p/demo/tests/subtests" ) // IncCounter demonstrates that it's possible to call a realm function from diff --git a/examples/gno.land/r/demo/tests/fake20/fake20.gno b/examples/gno.land/r/demo/tests/fake20/fake20.gno index 493f234bc0f..50d6d641755 100644 --- a/examples/gno.land/r/demo/tests/fake20/fake20.gno +++ b/examples/gno.land/r/demo/tests/fake20/fake20.gno @@ -24,7 +24,6 @@ func init() { Init() } - // method proxies as public functions. // diff --git a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno index d5c5ef63944..730f76d21de 100644 --- a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno +++ b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno @@ -7,7 +7,7 @@ import ( ) var ( - foo *grc20.AdminToken + foo *grc20.AdminToken Owner = std.Address("g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf") ) diff --git a/gnovm/stdlibs/stdshim/stdshim.gno b/gnovm/stdlibs/stdshim/stdshim.gno index b2585d7493b..c047bb2ba93 100644 --- a/gnovm/stdlibs/stdshim/stdshim.gno +++ b/gnovm/stdlibs/stdshim/stdshim.gno @@ -41,7 +41,6 @@ func GetCaller() Address { return Address("") } - func GetOrigCaller() Address { panic(shimWarn) return Address("") From 09a600d9d0d37526938f2850e7ce7802c1146d41 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Mon, 24 Apr 2023 11:05:24 +0100 Subject: [PATCH 07/25] fix: integration test --- misc/docker-integration/integration_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/misc/docker-integration/integration_test.go b/misc/docker-integration/integration_test.go index ac9d5443c3e..f4065f8cf0e 100644 --- a/misc/docker-integration/integration_test.go +++ b/misc/docker-integration/integration_test.go @@ -57,6 +57,17 @@ func runSuite(t *testing.T, tempdir string) { require.True(t, acc.Coins.IsAllGTE(minCoins), "test1 account coins expected at least %s, got %s", minCoins, acc.Coins) + // add gno.land/r/demo/tests/subtests package + dockerExec(t, + `echo 'pass' | gnokey maketx addpkg -insecure-password-stdin \ + -gas-fee 1000000ugnot -gas-wanted 2000000 \ + -broadcast -chainid dev \ + -pkgdir /opt/gno/src/examples/gno.land/r/demo/tests/subtests \ + -pkgpath gno.land/r/demo/tests/subtests \ + -deposit 100000000ugnot \ + test1`, + ) + // add gno.land/r/demo/tests package dockerExec(t, `echo 'pass' | gnokey maketx addpkg -insecure-password-stdin \ From a6f7f6f71a4c5072553bec59de367515a570aff3 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Mon, 24 Apr 2023 11:10:50 +0100 Subject: [PATCH 08/25] chore: cleanup --- examples/gno.land/r/demo/tests/phishing/phishing.gno | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 examples/gno.land/r/demo/tests/phishing/phishing.gno diff --git a/examples/gno.land/r/demo/tests/phishing/phishing.gno b/examples/gno.land/r/demo/tests/phishing/phishing.gno deleted file mode 100644 index d3970459b80..00000000000 --- a/examples/gno.land/r/demo/tests/phishing/phishing.gno +++ /dev/null @@ -1,4 +0,0 @@ -package phising - -func GetMillionaire() { -} From 5d3902162ef0b1882bd96e6e5a20c3834d031012 Mon Sep 17 00:00:00 2001 From: Thomas Bruyelle Date: Mon, 24 Apr 2023 18:37:57 +0200 Subject: [PATCH 09/25] refac GetCaller and test Also: - avoid counting the same realm twice. - remove PrintCallers - remove ExecFromTests already covered in other cases --- examples/gno.land/p/demo/tests/tests.gno | 6 - examples/gno.land/r/demo/tests/tests.gno | 12 -- gnovm/stdlibs/stdlibs.go | 40 ++--- gnovm/tests/files/zrealm_crossrealm11.gno | 189 +++++++++++++++------- gnovm/tests/files/zrealm_tests0.gno | 70 +------- 5 files changed, 154 insertions(+), 163 deletions(-) diff --git a/examples/gno.land/p/demo/tests/tests.gno b/examples/gno.land/p/demo/tests/tests.gno index 59dcbe43df5..dd8be73d787 100644 --- a/examples/gno.land/p/demo/tests/tests.gno +++ b/examples/gno.land/p/demo/tests/tests.gno @@ -62,12 +62,6 @@ func GetSubtestsCaller() std.Address { return psubtests.GetCaller() } -func PrintCallers() { - println("p/TEST : ORIGCALL:", std.GetOrigCaller()) - println("p/TEST : PKG ADDR:", std.GetOrigPkgAddr()) - println("p/TEST : CALLER :", std.GetCaller()) -} - func Exec(fn func()) { fn() } diff --git a/examples/gno.land/r/demo/tests/tests.gno b/examples/gno.land/r/demo/tests/tests.gno index 1bef4c12162..c69ceb583b2 100644 --- a/examples/gno.land/r/demo/tests/tests.gno +++ b/examples/gno.land/r/demo/tests/tests.gno @@ -82,18 +82,6 @@ func GetSubtestsCaller() std.Address { return subtests.GetCaller() } -func ExecFromTest() { - Exec(func() { - println("xxx -> r/demo/tests -> r/demo/tests.Exec:", std.GetCaller()) - }) -} - func Exec(fn func()) { fn() } - -func PrintCallers() { - println("p/TEST : ORIGCALL:", std.GetOrigCaller()) - println("p/TEST : PKG ADDR:", std.GetOrigPkgAddr()) - println("p/TEST : CALLER :", std.GetCaller()) -} diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index a5f286229ef..268b7f56cc0 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -293,35 +293,35 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { "", "Address", ), func(m *gno.Machine) { - ctx := m.Context.(ExecContext) - - lastCaller := ctx.OrigCaller - - var currentFrame *gno.Frame = nil - - realms := []crypto.Bech32Address{} + var ( + ctx = m.Context.(ExecContext) + // Default lastCaller is OrigCaller, the signer of the tx + lastCaller = ctx.OrigCaller + realms = make(map[string]struct{}) + ) + // Loop on the stack frames to determine if there's at least 2 + // different realms in the stack. If yes, the second realm becomes the + // lastCaller. for i := m.NumFrames() - 1; i > 0; i-- { fr := m.Frames[i] - if fr.LastPackage == nil || !fr.LastPackage.IsRealm() { + // Ignore non-realm frame continue } - if currentFrame == nil { - currentFrame = &fr + pkgPath := fr.LastPackage.PkgPath + if _, ok := realms[pkgPath]; ok { + // Ignore realm already added + continue } - realms = append(realms, fr.LastPackage.GetPkgAddr().Bech32()) - - if len(realms) > 3 { + realms[pkgPath] = struct{}{} + if len(realms) > 1 { + // second realm met in the frames, it becomes the lastCaller + lastCaller = fr.LastPackage.GetPkgAddr().Bech32() + // we don't need to iterate further break } } - - if len(realms) > 1 { - lastCaller = realms[1] - } else { - lastCaller = ctx.OrigCaller - } - + // Return the result res0 := gno.Go2GnoValue( m.Alloc, m.Store, diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno index 12c85ada064..8192ca47f2b 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -4,72 +4,149 @@ package crossrealm_test import ( "std" - testfoo "gno.land/r/demo/tests_foo" ptests "gno.land/p/demo/tests" + "gno.land/p/demo/ufmt" rtests "gno.land/r/demo/tests" + testfoo "gno.land/r/demo/tests_foo" ) func Exec(fn func()) { fn() -} +} func main() { - println(`[DEBUG] - user1.gno: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm - crossrealm_test: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p - gno.land/p/demo/tests: g1lc7c8nv62nqyyhhxe88tpxx786gwq68prx3f6e - gno.land/r/demo/tests: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq - `) - - println("user1.gno -> r/crossrealm_test:", std.GetCaller()) - - println("user1.gno -> r/crossrealm_test -> p/demo/tests:", ptests.GetCaller()) - - println("user1.gno -> r/crossrealm_test -> r/demo/tests:", rtests.GetCaller()) - - println("user1.gno -> r/crossrealm_test -> r/demo/tests -> r/demo/tests/subtests", rtests.GetSubtestsCaller()) - - println("user1.gno -> r/crossrealm_test -> p/demo/tests -> p/demo/tests/subtests", ptests.GetSubtestsCaller()) - - println("user1.gno -> r/crossrealm_test -> p/demo/tests -> r/demo/tests", ptests.GetRealmGetCaller()) - - - // let's try to exploit an unsafe realm - rtests.Exec(func() { - // caller is `r/demo/tests` - println("user1.gno -> r/crossrealm_test -> r/demo/tests.Exec", std.GetCaller()) - - println("user1.gno -> r/crossrealm_test -> r/demo/tests.Exec -> p/demo/tests:", ptests.GetCaller()) - }) - - ptests.Exec(func() { - println("user1.gno -> r/crossrealm_test -> p/demo/tests.Exec: ", std.GetCaller()) - println("user1.gno -> r/crossrealm_test -> p/demo/tests.Exec -> p/demo/tests:", ptests.GetCaller()) - }) - - rtests.ExecFromTest() + // Create a map of the potential callers, this will give more understandable + // output than the bech32 addresses. + callersByAddr := make(map[std.Address]string) + for _, caller := range []string{ + "user1.gno", "gno.land/r/crossrealm_test", "gno.land/r/demo/tests", + } { + addr := std.DerivePkgAddr(caller) + callersByAddr[addr] = caller + } + + baseCallStack := "user1.gno -> r/crossrealm_test.main()" + tests := []struct { + callStackAdd string + callerFn func() std.Address + }{ + { + callStackAdd: "", + callerFn: std.GetCaller, + }, + { + callStackAdd: " -> r/crossrealm_test.getCaller()", + callerFn: getCaller, + }, + { + callStackAdd: " -> p/demo/tests", + callerFn: ptests.GetCaller, + }, + { + callStackAdd: " -> p/demo/tests -> p/demo/tests/subtests", + callerFn: ptests.GetSubtestsCaller, + }, + { + callStackAdd: " -> r/demo/tests", + callerFn: rtests.GetCaller, + }, + { + callStackAdd: " -> r/demo/tests -> r/demo/tests/subtests", + callerFn: rtests.GetSubtestsCaller, + }, + { + callStackAdd: " -> p/demo/tests -> r/demo/tests", + callerFn: ptests.GetRealmGetCaller, + }, + } + for i, tt := range tests { + callStack := ufmt.Sprintf("%s%s -> std.GetCaller()", baseCallStack, tt.callStackAdd) + println(ufmt.Sprintf("STACK CASE %d:\n%s", i, callStack)) + println(ufmt.Sprintf("\tcaller is %s", callersByAddr[tt.callerFn()])) + Exec(func() { + println(ufmt.Sprintf("wrapped in r/crossrealm_test.Exec:\n\tcaller is %s", callersByAddr[tt.callerFn()])) + }) + rtests.Exec(func() { + println(ufmt.Sprintf("wrapped in r/demo/tests.Exec:\n\tcaller is %s", callersByAddr[tt.callerFn()])) + }) + ptests.Exec(func() { + println(ufmt.Sprintf("wrapped p/demo/tests.Exec:\n\tcaller is %s", callersByAddr[tt.callerFn()])) + }) + println() + } +} - Exec(func() { - println("user1.gno -> r/crossrealm_test.Exec:", std.GetCaller()) - }) +func getCaller() std.Address { + return std.GetCaller() } // Output: -// [DEBUG] -// user1.gno: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// crossrealm_test: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p -// gno.land/p/demo/tests: g1lc7c8nv62nqyyhhxe88tpxx786gwq68prx3f6e -// gno.land/r/demo/tests: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq +// STACK CASE 0: +// user1.gno -> r/crossrealm_test.main() -> std.GetCaller() +// caller is user1.gno +// wrapped in r/crossrealm_test.Exec: +// caller is user1.gno +// wrapped in r/demo/tests.Exec: +// caller is gno.land/r/demo/tests +// wrapped p/demo/tests.Exec: +// caller is user1.gno +// +// STACK CASE 1: +// user1.gno -> r/crossrealm_test.main() -> r/crossrealm_test.getCaller() -> std.GetCaller() +// caller is user1.gno +// wrapped in r/crossrealm_test.Exec: +// caller is user1.gno +// wrapped in r/demo/tests.Exec: +// caller is gno.land/r/demo/tests +// wrapped p/demo/tests.Exec: +// caller is user1.gno +// +// STACK CASE 2: +// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> std.GetCaller() +// caller is user1.gno +// wrapped in r/crossrealm_test.Exec: +// caller is user1.gno +// wrapped in r/demo/tests.Exec: +// caller is gno.land/r/demo/tests +// wrapped p/demo/tests.Exec: +// caller is user1.gno +// +// STACK CASE 3: +// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> p/demo/tests/subtests -> std.GetCaller() +// caller is user1.gno +// wrapped in r/crossrealm_test.Exec: +// caller is user1.gno +// wrapped in r/demo/tests.Exec: +// caller is gno.land/r/demo/tests +// wrapped p/demo/tests.Exec: +// caller is user1.gno +// +// STACK CASE 4: +// user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> std.GetCaller() +// caller is gno.land/r/crossrealm_test +// wrapped in r/crossrealm_test.Exec: +// caller is gno.land/r/crossrealm_test +// wrapped in r/demo/tests.Exec: +// caller is gno.land/r/crossrealm_test +// wrapped p/demo/tests.Exec: +// caller is gno.land/r/crossrealm_test +// +// STACK CASE 5: +// user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> r/demo/tests/subtests -> std.GetCaller() +// caller is gno.land/r/demo/tests +// wrapped in r/crossrealm_test.Exec: +// caller is gno.land/r/demo/tests +// wrapped in r/demo/tests.Exec: +// caller is gno.land/r/demo/tests +// wrapped p/demo/tests.Exec: +// caller is gno.land/r/demo/tests // -// user1.gno -> r/crossrealm_test: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// user1.gno -> r/crossrealm_test -> p/demo/tests: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// user1.gno -> r/crossrealm_test -> r/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p -// user1.gno -> r/crossrealm_test -> r/demo/tests -> r/demo/tests/subtests g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq -// user1.gno -> r/crossrealm_test -> p/demo/tests -> p/demo/tests/subtests g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// user1.gno -> r/crossrealm_test -> p/demo/tests -> r/demo/tests g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p -// user1.gno -> r/crossrealm_test -> r/demo/tests.Exec g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq -// user1.gno -> r/crossrealm_test -> r/demo/tests.Exec -> p/demo/tests: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq -// user1.gno -> r/crossrealm_test -> p/demo/tests.Exec: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p -// user1.gno -> r/crossrealm_test -> p/demo/tests.Exec -> p/demo/tests: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p -// xxx -> r/demo/tests -> r/demo/tests.Exec: g1gz4ycmx0s6ln2wdrsh4e00l9fsel2wskqa3snq -// user1.gno -> r/crossrealm_test.Exec: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p +// STACK CASE 6: +// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> r/demo/tests -> std.GetCaller() +// caller is gno.land/r/crossrealm_test +// wrapped in r/crossrealm_test.Exec: +// caller is gno.land/r/crossrealm_test +// wrapped in r/demo/tests.Exec: +// caller is gno.land/r/crossrealm_test +// wrapped p/demo/tests.Exec: +// caller is gno.land/r/crossrealm_test diff --git a/gnovm/tests/files/zrealm_tests0.gno b/gnovm/tests/files/zrealm_tests0.gno index 8dabbc35d74..cab0868c4ef 100644 --- a/gnovm/tests/files/zrealm_tests0.gno +++ b/gnovm/tests/files/zrealm_tests0.gno @@ -1004,40 +1004,6 @@ func main() { // { // "T": { // "@type": "/gno.FuncType", -// "Params": [], -// "Results": [] -// }, -// "V": { -// "@type": "/gno.FuncValue", -// "Closure": { -// "@type": "/gno.RefValue", -// "Escaped": true, -// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" -// }, -// "FileName": "tests.gno", -// "IsMethod": false, -// "Name": "ExecFromTest", -// "PkgPath": "gno.land/r/demo/tests", -// "Source": { -// "@type": "/gno.RefNode", -// "BlockNode": null, -// "Location": { -// "File": "tests.gno", -// "Line": "85", -// "Nonce": "0", -// "PkgPath": "gno.land/r/demo/tests" -// } -// }, -// "Type": { -// "@type": "/gno.FuncType", -// "Params": [], -// "Results": [] -// } -// } -// }, -// { -// "T": { -// "@type": "/gno.FuncType", // "Params": [ // { // "Embedded": false, @@ -1068,7 +1034,7 @@ func main() { // "BlockNode": null, // "Location": { // "File": "tests.gno", -// "Line": "91", +// "Line": "85", // "Nonce": "0", // "PkgPath": "gno.land/r/demo/tests" // } @@ -1093,40 +1059,6 @@ func main() { // }, // { // "T": { -// "@type": "/gno.FuncType", -// "Params": [], -// "Results": [] -// }, -// "V": { -// "@type": "/gno.FuncValue", -// "Closure": { -// "@type": "/gno.RefValue", -// "Escaped": true, -// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" -// }, -// "FileName": "tests.gno", -// "IsMethod": false, -// "Name": "PrintCallers", -// "PkgPath": "gno.land/r/demo/tests", -// "Source": { -// "@type": "/gno.RefNode", -// "BlockNode": null, -// "Location": { -// "File": "tests.gno", -// "Line": "95", -// "Nonce": "0", -// "PkgPath": "gno.land/r/demo/tests" -// } -// }, -// "Type": { -// "@type": "/gno.FuncType", -// "Params": [], -// "Results": [] -// } -// } -// }, -// { -// "T": { // "@type": "/gno.SliceType", // "Elt": { // "@type": "/gno.RefType", From 73a41b932d047d5961baed33ace008a8cd96eec4 Mon Sep 17 00:00:00 2001 From: Thomas Bruyelle Date: Tue, 25 Apr 2023 11:55:49 +0200 Subject: [PATCH 10/25] revert difflib usage for an other PR --- gnovm/tests/file.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index 51917633158..451bf0677dc 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -13,13 +13,12 @@ import ( "strconv" "strings" - "github.com/pmezard/go-difflib/difflib" - gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs" "github.com/gnolang/gno/tm2/pkg/crypto" osm "github.com/gnolang/gno/tm2/pkg/os" "github.com/gnolang/gno/tm2/pkg/std" + "github.com/pmezard/go-difflib/difflib" ) type loggerFunc func(args ...interface{}) From e79361ac2ec8674e370bb5ac20c414fd35f2b19a Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Wed, 26 Apr 2023 18:05:57 +0100 Subject: [PATCH 11/25] chore: s/GetCaller/GetRealmCaller --- .../p/demo/tests/subtests/subtests.gno | 4 +- examples/gno.land/p/demo/tests/tests.gno | 10 ++--- .../gno.land/r/demo/tests/fake20/fake20.gno | 14 +++--- .../r/demo/tests/subtests/subtests.gno | 4 +- examples/gno.land/r/demo/tests/tests.gno | 6 +-- .../r/demo/tests/unsaferealm/unsaferealm.gno | 4 +- gnovm/stdlibs/stdlibs.go | 2 +- gnovm/stdlibs/stdshim/stdshim.gno | 2 +- gnovm/tests/files/zrealm_crossrealm11.gno | 44 +++++++++---------- .../zrealm_crossrealm_exploit1_stdlibs.gno | 18 ++++---- 10 files changed, 54 insertions(+), 54 deletions(-) diff --git a/examples/gno.land/p/demo/tests/subtests/subtests.gno b/examples/gno.land/p/demo/tests/subtests/subtests.gno index c85549a7992..5702c96e037 100644 --- a/examples/gno.land/p/demo/tests/subtests/subtests.gno +++ b/examples/gno.land/p/demo/tests/subtests/subtests.gno @@ -8,8 +8,8 @@ func CurrentRealmPath() string { return std.CurrentRealmPath() } -func GetCaller() std.Address { - return std.GetCaller() +func GetRealmCaller() std.Address { + return std.GetRealmCaller() } func Exec(fn func()) { diff --git a/examples/gno.land/p/demo/tests/tests.gno b/examples/gno.land/p/demo/tests/tests.gno index dd8be73d787..5c4cbaf0be8 100644 --- a/examples/gno.land/p/demo/tests/tests.gno +++ b/examples/gno.land/p/demo/tests/tests.gno @@ -54,18 +54,18 @@ func ModifyTestRealmObject2c() { SomeValue3.Field = "modified" } -func GetCaller() std.Address { - return std.GetCaller() +func GetRealmCaller() std.Address { + return std.GetRealmCaller() } func GetSubtestsCaller() std.Address { - return psubtests.GetCaller() + return psubtests.GetRealmCaller() } func Exec(fn func()) { fn() } -func GetRealmGetCaller() std.Address { - return rtests.GetCaller() +func GetRealmGetRealmCaller() std.Address { + return rtests.GetRealmCaller() } diff --git a/examples/gno.land/r/demo/tests/fake20/fake20.gno b/examples/gno.land/r/demo/tests/fake20/fake20.gno index 50d6d641755..34ee192e7db 100644 --- a/examples/gno.land/r/demo/tests/fake20/fake20.gno +++ b/examples/gno.land/r/demo/tests/fake20/fake20.gno @@ -29,7 +29,7 @@ func init() { // getters. -func GetCaller() std.Address { +func GetRealmCaller() std.Address { return std.GetCallerAt(1) // return std.GetOrigPkgAddr() } @@ -57,18 +57,18 @@ func Allowance(owner, spender std.Address) uint64 { // setters. func Transfer(to std.Address, amount uint64) { - caller := std.GetCaller() + caller := std.GetRealmCaller() println("transfering", amount, "from:", caller, "to:", to) foo.Transfer(caller, to, amount) } func Approve(spender std.Address, amount uint64) { - caller := std.GetCaller() + caller := std.GetRealmCaller() foo.Approve(caller, spender, amount) } func TransferFrom(from, to std.Address, amount uint64) { - caller := std.GetCaller() + caller := std.GetRealmCaller() foo.TransferFrom(caller, from, to, amount) } @@ -77,20 +77,20 @@ func TransferFrom(from, to std.Address, amount uint64) { func Faucet() { // FIXME: add limits? // FIXME: add payment in gnot? - caller := std.GetCaller() + caller := std.GetRealmCaller() foo.Mint(caller, 1000*10000) // 1k } // administration. func Mint(address std.Address, amount uint64) { - caller := std.GetCaller() + caller := std.GetRealmCaller() assertIsAdmin(caller) foo.Mint(address, amount) } func Burn(address std.Address, amount uint64) { - caller := std.GetCaller() + caller := std.GetRealmCaller() assertIsAdmin(caller) foo.Burn(address, amount) } diff --git a/examples/gno.land/r/demo/tests/subtests/subtests.gno b/examples/gno.land/r/demo/tests/subtests/subtests.gno index c85549a7992..5702c96e037 100644 --- a/examples/gno.land/r/demo/tests/subtests/subtests.gno +++ b/examples/gno.land/r/demo/tests/subtests/subtests.gno @@ -8,8 +8,8 @@ func CurrentRealmPath() string { return std.CurrentRealmPath() } -func GetCaller() std.Address { - return std.GetCaller() +func GetRealmCaller() std.Address { + return std.GetRealmCaller() } func Exec(fn func()) { diff --git a/examples/gno.land/r/demo/tests/tests.gno b/examples/gno.land/r/demo/tests/tests.gno index c69ceb583b2..d47d5044148 100644 --- a/examples/gno.land/r/demo/tests/tests.gno +++ b/examples/gno.land/r/demo/tests/tests.gno @@ -74,12 +74,12 @@ func PrintTestNodes() { println(gTestNode2.Child.Name) } -func GetCaller() std.Address { - return std.GetCaller() +func GetRealmCaller() std.Address { + return std.GetRealmCaller() } func GetSubtestsCaller() std.Address { - return subtests.GetCaller() + return subtests.GetRealmCaller() } func Exec(fn func()) { diff --git a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno index 730f76d21de..0c904ba3a2f 100644 --- a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno +++ b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno @@ -24,7 +24,7 @@ func init() { ** Some grc20 functions */ -func GetCaller() std.Address { +func GetRealmCaller() std.Address { return std.GetCallerAt(1) } @@ -38,7 +38,7 @@ func BalanceOf(owner std.Address) uint64 { } func Transfer(to std.Address, amount uint64) { - caller := std.GetCaller() + caller := std.GetRealmCaller() println("transfering", amount, "from:", caller, "to:", to) foo.Transfer(caller, to, amount) } diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 268b7f56cc0..83ccdd7deff 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -286,7 +286,7 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { m.PushValue(res0) }, ) - pn.DefineNative("GetCaller", + pn.DefineNative("GetRealmCaller", gno.Flds( // params ), gno.Flds( // results diff --git a/gnovm/stdlibs/stdshim/stdshim.gno b/gnovm/stdlibs/stdshim/stdshim.gno index c047bb2ba93..70bafceb8fa 100644 --- a/gnovm/stdlibs/stdshim/stdshim.gno +++ b/gnovm/stdlibs/stdshim/stdshim.gno @@ -36,7 +36,7 @@ func GetOrigSend() Coins { return Coins{} } -func GetCaller() Address { +func GetRealmCaller() Address { panic(shimWarn) return Address("") } diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno index 8192ca47f2b..4c5b838ae3e 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -10,6 +10,10 @@ import ( testfoo "gno.land/r/demo/tests_foo" ) +func getRealmCaller() std.Address { + return std.GetRealmCaller() +} + func Exec(fn func()) { fn() } @@ -32,15 +36,15 @@ func main() { }{ { callStackAdd: "", - callerFn: std.GetCaller, + callerFn: std.GetRealmCaller, }, { - callStackAdd: " -> r/crossrealm_test.getCaller()", - callerFn: getCaller, + callStackAdd: " -> r/crossrealm_test.getRealmCaller()", + callerFn: getRealmCaller, }, { callStackAdd: " -> p/demo/tests", - callerFn: ptests.GetCaller, + callerFn: ptests.GetRealmCaller, }, { callStackAdd: " -> p/demo/tests -> p/demo/tests/subtests", @@ -48,7 +52,7 @@ func main() { }, { callStackAdd: " -> r/demo/tests", - callerFn: rtests.GetCaller, + callerFn: rtests.GetRealmCaller, }, { callStackAdd: " -> r/demo/tests -> r/demo/tests/subtests", @@ -56,11 +60,11 @@ func main() { }, { callStackAdd: " -> p/demo/tests -> r/demo/tests", - callerFn: ptests.GetRealmGetCaller, + callerFn: ptests.GetRealmCaller, }, } for i, tt := range tests { - callStack := ufmt.Sprintf("%s%s -> std.GetCaller()", baseCallStack, tt.callStackAdd) + callStack := ufmt.Sprintf("%s%s -> std.GetRealmCaller()", baseCallStack, tt.callStackAdd) println(ufmt.Sprintf("STACK CASE %d:\n%s", i, callStack)) println(ufmt.Sprintf("\tcaller is %s", callersByAddr[tt.callerFn()])) Exec(func() { @@ -76,13 +80,9 @@ func main() { } } -func getCaller() std.Address { - return std.GetCaller() -} - // Output: // STACK CASE 0: -// user1.gno -> r/crossrealm_test.main() -> std.GetCaller() +// user1.gno -> r/crossrealm_test.main() -> std.GetRealmCaller() // caller is user1.gno // wrapped in r/crossrealm_test.Exec: // caller is user1.gno @@ -92,7 +92,7 @@ func getCaller() std.Address { // caller is user1.gno // // STACK CASE 1: -// user1.gno -> r/crossrealm_test.main() -> r/crossrealm_test.getCaller() -> std.GetCaller() +// user1.gno -> r/crossrealm_test.main() -> r/crossrealm_test.getRealmCaller() -> std.GetRealmCaller() // caller is user1.gno // wrapped in r/crossrealm_test.Exec: // caller is user1.gno @@ -102,7 +102,7 @@ func getCaller() std.Address { // caller is user1.gno // // STACK CASE 2: -// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> std.GetCaller() +// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> std.GetRealmCaller() // caller is user1.gno // wrapped in r/crossrealm_test.Exec: // caller is user1.gno @@ -112,7 +112,7 @@ func getCaller() std.Address { // caller is user1.gno // // STACK CASE 3: -// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> p/demo/tests/subtests -> std.GetCaller() +// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> p/demo/tests/subtests -> std.GetRealmCaller() // caller is user1.gno // wrapped in r/crossrealm_test.Exec: // caller is user1.gno @@ -122,7 +122,7 @@ func getCaller() std.Address { // caller is user1.gno // // STACK CASE 4: -// user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> std.GetCaller() +// user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> std.GetRealmCaller() // caller is gno.land/r/crossrealm_test // wrapped in r/crossrealm_test.Exec: // caller is gno.land/r/crossrealm_test @@ -132,7 +132,7 @@ func getCaller() std.Address { // caller is gno.land/r/crossrealm_test // // STACK CASE 5: -// user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> r/demo/tests/subtests -> std.GetCaller() +// user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> r/demo/tests/subtests -> std.GetRealmCaller() // caller is gno.land/r/demo/tests // wrapped in r/crossrealm_test.Exec: // caller is gno.land/r/demo/tests @@ -142,11 +142,11 @@ func getCaller() std.Address { // caller is gno.land/r/demo/tests // // STACK CASE 6: -// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> r/demo/tests -> std.GetCaller() -// caller is gno.land/r/crossrealm_test +// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> r/demo/tests -> std.GetRealmCaller() +// caller is user1.gno // wrapped in r/crossrealm_test.Exec: -// caller is gno.land/r/crossrealm_test +// caller is user1.gno // wrapped in r/demo/tests.Exec: -// caller is gno.land/r/crossrealm_test +// caller is gno.land/r/demo/tests // wrapped p/demo/tests.Exec: -// caller is gno.land/r/crossrealm_test +// caller is user1.gno diff --git a/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno b/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno index d2fb8fc7564..06a33435668 100644 --- a/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno +++ b/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno @@ -10,17 +10,17 @@ import ( ) func main() { - println("crossrealm caller :", std.GetCaller(), "balance:", unsaferealm.BalanceOf(std.GetCaller())) - println("unsaferealm caller:", unsaferealm.GetCaller(), "balance:", unsaferealm.BalanceOf(unsaferealm.GetCaller())) - println("fake20 caller :", fake20.GetCaller(), "balance:", unsaferealm.BalanceOf(fake20.GetCaller())) + println("crossrealm caller :", std.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(std.GetRealmCaller())) + println("unsaferealm caller:", unsaferealm.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(unsaferealm.GetRealmCaller())) + println("fake20 caller :", fake20.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(fake20.GetRealmCaller())) println("======================") - addr := std.GetCaller() + addr := std.GetRealmCaller() // println("balance:", unsaferealm.BalanceOf(addr)) // Test to exploit from the Do function steal money from unsaferealm treasury unsaferealm.Do(func() { - println("transfering 1.", std.GetCaller()) + println("transfering 1.", std.GetRealmCaller()) unsaferealm.Transfer(addr, 100000) }) @@ -29,7 +29,7 @@ func main() { // Test to exploit from the Do function steal money from unsaferealm treasury unsaferealm.Do(func() { - println("transfering 2.", std.GetCaller()) + println("transfering 2.", std.GetRealmCaller()) fake20.Transfer(addr, 100000) unsaferealm.Do(func() { fake20.Transfer(addr, 100000) @@ -37,9 +37,9 @@ func main() { }) println("======================") - println("crossrealm caller :", std.GetCaller(), "balance:", unsaferealm.BalanceOf(std.GetCaller())) - println("unsaferealm caller:", unsaferealm.GetCaller(), "balance:", unsaferealm.BalanceOf(unsaferealm.GetCaller())) - println("fake20 caller :", fake20.GetCaller(), "balance:", unsaferealm.BalanceOf(fake20.GetCaller())) + println("crossrealm caller :", std.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(std.GetRealmCaller())) + println("unsaferealm caller:", unsaferealm.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(unsaferealm.GetRealmCaller())) + println("fake20 caller :", fake20.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(fake20.GetRealmCaller())) } // Output: From 770cf3149385a56933e36be02ca3cb0da2cc9c68 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Wed, 26 Apr 2023 18:10:18 +0100 Subject: [PATCH 12/25] fix: zrealm_test0.gno --- gnovm/tests/files/zrealm_tests0.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/tests/files/zrealm_tests0.gno b/gnovm/tests/files/zrealm_tests0.gno index cab0868c4ef..fbb4d0daac9 100644 --- a/gnovm/tests/files/zrealm_tests0.gno +++ b/gnovm/tests/files/zrealm_tests0.gno @@ -918,7 +918,7 @@ func main() { // }, // "FileName": "tests.gno", // "IsMethod": false, -// "Name": "GetCaller", +// "Name": "GetRealmCaller", // "PkgPath": "gno.land/r/demo/tests", // "Source": { // "@type": "/gno.RefNode", From 68e30716794726a1807ab9bc8d864ba74306e925 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Wed, 26 Apr 2023 18:14:01 +0100 Subject: [PATCH 13/25] chore: remove exploit_test --- .../gno.land/r/demo/tests/fake20/fake20.gno | 121 ------------------ .../r/demo/tests/unsaferealm/unsaferealm.gno | 52 -------- .../tests/unsaferealm/unsaferealm_test.gno | 9 -- .../zrealm_crossrealm_exploit1_stdlibs.gno | 60 --------- 4 files changed, 242 deletions(-) delete mode 100644 examples/gno.land/r/demo/tests/fake20/fake20.gno delete mode 100644 examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno delete mode 100644 examples/gno.land/r/demo/tests/unsaferealm/unsaferealm_test.gno delete mode 100644 gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno diff --git a/examples/gno.land/r/demo/tests/fake20/fake20.gno b/examples/gno.land/r/demo/tests/fake20/fake20.gno deleted file mode 100644 index 34ee192e7db..00000000000 --- a/examples/gno.land/r/demo/tests/fake20/fake20.gno +++ /dev/null @@ -1,121 +0,0 @@ -package fake20 - -import ( - "std" - "strings" - - "gno.land/p/demo/grc/grc20" - "gno.land/p/demo/ufmt" -) - -var ( - foo *grc20.AdminToken - admin std.Address = "g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj" // TODO: helper to change admin -) - -func Init() { - foo = grc20.NewAdminToken("Fake", "FAKE", 4) - foo.Mint(admin, 1000000*10000) // @administrator (1M) - foo.Mint("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq", 10000*10000) // @manfred (10k) - foo.Mint("g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf", 10000*10000) // @gno.land/r/demo/tests/unsaferealm -} - -func init() { - Init() -} - -// method proxies as public functions. -// - -// getters. - -func GetRealmCaller() std.Address { - return std.GetCallerAt(1) - // return std.GetOrigPkgAddr() -} - -func TotalSupply() uint64 { - return foo.TotalSupply() -} - -func BalanceOf(owner std.Address) uint64 { - balance, err := foo.BalanceOf(owner) - if err != nil { - panic(err) - } - return balance -} - -func Allowance(owner, spender std.Address) uint64 { - allowance, err := foo.Allowance(owner, spender) - if err != nil { - panic(err) - } - return allowance -} - -// setters. - -func Transfer(to std.Address, amount uint64) { - caller := std.GetRealmCaller() - println("transfering", amount, "from:", caller, "to:", to) - foo.Transfer(caller, to, amount) -} - -func Approve(spender std.Address, amount uint64) { - caller := std.GetRealmCaller() - foo.Approve(caller, spender, amount) -} - -func TransferFrom(from, to std.Address, amount uint64) { - caller := std.GetRealmCaller() - foo.TransferFrom(caller, from, to, amount) -} - -// faucet. - -func Faucet() { - // FIXME: add limits? - // FIXME: add payment in gnot? - caller := std.GetRealmCaller() - foo.Mint(caller, 1000*10000) // 1k -} - -// administration. - -func Mint(address std.Address, amount uint64) { - caller := std.GetRealmCaller() - assertIsAdmin(caller) - foo.Mint(address, amount) -} - -func Burn(address std.Address, amount uint64) { - caller := std.GetRealmCaller() - assertIsAdmin(caller) - foo.Burn(address, amount) -} - -// render. -// - -func Render(path string) string { - parts := strings.Split(path, "/") - c := len(parts) - - switch { - case path == "": - return foo.RenderHome() - case c == 2 && parts[0] == "balance": - owner := std.Address(parts[1]) - balance, _ := foo.BalanceOf(owner) - return ufmt.Sprintf("%d\n", balance) - default: - return "404\n" - } -} - -func assertIsAdmin(address std.Address) { - if address != admin { - panic("restricted access") - } -} diff --git a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno deleted file mode 100644 index 0c904ba3a2f..00000000000 --- a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm.gno +++ /dev/null @@ -1,52 +0,0 @@ -package unsaferealm - -import ( - "std" - - "gno.land/p/demo/grc/grc20" -) - -var ( - foo *grc20.AdminToken - Owner = std.Address("g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf") -) - -func init() { - foo = grc20.NewAdminToken("Fake", "FAKE", 4) - - // std.TestDerivePkgAddr("gno.land/r/demo/tests/unsaferealm") - // foo.Mint("g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf", 1000000*10000) - foo.Mint(Owner, 1000000*10000) - // foo.Mint(std.GetOrigPkgAddr(), 1000000*10000) -} - -/* -** Some grc20 functions - */ - -func GetRealmCaller() std.Address { - return std.GetCallerAt(1) -} - -func BalanceOf(owner std.Address) uint64 { - balance, err := foo.BalanceOf(owner) - if err != nil { - panic(err) - } - - return balance -} - -func Transfer(to std.Address, amount uint64) { - caller := std.GetRealmCaller() - println("transfering", amount, "from:", caller, "to:", to) - foo.Transfer(caller, to, amount) -} - -/* -** Realm unsafe functions - */ - -func Do(fn func()) { - fn() -} diff --git a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm_test.gno b/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm_test.gno deleted file mode 100644 index 988dd16c238..00000000000 --- a/examples/gno.land/r/demo/tests/unsaferealm/unsaferealm_test.gno +++ /dev/null @@ -1,9 +0,0 @@ -package unsaferealm - -import ( - "testing" -) - -func TestUnsafeRealm(t *testing.T) { - println("Hello") -} diff --git a/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno b/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno deleted file mode 100644 index 06a33435668..00000000000 --- a/gnovm/tests/files/zrealm_crossrealm_exploit1_stdlibs.gno +++ /dev/null @@ -1,60 +0,0 @@ -// PKGPATH: gno.land/r/crossrealm_test -package crossrealm_test - -import ( - "std" - - "gno.land/r/demo/tests" - "gno.land/r/demo/tests/unsaferealm" - "gno.land/r/demo/tests/fake20" -) - -func main() { - println("crossrealm caller :", std.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(std.GetRealmCaller())) - println("unsaferealm caller:", unsaferealm.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(unsaferealm.GetRealmCaller())) - println("fake20 caller :", fake20.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(fake20.GetRealmCaller())) - println("======================") - - addr := std.GetRealmCaller() - // println("balance:", unsaferealm.BalanceOf(addr)) - - // Test to exploit from the Do function steal money from unsaferealm treasury - unsaferealm.Do(func() { - println("transfering 1.", std.GetRealmCaller()) - unsaferealm.Transfer(addr, 100000) - }) - - println("balance:", unsaferealm.BalanceOf(addr)) - println("======================") - - // Test to exploit from the Do function steal money from unsaferealm treasury - unsaferealm.Do(func() { - println("transfering 2.", std.GetRealmCaller()) - fake20.Transfer(addr, 100000) - unsaferealm.Do(func() { - fake20.Transfer(addr, 100000) - }) - }) - - println("======================") - println("crossrealm caller :", std.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(std.GetRealmCaller())) - println("unsaferealm caller:", unsaferealm.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(unsaferealm.GetRealmCaller())) - println("fake20 caller :", fake20.GetRealmCaller(), "balance:", unsaferealm.BalanceOf(fake20.GetRealmCaller())) -} - -// Output: -// crossrealm caller : g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm balance: 0 -// unsaferealm caller: g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf balance: 10000000000 -// fake20 caller : g1zjzuzhywuxrk3cdvm7ma33vu4x2xyunxhzslu9 balance: 0 -// ====================== -// transfering 1. g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf -// transfering 100000 from: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p to: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// balance: 0 -// ====================== -// transfering 2. g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf -// transfering 100000 from: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p to: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// transfering 100000 from: g1vla5mffzum6060t99u4xhm8mnhgxr0sz4k574p to: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// ====================== -// crossrealm caller : g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm balance: 0 -// unsaferealm caller: g1lpnflsxpr84dsqkznw85yd5wdzenkj89vsptmf balance: 10000000000 -// fake20 caller : g1zjzuzhywuxrk3cdvm7ma33vu4x2xyunxhzslu9 balance: 0 From cb5ae15934d01242d8daffd9bfbc728916690b4b Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Tue, 9 May 2023 09:58:45 +0100 Subject: [PATCH 14/25] Update gnovm/stdlibs/stdlibs.go Co-authored-by: Antonio Navarro Perez --- gnovm/stdlibs/stdlibs.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 83ccdd7deff..4b941743b71 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -314,12 +314,14 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { continue } realms[pkgPath] = struct{}{} - if len(realms) > 1 { - // second realm met in the frames, it becomes the lastCaller - lastCaller = fr.LastPackage.GetPkgAddr().Bech32() - // we don't need to iterate further - break + if len(realms) <= 1 { + continue } + + // second realm met in the frames, it becomes the lastCaller + lastCaller = fr.LastPackage.GetPkgAddr().Bech32() + // we don't need to iterate further + break } // Return the result res0 := gno.Go2GnoValue( From 98c7b05960227c10bb92ac08df6bef4c90e6e38c Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Tue, 9 May 2023 10:12:25 +0100 Subject: [PATCH 15/25] chore: format --- gnovm/stdlibs/stdlibs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 4b941743b71..03c50a1e54b 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -317,7 +317,7 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { if len(realms) <= 1 { continue } - + // second realm met in the frames, it becomes the lastCaller lastCaller = fr.LastPackage.GetPkgAddr().Bech32() // we don't need to iterate further From 93f82346467776ea02d536a00c9427d5b238e3e2 Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Wed, 24 May 2023 10:11:59 +0200 Subject: [PATCH 16/25] chore: clarify func names Signed-off-by: Manfred Touron <94029+moul@users.noreply.github.com> --- examples/gno.land/p/demo/tests/tests.gno | 11 +++-- examples/gno.land/r/demo/tests/tests.gno | 2 +- gnovm/tests/files/zrealm_crossrealm11.gno | 60 +++++++++++------------ gnovm/tests/files/zrealm_tests0.gno | 2 +- 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/examples/gno.land/p/demo/tests/tests.gno b/examples/gno.land/p/demo/tests/tests.gno index 5c4cbaf0be8..49df6399475 100644 --- a/examples/gno.land/p/demo/tests/tests.gno +++ b/examples/gno.land/p/demo/tests/tests.gno @@ -58,14 +58,15 @@ func GetRealmCaller() std.Address { return std.GetRealmCaller() } -func GetSubtestsCaller() std.Address { +func GetPSubtestsCaller() std.Address { return psubtests.GetRealmCaller() } -func Exec(fn func()) { - fn() +func GetRTestsGetRealmCaller() std.Address { + return rtests.GetRealmCaller() } -func GetRealmGetRealmCaller() std.Address { - return rtests.GetRealmCaller() +// Warning: unsafe pattern. +func Exec(fn func()) { + fn() } diff --git a/examples/gno.land/r/demo/tests/tests.gno b/examples/gno.land/r/demo/tests/tests.gno index d47d5044148..039fcd3ca0d 100644 --- a/examples/gno.land/r/demo/tests/tests.gno +++ b/examples/gno.land/r/demo/tests/tests.gno @@ -78,7 +78,7 @@ func GetRealmCaller() std.Address { return std.GetRealmCaller() } -func GetSubtestsCaller() std.Address { +func GetPSubtestsCaller() std.Address { return subtests.GetRealmCaller() } diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno index 4c5b838ae3e..0aaab35d33b 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -48,7 +48,7 @@ func main() { }, { callStackAdd: " -> p/demo/tests -> p/demo/tests/subtests", - callerFn: ptests.GetSubtestsCaller, + callerFn: ptests.GetPSubtestsCaller, }, { callStackAdd: " -> r/demo/tests", @@ -56,7 +56,7 @@ func main() { }, { callStackAdd: " -> r/demo/tests -> r/demo/tests/subtests", - callerFn: rtests.GetSubtestsCaller, + callerFn: rtests.GetPSubtestsCaller, }, { callStackAdd: " -> p/demo/tests -> r/demo/tests", @@ -83,70 +83,70 @@ func main() { // Output: // STACK CASE 0: // user1.gno -> r/crossrealm_test.main() -> std.GetRealmCaller() -// caller is user1.gno +// caller is user1.gno // wrapped in r/crossrealm_test.Exec: -// caller is user1.gno +// caller is user1.gno // wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests +// caller is gno.land/r/demo/tests // wrapped p/demo/tests.Exec: -// caller is user1.gno +// caller is user1.gno // // STACK CASE 1: // user1.gno -> r/crossrealm_test.main() -> r/crossrealm_test.getRealmCaller() -> std.GetRealmCaller() -// caller is user1.gno +// caller is user1.gno // wrapped in r/crossrealm_test.Exec: -// caller is user1.gno +// caller is user1.gno // wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests +// caller is gno.land/r/demo/tests // wrapped p/demo/tests.Exec: -// caller is user1.gno +// caller is user1.gno // // STACK CASE 2: // user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> std.GetRealmCaller() -// caller is user1.gno +// caller is user1.gno // wrapped in r/crossrealm_test.Exec: -// caller is user1.gno +// caller is user1.gno // wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests +// caller is gno.land/r/demo/tests // wrapped p/demo/tests.Exec: -// caller is user1.gno +// caller is user1.gno // // STACK CASE 3: // user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> p/demo/tests/subtests -> std.GetRealmCaller() -// caller is user1.gno +// caller is user1.gno // wrapped in r/crossrealm_test.Exec: -// caller is user1.gno +// caller is user1.gno // wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests +// caller is gno.land/r/demo/tests // wrapped p/demo/tests.Exec: -// caller is user1.gno +// caller is user1.gno // // STACK CASE 4: // user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> std.GetRealmCaller() -// caller is gno.land/r/crossrealm_test +// caller is gno.land/r/crossrealm_test // wrapped in r/crossrealm_test.Exec: -// caller is gno.land/r/crossrealm_test +// caller is gno.land/r/crossrealm_test // wrapped in r/demo/tests.Exec: -// caller is gno.land/r/crossrealm_test +// caller is gno.land/r/crossrealm_test // wrapped p/demo/tests.Exec: -// caller is gno.land/r/crossrealm_test +// caller is gno.land/r/crossrealm_test // // STACK CASE 5: // user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> r/demo/tests/subtests -> std.GetRealmCaller() -// caller is gno.land/r/demo/tests +// caller is gno.land/r/demo/tests // wrapped in r/crossrealm_test.Exec: -// caller is gno.land/r/demo/tests +// caller is gno.land/r/demo/tests // wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests +// caller is gno.land/r/demo/tests // wrapped p/demo/tests.Exec: -// caller is gno.land/r/demo/tests +// caller is gno.land/r/demo/tests // // STACK CASE 6: // user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> r/demo/tests -> std.GetRealmCaller() -// caller is user1.gno +// caller is user1.gno // wrapped in r/crossrealm_test.Exec: -// caller is user1.gno +// caller is user1.gno // wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests +// caller is gno.land/r/demo/tests // wrapped p/demo/tests.Exec: -// caller is user1.gno +// caller is user1.gno diff --git a/gnovm/tests/files/zrealm_tests0.gno b/gnovm/tests/files/zrealm_tests0.gno index fbb4d0daac9..15f78a8eeb7 100644 --- a/gnovm/tests/files/zrealm_tests0.gno +++ b/gnovm/tests/files/zrealm_tests0.gno @@ -972,7 +972,7 @@ func main() { // }, // "FileName": "tests.gno", // "IsMethod": false, -// "Name": "GetSubtestsCaller", +// "Name": "GetPSubtestsCaller", // "PkgPath": "gno.land/r/demo/tests", // "Source": { // "@type": "/gno.RefNode", From 459db942e58e91f5e3da9e28ccf7d7df5436277b Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Wed, 24 May 2023 11:16:53 +0200 Subject: [PATCH 17/25] chore: refactor tests for increased readability Signed-off-by: Manfred Touron <94029+moul@users.noreply.github.com> --- gnovm/tests/files/zrealm_crossrealm11.gno | 138 ++++++++++------------ 1 file changed, 60 insertions(+), 78 deletions(-) diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno index 0aaab35d33b..7c7e321d89b 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -3,6 +3,7 @@ package crossrealm_test import ( "std" + "strings" ptests "gno.land/p/demo/tests" "gno.land/p/demo/ufmt" @@ -29,7 +30,6 @@ func main() { callersByAddr[addr] = caller } - baseCallStack := "user1.gno -> r/crossrealm_test.main()" tests := []struct { callStackAdd string callerFn func() std.Address @@ -39,7 +39,7 @@ func main() { callerFn: std.GetRealmCaller, }, { - callStackAdd: " -> r/crossrealm_test.getRealmCaller()", + callStackAdd: " -> r/crossrealm_test.getRealmCaller", callerFn: getRealmCaller, }, { @@ -63,90 +63,72 @@ func main() { callerFn: ptests.GetRealmCaller, }, } + + println("---") // needed to have space prefixes + printColumns("STACK", "std.GetRealmCaller") + printColumns("-----", "------------------") + + baseCallStack := "user1.gno -> r/crossrealm_test.main" for i, tt := range tests { - callStack := ufmt.Sprintf("%s%s -> std.GetRealmCaller()", baseCallStack, tt.callStackAdd) - println(ufmt.Sprintf("STACK CASE %d:\n%s", i, callStack)) - println(ufmt.Sprintf("\tcaller is %s", callersByAddr[tt.callerFn()])) + printColumns(baseCallStack+tt.callStackAdd, callersByAddr[tt.callerFn()]) Exec(func() { - println(ufmt.Sprintf("wrapped in r/crossrealm_test.Exec:\n\tcaller is %s", callersByAddr[tt.callerFn()])) + printColumns(baseCallStack+" -> r/crossrealm_test.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn()]) }) rtests.Exec(func() { - println(ufmt.Sprintf("wrapped in r/demo/tests.Exec:\n\tcaller is %s", callersByAddr[tt.callerFn()])) + printColumns(baseCallStack+" -> r/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn()]) }) ptests.Exec(func() { - println(ufmt.Sprintf("wrapped p/demo/tests.Exec:\n\tcaller is %s", callersByAddr[tt.callerFn()])) + printColumns(baseCallStack+" -> p/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn()]) }) - println() } } +func printColumns(left, right string) { + const w = 105 + + output := "" + padding := w - len(left) + + // strings.Repeat is not always available when using various imports modes. + for i := 0; i < padding; i++ { + output += " " + } + + output += left + output += " = " + output += right + println(output) +} + // Output: -// STACK CASE 0: -// user1.gno -> r/crossrealm_test.main() -> std.GetRealmCaller() -// caller is user1.gno -// wrapped in r/crossrealm_test.Exec: -// caller is user1.gno -// wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests -// wrapped p/demo/tests.Exec: -// caller is user1.gno -// -// STACK CASE 1: -// user1.gno -> r/crossrealm_test.main() -> r/crossrealm_test.getRealmCaller() -> std.GetRealmCaller() -// caller is user1.gno -// wrapped in r/crossrealm_test.Exec: -// caller is user1.gno -// wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests -// wrapped p/demo/tests.Exec: -// caller is user1.gno -// -// STACK CASE 2: -// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> std.GetRealmCaller() -// caller is user1.gno -// wrapped in r/crossrealm_test.Exec: -// caller is user1.gno -// wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests -// wrapped p/demo/tests.Exec: -// caller is user1.gno -// -// STACK CASE 3: -// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> p/demo/tests/subtests -> std.GetRealmCaller() -// caller is user1.gno -// wrapped in r/crossrealm_test.Exec: -// caller is user1.gno -// wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests -// wrapped p/demo/tests.Exec: -// caller is user1.gno -// -// STACK CASE 4: -// user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> std.GetRealmCaller() -// caller is gno.land/r/crossrealm_test -// wrapped in r/crossrealm_test.Exec: -// caller is gno.land/r/crossrealm_test -// wrapped in r/demo/tests.Exec: -// caller is gno.land/r/crossrealm_test -// wrapped p/demo/tests.Exec: -// caller is gno.land/r/crossrealm_test -// -// STACK CASE 5: -// user1.gno -> r/crossrealm_test.main() -> r/demo/tests -> r/demo/tests/subtests -> std.GetRealmCaller() -// caller is gno.land/r/demo/tests -// wrapped in r/crossrealm_test.Exec: -// caller is gno.land/r/demo/tests -// wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests -// wrapped p/demo/tests.Exec: -// caller is gno.land/r/demo/tests -// -// STACK CASE 6: -// user1.gno -> r/crossrealm_test.main() -> p/demo/tests -> r/demo/tests -> std.GetRealmCaller() -// caller is user1.gno -// wrapped in r/crossrealm_test.Exec: -// caller is user1.gno -// wrapped in r/demo/tests.Exec: -// caller is gno.land/r/demo/tests -// wrapped p/demo/tests.Exec: -// caller is user1.gno +// --- +// STACK = std.GetRealmCaller +// ----- = ------------------ +// user1.gno -> r/crossrealm_test.main = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.getRealmCaller = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> r/crossrealm_test.getRealmCaller = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> r/crossrealm_test.getRealmCaller = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> r/crossrealm_test.getRealmCaller = user1.gno +// user1.gno -> r/crossrealm_test.main -> p/demo/tests = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> p/demo/tests = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> p/demo/tests = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> p/demo/tests = user1.gno +// user1.gno -> r/crossrealm_test.main -> p/demo/tests -> p/demo/tests/subtests = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> p/demo/tests -> p/demo/tests/subtests = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> p/demo/tests -> p/demo/tests/subtests = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> p/demo/tests -> p/demo/tests/subtests = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/demo/tests = gno.land/r/crossrealm_test +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> r/demo/tests = gno.land/r/crossrealm_test +// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> r/demo/tests = gno.land/r/crossrealm_test +// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> r/demo/tests = gno.land/r/crossrealm_test +// user1.gno -> r/crossrealm_test.main -> r/demo/tests -> r/demo/tests/subtests = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> r/demo/tests -> r/demo/tests/subtests = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> r/demo/tests -> r/demo/tests/subtests = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> r/demo/tests -> r/demo/tests/subtests = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> p/demo/tests -> r/demo/tests = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> p/demo/tests -> r/demo/tests = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> p/demo/tests -> r/demo/tests = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> p/demo/tests -> r/demo/tests = user1.gno From 44f2b7bea903934167afd347df610bc83e5315f1 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Wed, 24 May 2023 10:57:06 +0100 Subject: [PATCH 18/25] fix(tests): wrong call function --- gnovm/tests/files/zrealm_crossrealm11.gno | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno index 7c7e321d89b..6a107042aea 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -60,7 +60,7 @@ func main() { }, { callStackAdd: " -> p/demo/tests -> r/demo/tests", - callerFn: ptests.GetRealmCaller, + callerFn: ptests.GetRTestsGetRealmCaller, }, } @@ -128,7 +128,7 @@ func printColumns(left, right string) { // user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> r/demo/tests -> r/demo/tests/subtests = gno.land/r/demo/tests // user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> r/demo/tests -> r/demo/tests/subtests = gno.land/r/demo/tests // user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> r/demo/tests -> r/demo/tests/subtests = gno.land/r/demo/tests -// user1.gno -> r/crossrealm_test.main -> p/demo/tests -> r/demo/tests = user1.gno -// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> p/demo/tests -> r/demo/tests = user1.gno -// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> p/demo/tests -> r/demo/tests = gno.land/r/demo/tests -// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> p/demo/tests -> r/demo/tests = user1.gno +// user1.gno -> r/crossrealm_test.main -> p/demo/tests -> r/demo/tests = gno.land/r/crossrealm_test +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> p/demo/tests -> r/demo/tests = gno.land/r/crossrealm_test +// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> p/demo/tests -> r/demo/tests = gno.land/r/crossrealm_test +// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> p/demo/tests -> r/demo/tests = gno.land/r/crossrealm_test From d0dc76e750c0a4a73761f6a90a70904a66f40fd8 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Thu, 25 May 2023 10:14:09 +0100 Subject: [PATCH 19/25] fix: use a string rather than a map --- gnovm/stdlibs/stdlibs.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 03c50a1e54b..7a2c5ef84a6 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -296,12 +296,10 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { var ( ctx = m.Context.(ExecContext) // Default lastCaller is OrigCaller, the signer of the tx - lastCaller = ctx.OrigCaller - realms = make(map[string]struct{}) + lastCaller = ctx.OrigCaller + lastPkgPath = "" ) - // Loop on the stack frames to determine if there's at least 2 - // different realms in the stack. If yes, the second realm becomes the - // lastCaller. + for i := m.NumFrames() - 1; i > 0; i-- { fr := m.Frames[i] if fr.LastPackage == nil || !fr.LastPackage.IsRealm() { @@ -309,12 +307,9 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { continue } pkgPath := fr.LastPackage.PkgPath - if _, ok := realms[pkgPath]; ok { - // Ignore realm already added - continue - } - realms[pkgPath] = struct{}{} - if len(realms) <= 1 { + if lastPkgPath == "" || lastPkgPath == pkgPath { + // Ignore first realm met + lastPkgPath = pkgPath continue } @@ -323,6 +318,7 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { // we don't need to iterate further break } + // Return the result res0 := gno.Go2GnoValue( m.Alloc, From 229545a0c97dd57a047c2c800750af064384f6f5 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Thu, 25 May 2023 16:06:15 +0100 Subject: [PATCH 20/25] chore: rename to PrevRealm --- .../p/demo/tests/subtests/subtests.gno | 4 +- examples/gno.land/p/demo/tests/tests.gno | 12 +++--- .../r/demo/tests/subtests/subtests.gno | 4 +- examples/gno.land/r/demo/tests/tests.gno | 8 ++-- gnovm/stdlibs/frame.go | 8 ++++ gnovm/stdlibs/std/frame.gno | 10 +++++ gnovm/stdlibs/stdlibs.go | 16 ++++--- gnovm/stdlibs/stdshim/frame.gno | 6 +++ gnovm/stdlibs/stdshim/stdshim.gno | 7 ++- gnovm/tests/files/zrealm_crossrealm11.gno | 43 ++++++++++--------- gnovm/tests/files/zrealm_tests0.gno | 12 +++--- 11 files changed, 82 insertions(+), 48 deletions(-) create mode 100644 gnovm/stdlibs/frame.go create mode 100644 gnovm/stdlibs/std/frame.gno create mode 100644 gnovm/stdlibs/stdshim/frame.gno diff --git a/examples/gno.land/p/demo/tests/subtests/subtests.gno b/examples/gno.land/p/demo/tests/subtests/subtests.gno index 5702c96e037..cdff70380ec 100644 --- a/examples/gno.land/p/demo/tests/subtests/subtests.gno +++ b/examples/gno.land/p/demo/tests/subtests/subtests.gno @@ -8,8 +8,8 @@ func CurrentRealmPath() string { return std.CurrentRealmPath() } -func GetRealmCaller() std.Address { - return std.GetRealmCaller() +func GetPrevRealm() std.Realm { + return std.PrevRealm() } func Exec(fn func()) { diff --git a/examples/gno.land/p/demo/tests/tests.gno b/examples/gno.land/p/demo/tests/tests.gno index 49df6399475..f0e4173f313 100644 --- a/examples/gno.land/p/demo/tests/tests.gno +++ b/examples/gno.land/p/demo/tests/tests.gno @@ -54,16 +54,16 @@ func ModifyTestRealmObject2c() { SomeValue3.Field = "modified" } -func GetRealmCaller() std.Address { - return std.GetRealmCaller() +func GetPrevRealm() std.Realm { + return std.PrevRealm() } -func GetPSubtestsCaller() std.Address { - return psubtests.GetRealmCaller() +func GetPSubtestsPrevRealm() std.Realm { + return psubtests.GetPrevRealm() } -func GetRTestsGetRealmCaller() std.Address { - return rtests.GetRealmCaller() +func GetRTestsGetPrevRealm() std.Realm { + return rtests.GetPrevRealm() } // Warning: unsafe pattern. diff --git a/examples/gno.land/r/demo/tests/subtests/subtests.gno b/examples/gno.land/r/demo/tests/subtests/subtests.gno index 5702c96e037..cdff70380ec 100644 --- a/examples/gno.land/r/demo/tests/subtests/subtests.gno +++ b/examples/gno.land/r/demo/tests/subtests/subtests.gno @@ -8,8 +8,8 @@ func CurrentRealmPath() string { return std.CurrentRealmPath() } -func GetRealmCaller() std.Address { - return std.GetRealmCaller() +func GetPrevRealm() std.Realm { + return std.PrevRealm() } func Exec(fn func()) { diff --git a/examples/gno.land/r/demo/tests/tests.gno b/examples/gno.land/r/demo/tests/tests.gno index 039fcd3ca0d..dd2518e2e49 100644 --- a/examples/gno.land/r/demo/tests/tests.gno +++ b/examples/gno.land/r/demo/tests/tests.gno @@ -74,12 +74,12 @@ func PrintTestNodes() { println(gTestNode2.Child.Name) } -func GetRealmCaller() std.Address { - return std.GetRealmCaller() +func GetPrevRealm() std.Realm { + return std.PrevRealm() } -func GetPSubtestsCaller() std.Address { - return subtests.GetRealmCaller() +func GetPSubtestsPrevRealm() std.Realm { + return subtests.GetPrevRealm() } func Exec(fn func()) { diff --git a/gnovm/stdlibs/frame.go b/gnovm/stdlibs/frame.go new file mode 100644 index 00000000000..e39a034953d --- /dev/null +++ b/gnovm/stdlibs/frame.go @@ -0,0 +1,8 @@ +package stdlibs + +import "github.com/gnolang/gno/tm2/pkg/crypto" + +type Realm struct { + Addr crypto.Bech32Address + PkgPath string +} diff --git a/gnovm/stdlibs/std/frame.gno b/gnovm/stdlibs/std/frame.gno new file mode 100644 index 00000000000..555402c4a21 --- /dev/null +++ b/gnovm/stdlibs/std/frame.gno @@ -0,0 +1,10 @@ +package std + +type Realm struct { + Addr Address + PkgPath string +} + +// func (r Realm) IsUser() bool { +// return r.Addr == GetOrigCaller() +// } diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 7a2c5ef84a6..66456712683 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -17,6 +17,7 @@ func InjectNativeMappings(store gno.Store) { store.AddGo2GnoMapping(reflect.TypeOf(crypto.Bech32Address("")), "std", "Address") store.AddGo2GnoMapping(reflect.TypeOf(std.Coins{}), "std", "Coins") store.AddGo2GnoMapping(reflect.TypeOf(std.Coin{}), "std", "Coin") + store.AddGo2GnoMapping(reflect.TypeOf(Realm{}), "std", "Realm") } func InjectPackage(store gno.Store, pn *gno.PackageNode) { @@ -286,11 +287,11 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { m.PushValue(res0) }, ) - pn.DefineNative("GetRealmCaller", + pn.DefineNative("PrevRealm", gno.Flds( // params ), gno.Flds( // results - "", "Address", + "", "Realm", ), func(m *gno.Machine) { var ( @@ -315,6 +316,7 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { // second realm met in the frames, it becomes the lastCaller lastCaller = fr.LastPackage.GetPkgAddr().Bech32() + lastPkgPath = pkgPath // we don't need to iterate further break } @@ -323,10 +325,14 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { res0 := gno.Go2GnoValue( m.Alloc, m.Store, - reflect.ValueOf(lastCaller), + reflect.ValueOf(Realm{ + lastCaller, + lastPkgPath, + }), ) - addrT := store.GetType(gno.DeclaredTypeID("std", "Address")) - res0.T = addrT + + realmT := store.GetType(gno.DeclaredTypeID("std", "Realm")) + res0.T = realmT m.PushValue(res0) }, ) diff --git a/gnovm/stdlibs/stdshim/frame.gno b/gnovm/stdlibs/stdshim/frame.gno new file mode 100644 index 00000000000..e31a1e69fd1 --- /dev/null +++ b/gnovm/stdlibs/stdshim/frame.gno @@ -0,0 +1,6 @@ +package std + +type Realm struct { + Addr Address + PkgPath string +} diff --git a/gnovm/stdlibs/stdshim/stdshim.gno b/gnovm/stdlibs/stdshim/stdshim.gno index 70bafceb8fa..71484972fe3 100644 --- a/gnovm/stdlibs/stdshim/stdshim.gno +++ b/gnovm/stdlibs/stdshim/stdshim.gno @@ -36,9 +36,12 @@ func GetOrigSend() Coins { return Coins{} } -func GetRealmCaller() Address { +func PrevRealm() Realm { panic(shimWarn) - return Address("") + return Realm{ + Addr: Address(""), + PkgPath: "", + } } func GetOrigCaller() Address { diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno index 6a107042aea..5bb6834ba90 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -4,6 +4,7 @@ package crossrealm_test import ( "std" "strings" + "fmt" ptests "gno.land/p/demo/tests" "gno.land/p/demo/ufmt" @@ -11,8 +12,8 @@ import ( testfoo "gno.land/r/demo/tests_foo" ) -func getRealmCaller() std.Address { - return std.GetRealmCaller() +func getPrevRealm() std.Realm { + return std.PrevRealm() } func Exec(fn func()) { @@ -32,53 +33,53 @@ func main() { tests := []struct { callStackAdd string - callerFn func() std.Address + callerFn func() std.Realm }{ { callStackAdd: "", - callerFn: std.GetRealmCaller, + callerFn: std.PrevRealm, }, { - callStackAdd: " -> r/crossrealm_test.getRealmCaller", - callerFn: getRealmCaller, + callStackAdd: " -> r/crossrealm_test.getPrevRealm", + callerFn: getPrevRealm, }, { callStackAdd: " -> p/demo/tests", - callerFn: ptests.GetRealmCaller, + callerFn: ptests.GetPrevRealm, }, { callStackAdd: " -> p/demo/tests -> p/demo/tests/subtests", - callerFn: ptests.GetPSubtestsCaller, + callerFn: ptests.GetPSubtestsPrevRealm, }, { callStackAdd: " -> r/demo/tests", - callerFn: rtests.GetRealmCaller, + callerFn: rtests.GetPrevRealm, }, { callStackAdd: " -> r/demo/tests -> r/demo/tests/subtests", - callerFn: rtests.GetPSubtestsCaller, + callerFn: rtests.GetPSubtestsPrevRealm, }, { callStackAdd: " -> p/demo/tests -> r/demo/tests", - callerFn: ptests.GetRTestsGetRealmCaller, + callerFn: ptests.GetRTestsGetPrevRealm, }, } println("---") // needed to have space prefixes - printColumns("STACK", "std.GetRealmCaller") + printColumns("STACK", "std.PrevRealm") printColumns("-----", "------------------") baseCallStack := "user1.gno -> r/crossrealm_test.main" for i, tt := range tests { - printColumns(baseCallStack+tt.callStackAdd, callersByAddr[tt.callerFn()]) + printColumns(baseCallStack+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) Exec(func() { - printColumns(baseCallStack+" -> r/crossrealm_test.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn()]) + printColumns(baseCallStack+" -> r/crossrealm_test.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) }) rtests.Exec(func() { - printColumns(baseCallStack+" -> r/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn()]) + printColumns(baseCallStack+" -> r/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) }) ptests.Exec(func() { - printColumns(baseCallStack+" -> p/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn()]) + printColumns(baseCallStack+" -> p/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) }) } } @@ -102,16 +103,16 @@ func printColumns(left, right string) { // Output: // --- -// STACK = std.GetRealmCaller +// STACK = std.PrevRealm // ----- = ------------------ // user1.gno -> r/crossrealm_test.main = user1.gno // user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec = user1.gno // user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec = gno.land/r/demo/tests // user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec = user1.gno -// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.getRealmCaller = user1.gno -// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> r/crossrealm_test.getRealmCaller = user1.gno -// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> r/crossrealm_test.getRealmCaller = gno.land/r/demo/tests -// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> r/crossrealm_test.getRealmCaller = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.getPrevRealm = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> r/crossrealm_test.getPrevRealm = user1.gno +// user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> r/crossrealm_test.getPrevRealm = gno.land/r/demo/tests +// user1.gno -> r/crossrealm_test.main -> p/demo/tests.Exec -> r/crossrealm_test.getPrevRealm = user1.gno // user1.gno -> r/crossrealm_test.main -> p/demo/tests = user1.gno // user1.gno -> r/crossrealm_test.main -> r/crossrealm_test.Exec -> p/demo/tests = user1.gno // user1.gno -> r/crossrealm_test.main -> r/demo/tests.Exec -> p/demo/tests = gno.land/r/demo/tests diff --git a/gnovm/tests/files/zrealm_tests0.gno b/gnovm/tests/files/zrealm_tests0.gno index 15f78a8eeb7..bc07acea1b4 100644 --- a/gnovm/tests/files/zrealm_tests0.gno +++ b/gnovm/tests/files/zrealm_tests0.gno @@ -904,7 +904,7 @@ func main() { // "Tag": "", // "Type": { // "@type": "/gno.RefType", -// "ID": "std.Address" +// "ID": "std.Realm" // } // } // ] @@ -918,7 +918,7 @@ func main() { // }, // "FileName": "tests.gno", // "IsMethod": false, -// "Name": "GetRealmCaller", +// "Name": "GetPrevRealm", // "PkgPath": "gno.land/r/demo/tests", // "Source": { // "@type": "/gno.RefNode", @@ -940,7 +940,7 @@ func main() { // "Tag": "", // "Type": { // "@type": "/gno.RefType", -// "ID": "std.Address" +// "ID": "std.Realm" // } // } // ] @@ -958,7 +958,7 @@ func main() { // "Tag": "", // "Type": { // "@type": "/gno.RefType", -// "ID": "std.Address" +// "ID": "std.Realm" // } // } // ] @@ -972,7 +972,7 @@ func main() { // }, // "FileName": "tests.gno", // "IsMethod": false, -// "Name": "GetPSubtestsCaller", +// "Name": "GetPSubtestsPrevRealm", // "PkgPath": "gno.land/r/demo/tests", // "Source": { // "@type": "/gno.RefNode", @@ -994,7 +994,7 @@ func main() { // "Tag": "", // "Type": { // "@type": "/gno.RefType", -// "ID": "std.Address" +// "ID": "std.Realm" // } // } // ] From eb456c99fcd5f7ce0bad31b46bb77cd257f00eff Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Fri, 26 May 2023 11:03:00 +0100 Subject: [PATCH 21/25] chore: update tests --- gnovm/stdlibs/std/frame.gno | 6 +++--- gnovm/stdlibs/stdlibs.go | 18 +++++++++++------- gnovm/tests/files/zrealm_crossrealm11.gno | 18 ++++++++++++++++-- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/gnovm/stdlibs/std/frame.gno b/gnovm/stdlibs/std/frame.gno index 555402c4a21..c521af449ee 100644 --- a/gnovm/stdlibs/std/frame.gno +++ b/gnovm/stdlibs/std/frame.gno @@ -5,6 +5,6 @@ type Realm struct { PkgPath string } -// func (r Realm) IsUser() bool { -// return r.Addr == GetOrigCaller() -// } +func (r Realm) IsUser() bool { + return r.PkgPath == "" +} diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 66456712683..20f9a0b27cb 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -308,17 +308,21 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { continue } pkgPath := fr.LastPackage.PkgPath - if lastPkgPath == "" || lastPkgPath == pkgPath { - // Ignore first realm met + // The first realm we encounter will be the one calling + // this function; to get the calling realm determine the first frame + // where fr.LastPackage changes. + if lastPkgPath != "" && lastPkgPath != pkgPath { + lastCaller = fr.LastPackage.GetPkgAddr().Bech32() lastPkgPath = pkgPath - continue + break } - // second realm met in the frames, it becomes the lastCaller - lastCaller = fr.LastPackage.GetPkgAddr().Bech32() lastPkgPath = pkgPath - // we don't need to iterate further - break + } + + // Empty the pkgPath if we return a user + if ctx.OrigCaller == lastCaller { + lastPkgPath = "" } // Return the result diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno index 5bb6834ba90..bf2ac7e3a1f 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -4,7 +4,6 @@ package crossrealm_test import ( "std" "strings" - "fmt" ptests "gno.land/p/demo/tests" "gno.land/p/demo/ufmt" @@ -31,6 +30,15 @@ func main() { callersByAddr[addr] = caller } + assertRealm := func(r std.Realm) { + pkgPath := callersByAddr[r.Addr] + if r.IsUser() && pkgPath != "user1.gno" { + panic(ufmt.Sprintf("ERROR: expected: 'user1.gno', got:'%s'", pkgPath)) + } else if !r.IsUser() && pkgPath != r.PkgPath { + panic(ufmt.Sprintf("ERROR: expected: '%s', got: '%s'", pkgPath, r.PkgPath)) + } + } + tests := []struct { callStackAdd string callerFn func() std.Realm @@ -73,12 +81,18 @@ func main() { for i, tt := range tests { printColumns(baseCallStack+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) Exec(func() { - printColumns(baseCallStack+" -> r/crossrealm_test.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) + r := tt.callerFn() + assertRealm(r) + printColumns(baseCallStack+" -> r/crossrealm_test.Exec"+tt.callStackAdd, callersByAddr[r.Addr]) }) rtests.Exec(func() { + r := tt.callerFn() + assertRealm(r) printColumns(baseCallStack+" -> r/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) }) ptests.Exec(func() { + r := tt.callerFn() + assertRealm(r) printColumns(baseCallStack+" -> p/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) }) } From f8ac5020efd87dce532527fbdb66bdc2b80d488c Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Fri, 26 May 2023 17:35:31 +0100 Subject: [PATCH 22/25] chore: add IsUser on frame.go --- gnovm/stdlibs/frame.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gnovm/stdlibs/frame.go b/gnovm/stdlibs/frame.go index e39a034953d..2b7045ea547 100644 --- a/gnovm/stdlibs/frame.go +++ b/gnovm/stdlibs/frame.go @@ -6,3 +6,7 @@ type Realm struct { Addr crypto.Bech32Address PkgPath string } + +func (r Realm) IsUser() bool { + return r.PkgPath == "" +} From 505a5c66f8c12fbbf05ff6154302e334d75498e2 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Sat, 3 Jun 2023 09:46:52 +0100 Subject: [PATCH 23/25] chore: update condition to if-else for readability --- gnovm/stdlibs/stdlibs.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index 9e792adac75..b67a2cd5b77 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -287,13 +287,15 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { // The first realm we encounter will be the one calling // this function; to get the calling realm determine the first frame // where fr.LastPackage changes. - if lastPkgPath != "" && lastPkgPath != pkgPath { + if lastPkgPath == "" { + lastPkgPath = pkgPath + } else if lastPkgPath == pkgPath { + continue + } else { lastCaller = fr.LastPackage.GetPkgAddr().Bech32() lastPkgPath = pkgPath break } - - lastPkgPath = pkgPath } // Empty the pkgPath if we return a user From bb0d5533541345abeda98cac4be13b321bf7f865 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Tue, 6 Jun 2023 16:17:29 +0100 Subject: [PATCH 24/25] chore: export Addr et PkgPath as methods --- gnovm/stdlibs/frame.go | 14 +++++++++++--- gnovm/stdlibs/std/frame.gno | 14 +++++++++++--- gnovm/stdlibs/stdlibs.go | 4 ++-- gnovm/stdlibs/stdshim/frame.gno | 16 ++++++++++++++-- gnovm/tests/files/zrealm_crossrealm11.gno | 14 +++++++------- 5 files changed, 45 insertions(+), 17 deletions(-) diff --git a/gnovm/stdlibs/frame.go b/gnovm/stdlibs/frame.go index 2b7045ea547..e428bb1776d 100644 --- a/gnovm/stdlibs/frame.go +++ b/gnovm/stdlibs/frame.go @@ -3,10 +3,18 @@ package stdlibs import "github.com/gnolang/gno/tm2/pkg/crypto" type Realm struct { - Addr crypto.Bech32Address - PkgPath string + addr crypto.Bech32Address + pkgPath string +} + +func (r Realm) Addr() crypto.Bech32Address { + return r.addr +} + +func (r Realm) PkgPath() string { + return r.pkgPath } func (r Realm) IsUser() bool { - return r.PkgPath == "" + return r.pkgPath == "" } diff --git a/gnovm/stdlibs/std/frame.gno b/gnovm/stdlibs/std/frame.gno index c521af449ee..bc3a000f5a0 100644 --- a/gnovm/stdlibs/std/frame.gno +++ b/gnovm/stdlibs/std/frame.gno @@ -1,10 +1,18 @@ package std type Realm struct { - Addr Address - PkgPath string + addr Address + pkgPath string +} + +func (r Realm) Addr() Address { + return r.addr +} + +func (r Realm) PkgPath() string { + return r.pkgPath } func (r Realm) IsUser() bool { - return r.PkgPath == "" + return r.pkgPath == "" } diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go index b67a2cd5b77..9ac790c2b4e 100644 --- a/gnovm/stdlibs/stdlibs.go +++ b/gnovm/stdlibs/stdlibs.go @@ -308,8 +308,8 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { m.Alloc, m.Store, reflect.ValueOf(Realm{ - lastCaller, - lastPkgPath, + addr: lastCaller, + pkgPath: lastPkgPath, }), ) diff --git a/gnovm/stdlibs/stdshim/frame.gno b/gnovm/stdlibs/stdshim/frame.gno index e31a1e69fd1..bc3a000f5a0 100644 --- a/gnovm/stdlibs/stdshim/frame.gno +++ b/gnovm/stdlibs/stdshim/frame.gno @@ -1,6 +1,18 @@ package std type Realm struct { - Addr Address - PkgPath string + addr Address + pkgPath string +} + +func (r Realm) Addr() Address { + return r.addr +} + +func (r Realm) PkgPath() string { + return r.pkgPath +} + +func (r Realm) IsUser() bool { + return r.pkgPath == "" } diff --git a/gnovm/tests/files/zrealm_crossrealm11.gno b/gnovm/tests/files/zrealm_crossrealm11.gno index bf2ac7e3a1f..ecb3555c29c 100644 --- a/gnovm/tests/files/zrealm_crossrealm11.gno +++ b/gnovm/tests/files/zrealm_crossrealm11.gno @@ -31,11 +31,11 @@ func main() { } assertRealm := func(r std.Realm) { - pkgPath := callersByAddr[r.Addr] + pkgPath := callersByAddr[r.Addr()] if r.IsUser() && pkgPath != "user1.gno" { panic(ufmt.Sprintf("ERROR: expected: 'user1.gno', got:'%s'", pkgPath)) - } else if !r.IsUser() && pkgPath != r.PkgPath { - panic(ufmt.Sprintf("ERROR: expected: '%s', got: '%s'", pkgPath, r.PkgPath)) + } else if !r.IsUser() && pkgPath != r.PkgPath() { + panic(ufmt.Sprintf("ERROR: expected: '%s', got: '%s'", pkgPath, r.PkgPath())) } } @@ -79,21 +79,21 @@ func main() { baseCallStack := "user1.gno -> r/crossrealm_test.main" for i, tt := range tests { - printColumns(baseCallStack+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) + printColumns(baseCallStack+tt.callStackAdd, callersByAddr[tt.callerFn().Addr()]) Exec(func() { r := tt.callerFn() assertRealm(r) - printColumns(baseCallStack+" -> r/crossrealm_test.Exec"+tt.callStackAdd, callersByAddr[r.Addr]) + printColumns(baseCallStack+" -> r/crossrealm_test.Exec"+tt.callStackAdd, callersByAddr[r.Addr()]) }) rtests.Exec(func() { r := tt.callerFn() assertRealm(r) - printColumns(baseCallStack+" -> r/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) + printColumns(baseCallStack+" -> r/demo/tests.Exec"+tt.callStackAdd, callersByAddr[r.Addr()]) }) ptests.Exec(func() { r := tt.callerFn() assertRealm(r) - printColumns(baseCallStack+" -> p/demo/tests.Exec"+tt.callStackAdd, callersByAddr[tt.callerFn().Addr]) + printColumns(baseCallStack+" -> p/demo/tests.Exec"+tt.callStackAdd, callersByAddr[r.Addr()]) }) } } From fb9245bd99a4f4c37e7fb85896d6c389c4f9d115 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Tue, 6 Jun 2023 16:34:33 +0100 Subject: [PATCH 25/25] fix: stdshim realm --- gnovm/stdlibs/stdshim/stdshim.gno | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnovm/stdlibs/stdshim/stdshim.gno b/gnovm/stdlibs/stdshim/stdshim.gno index dd2b2d55311..8e1fdc0da75 100644 --- a/gnovm/stdlibs/stdshim/stdshim.gno +++ b/gnovm/stdlibs/stdshim/stdshim.gno @@ -39,8 +39,8 @@ func GetOrigSend() Coins { func PrevRealm() Realm { panic(shimWarn) return Realm{ - Addr: Address(""), - PkgPath: "", + addr: Address(""), + pkgPath: "", } }