From 86f5624f934e71a6fc9575532b4407493135aa15 Mon Sep 17 00:00:00 2001 From: thinhnx-var <168700277+thinhnx-var@users.noreply.github.com> Date: Fri, 31 May 2024 22:15:00 +0700 Subject: [PATCH] feat(sdk/vm)!: only allow using msgcall on realms (#2242)
Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
Follow discussion in #2192 and [TheHowl's comment](https://github.com/gnolang/gno/issues/1538#issuecomment-1911939360), this PR aims to prohibit the use of `maketx call` with a `p/` entrypoint and force `maketx call` to call to a `gno.land/` pkgpath Behavior: ``` $ gnokey maketx call -broadcast -pkgpath gno.land/p/ -gas-wanted 10000000 -gas-fee 1000000ugnot -func Demo -remote localhost:26657 testKey --= Error =-- Data: forbidden/bad package called Msg Traces: 0 ....... deliver transaction failed: log: --= /Error =-- ``` ``` $ gnokey maketx call -broadcast -pkgpath gno.land/p -gas-wanted 10000000 -gas-fee 1000000ugnot -func Demo -remote localhost: 26657 testKey --= Error =-- Data: forbidden/bad package called Msg Traces: 0 ....... deliver transaction failed: log: --= /Error =-- ``` For `stdlibs`, force the pkgpath to begins with `gno.land/` ``` $ gnokey maketx call -broadcast -pkgpath strconv -gas-wanted 10000000 -gas-fee 1000000ugnot -func Itoa -args 11 testKey --= Error =-- Data: forbidden/bad package called Msg Traces: 0 ....... deliver transaction failed: log: --= /Error =-- ``` --------- Co-authored-by: Morgan Bazalgette --- .../gnoland/testdata/assertorigincall.txtar | 18 ++++++----- .../gnoland/testdata/maketx_call_pure.txtar | 32 +++++++++++++++++++ gno.land/cmd/gnoland/testdata/prevrealm.txtar | 13 ++++---- gno.land/pkg/sdk/vm/msgs.go | 5 ++- gnovm/pkg/gnolang/realm.go | 2 +- 5 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 gno.land/cmd/gnoland/testdata/maketx_call_pure.txtar diff --git a/gno.land/cmd/gnoland/testdata/assertorigincall.txtar b/gno.land/cmd/gnoland/testdata/assertorigincall.txtar index fdbfebeef4a..e3cd1be744a 100644 --- a/gno.land/cmd/gnoland/testdata/assertorigincall.txtar +++ b/gno.land/cmd/gnoland/testdata/assertorigincall.txtar @@ -56,17 +56,18 @@ stdout 'OK!' ! gnokey maketx call -pkgpath gno.land/r/foo -func C -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 stderr 'invalid non-origin call' +## remove due to update to maketx call can only call realm (case 7,8,9) ## 7. MsgCall -> p/demo/bar.A -> myrlm.A: PANIC -! gnokey maketx call -pkgpath gno.land/p/demo/bar -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 -stderr 'invalid non-origin call' +## ! gnokey maketx call -pkgpath gno.land/p/demo/bar -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## stderr 'invalid non-origin call' ## 8. MsgCall -> p/demo/bar.B -> myrlm.B: PASS -gnokey maketx call -pkgpath gno.land/p/demo/bar -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 -stdout 'OK!' +## gnokey maketx call -pkgpath gno.land/p/demo/bar -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## stdout 'OK!' ## 9. MsgCall -> p/demo/bar.C -> myrlm.C: PANIC -! gnokey maketx call -pkgpath gno.land/p/demo/bar -func C -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 -stderr 'invalid non-origin call' +## ! gnokey maketx call -pkgpath gno.land/p/demo/bar -func C -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## stderr 'invalid non-origin call' ## 10. MsgRun -> run.main -> myrlm.A: PANIC ! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmA.gno @@ -104,9 +105,10 @@ stdout 'OK!' ! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barC.gno stderr 'invalid non-origin call' +## remove testcase 19 due to maketx call forced to call a realm ## 19. MsgCall -> std.AssertOriginCall: pass -gnokey maketx call -pkgpath std -func AssertOriginCall -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 -stdout 'OK!' +## gnokey maketx call -pkgpath std -func AssertOriginCall -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## stdout 'OK!' ## 20. MsgRun -> std.AssertOriginCall: PANIC ! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/baz.gno diff --git a/gno.land/cmd/gnoland/testdata/maketx_call_pure.txtar b/gno.land/cmd/gnoland/testdata/maketx_call_pure.txtar new file mode 100644 index 00000000000..e3231eccc01 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/maketx_call_pure.txtar @@ -0,0 +1,32 @@ +# load the package +loadpkg gno.land/p/foo/call_package $WORK/package +loadpkg gno.land/r/foo/call_realm $WORK/realm + +# start a new node +gnoland start + +# 1. call to package ERROR +! gnokey maketx call -pkgpath gno.land/p/foo/call_package -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stderr '"gnokey" error: --= Error =--\nData: invalid package path' + +# 2. call to stdlibs ERROR +! gnokey maketx call -pkgpath strconv -func Itoa -args 11 -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stderr '"gnokey" error: --= Error =--\nData: invalid package path' + +# 3. normal call to realm PASS +gnokey maketx call -pkgpath gno.land/r/foo/call_realm -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +stdout OK! + +-- package/package.gno -- +package call_package + +func Render() string { + return "notok" +} + +-- realm/realm.gno -- +package call_realm + +func Render() string { + return "ok" +} diff --git a/gno.land/cmd/gnoland/testdata/prevrealm.txtar b/gno.land/cmd/gnoland/testdata/prevrealm.txtar index ac7988616a4..72a207fae22 100644 --- a/gno.land/cmd/gnoland/testdata/prevrealm.txtar +++ b/gno.land/cmd/gnoland/testdata/prevrealm.txtar @@ -49,13 +49,14 @@ stdout ${RFOO_ADDR} gnokey maketx call -pkgpath gno.land/r/foo -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 stdout ${RFOO_ADDR} +## remove due to update to maketx call can only call realm (case 5, 6, 13) ## 5. MsgCall -> p/demo/bar.A -> myrlm.A: user address -gnokey maketx call -pkgpath gno.land/p/demo/bar -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 -stdout ${USER_ADDR_test1} +## gnokey maketx call -pkgpath gno.land/p/demo/bar -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## stdout ${USER_ADDR_test1} ## 6. MsgCall -> p/demo/bar.B -> myrlm.B -> r/foo.A: user address -gnokey maketx call -pkgpath gno.land/p/demo/bar -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 -stdout ${USER_ADDR_test1} +## gnokey maketx call -pkgpath gno.land/p/demo/bar -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## stdout ${USER_ADDR_test1} ## 7. MsgRun -> myrlm.A: user address gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmA.gno @@ -82,8 +83,8 @@ gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid t stdout ${USER_ADDR_test1} ## 13. MsgCall -> std.PrevRealm(): user address -gnokey maketx call -pkgpath std -func PrevRealm -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 -stdout ${USER_ADDR_test1} +## gnokey maketx call -pkgpath std -func PrevRealm -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## stdout ${USER_ADDR_test1} ## 14. MsgRun -> std.PrevRealm(): user address gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/baz.gno diff --git a/gno.land/pkg/sdk/vm/msgs.go b/gno.land/pkg/sdk/vm/msgs.go index e42babe1510..e5616fa2395 100644 --- a/gno.land/pkg/sdk/vm/msgs.go +++ b/gno.land/pkg/sdk/vm/msgs.go @@ -113,9 +113,12 @@ func (msg MsgCall) ValidateBasic() error { if msg.Caller.IsZero() { return std.ErrInvalidAddress("missing caller address") } - if msg.PkgPath == "" { // XXX + if msg.PkgPath == "" { return ErrInvalidPkgPath("missing package path") } + if !gno.IsRealmPath(msg.PkgPath) { + return ErrInvalidPkgPath("pkgpath must be of a realm") + } if msg.Func == "" { // XXX return ErrInvalidExpr("missing function to call") } diff --git a/gnovm/pkg/gnolang/realm.go b/gnovm/pkg/gnolang/realm.go index 17b655e6352..85f94d4fcbe 100644 --- a/gnovm/pkg/gnolang/realm.go +++ b/gnovm/pkg/gnolang/realm.go @@ -1518,7 +1518,7 @@ func isUnsaved(oo Object) bool { // be realms and as such to have their state persisted. This is used by [IsRealmPath]. const realmPathPrefix = "gno.land/r/" -var ReGnoRunPath = regexp.MustCompile(`gno\.land/r/g[a-z0-9]+/run`) +var ReGnoRunPath = regexp.MustCompile(`^gno\.land/r/g[a-z0-9]+/run$`) // IsRealmPath determines whether the given pkgpath is for a realm, and as such // should persist the global state.