Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: PrevRealm ignores user realms in MsgRun #1719

Merged
merged 7 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions gno.land/cmd/gnoland/testdata/prevrealm.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# This tests ensure the consistency of the std.PrevRealm function, in the
# following situations:
#
#
# | Num | Msg Type | Call from | Entry Point | Result |
# |-----|:--------:|:-------------------:|:---------------:|:------------:|
# | 1 | MsgCall | wallet direct | myrlm.A() | user address |
# | 2 | | | myrlm.B() | user address |
# | 3 | | through /r/foo | myrlm.A() | r/foo |
# | 4 | | | myrlm.B() | r/foo |
# | 5 | | through /p/demo/bar | myrlm.A() | user address |
# | 6 | | | myrlm.B() | user address |
# | 7 | MsgRun | wallet direct | myrlm.A() | user address |
# | 8 | | | myrlm.B() | user address |
# | 9 | | through /r/foo | myrlm.A() | r/foo |
# | 10 | | | myrlm.B() | r/foo |
# | 11 | | through /p/demo/bar | myrlm.A() | user address |
# | 12 | | | myrlm.B() | user address |
# | 13 | MsgCall | wallet direct | std.PrevRealm() | user address |
# | 14 | MsgRun | wallet direct | std.PrevRealm() | user address |

# Init
## start a new node
gnoland start

## deploy myrlm
gnokey maketx addpkg -pkgdir $WORK/r/myrlm -pkgpath gno.land/r/myrlm -gas-fee 1000000ugnot -gas-wanted 2100000 -broadcast -chainid=tendermint_test test1
stdout 'OK!'

## deploy r/foo
gnokey maketx addpkg -pkgdir $WORK/r/foo -pkgpath gno.land/r/foo -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1
stdout 'OK!'

## deploy p/demo/bar
gnokey maketx addpkg -pkgdir $WORK/p/demo/bar -pkgpath gno.land/p/demo/bar -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1
stdout 'OK!'
thehowl marked this conversation as resolved.
Show resolved Hide resolved

env RFOO_ADDR=g1evezrh92xaucffmtgsaa3rvmz5s8kedffsg469

# Test cases
## 1. MsgCall -> myrlm.A: user address
gnokey maketx call -pkgpath gno.land/r/myrlm -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1
stdout ${USER_ADDR_test1}

## 2. MsgCall -> myrealm.B -> myrlm.A: user address
gnokey maketx call -pkgpath gno.land/r/myrlm -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1
stdout ${USER_ADDR_test1}

## 3. MsgCall -> r/foo.A -> myrlm.A: r/foo
gnokey maketx call -pkgpath gno.land/r/foo -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1
stdout ${RFOO_ADDR}

## 4. MsgCall -> r/foo.B -> myrlm.B -> r/foo.A: r/foo
gnokey maketx call -pkgpath gno.land/r/foo -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1
stdout ${RFOO_ADDR}

## 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}

## 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}

## 7. MsgRun -> myrlm.A: user address
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmA.gno
stdout ${USER_ADDR_test1}

## 8. MsgRun -> myrealm.B -> myrlm.A: user address
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmB.gno
stdout ${USER_ADDR_test1}

## 9. MsgRun -> r/foo.A -> myrlm.A: r/foo
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooA.gno
stdout ${RFOO_ADDR}

## 10. MsgRun -> r/foo.B -> myrlm.B -> r/foo.A: r/foo
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooB.gno
stdout ${RFOO_ADDR}

## 11. MsgRun -> p/demo/bar.A -> myrlm.A: user address
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barA.gno
stdout ${USER_ADDR_test1}

## 12. MsgRun -> p/demo/bar.B -> myrlm.B -> r/foo.A: user address
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barB.gno
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}

## 14. MsgRun -> std.PrevRealm(): user address
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/baz.gno
stdout ${USER_ADDR_test1}

-- r/myrlm/myrlm.gno --
package myrlm

import "std"

func A() string {
return std.PrevRealm().Addr().String()
}

func B() string {
return A()
}
-- r/foo/foo.gno --
package foo

import "gno.land/r/myrlm"

func A() string {
return myrlm.A()
}

func B() string {
return myrlm.B()
}
-- p/demo/bar/bar.gno --
package bar

import "gno.land/r/myrlm"

func A() string {
return myrlm.A()
}

func B() string {
return myrlm.B()
}
-- run/myrlmA.gno --
package main

import myrlm "gno.land/r/myrlm"

func main() {
println(myrlm.A())
}
-- run/myrlmB.gno --
package main

import "gno.land/r/myrlm"

func main() {
println(myrlm.B())
}
-- run/fooA.gno --
package main

import "gno.land/r/foo"

func main() {
println(foo.A())
}
-- run/fooB.gno --
package main

import "gno.land/r/foo"

func main() {
println(foo.B())
}
-- run/barA.gno --
package main

import "gno.land/p/demo/bar"

func main() {
println(bar.A())
}
-- run/barB.gno --
package main

import "gno.land/p/demo/bar"

func main() {
println(bar.B())
}
-- run/baz.gno --
package main

import "std"

func main() {
println(std.PrevRealm().Addr().String())
}
5 changes: 1 addition & 4 deletions gno.land/pkg/sdk/vm/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"bytes"
"fmt"
"os"
"regexp"
"strings"

gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
Expand Down Expand Up @@ -131,8 +130,6 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store {
}
}

var reRunPath = regexp.MustCompile(`gno\.land/r/g[a-z0-9]+/run`)

// AddPackage adds a package with given fileset.
func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) {
creator := msg.Creator
Expand All @@ -156,7 +153,7 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) {
return ErrInvalidPkgPath("package already exists: " + pkgPath)
}

if reRunPath.MatchString(pkgPath) {
if gno.ReGnoRunPath.MatchString(pkgPath) {
return ErrInvalidPkgPath("reserved package name: " + pkgPath)
}

Expand Down
7 changes: 6 additions & 1 deletion gnovm/pkg/gnolang/realm.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"reflect"
"regexp"
"strings"
)

Expand Down Expand Up @@ -1517,10 +1518,14 @@ 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`)
thehowl marked this conversation as resolved.
Show resolved Hide resolved

// IsRealmPath determines whether the given pkgpath is for a realm, and as such
// should persist the global state.
func IsRealmPath(pkgPath string) bool {
return strings.HasPrefix(pkgPath, realmPathPrefix)
return strings.HasPrefix(pkgPath, realmPathPrefix) &&
// MsgRun pkgPath aren't realms
!ReGnoRunPath.MatchString(pkgPath)
}

func prettyJSON(jstr []byte) []byte {
Expand Down
1 change: 1 addition & 0 deletions gnovm/pkg/gnolang/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@ type PackageValue struct {
fBlocksMap map[Name]*Block
}

// IsRealm returns true if pv represents a realm.
func (pv *PackageValue) IsRealm() bool {
return IsRealmPath(pv.PkgPath)
}
Expand Down
4 changes: 2 additions & 2 deletions gnovm/pkg/transpiler/transpiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ func TranspileBuildPackage(fileOrPkg, goBinary string) error {
return err
}

var errorRe = regexp.MustCompile(`(?m)^(\S+):(\d+):(\d+): (.+)$`)
var reGoBuildError = regexp.MustCompile(`(?m)^(\S+):(\d+):(\d+): (.+)$`)

// parseGoBuildErrors returns a scanner.ErrorList filled with all errors found
// in out, which is supposed to be the output of the `go build` command.
Expand All @@ -240,7 +240,7 @@ var errorRe = regexp.MustCompile(`(?m)^(\S+):(\d+):(\d+): (.+)$`)
// See https://github.com/golang/go/issues/62067
func parseGoBuildErrors(out string) error {
var errList goscanner.ErrorList
matches := errorRe.FindAllStringSubmatch(out, -1)
matches := reGoBuildError.FindAllStringSubmatch(out, -1)
for _, match := range matches {
filename := match[1]
line, err := strconv.Atoi(match[2])
Expand Down
Loading