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.