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: make AssertOriginCall always panic with MsgRun #1665

Merged
8 changes: 8 additions & 0 deletions examples/gno.land/r/demo/tests/subtests/subtests.gno
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,11 @@ func GetPrevRealm() std.Realm {
func Exec(fn func()) {
fn()
}

func CallAssertOriginCall() {
std.AssertOriginCall()
}

func CallIsOriginCall() bool {
return std.IsOriginCall()
}
12 changes: 10 additions & 2 deletions examples/gno.land/r/demo/tests/tests.gno
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,22 @@ func CurrentRealmPath() string {
return std.CurrentRealmPath()
}

func AssertOriginCall() {
func CallAssertOriginCall() {
std.AssertOriginCall()
}

func IsOriginCall() bool {
func CallIsOriginCall() bool {
return std.IsOriginCall()
}

func CallSubtestsAssertOriginCall() {
rsubtests.CallAssertOriginCall()
}

func CallSubtestsIsOriginCall() bool {
return rsubtests.CallIsOriginCall()
}

//----------------------------------------
// Test structure to ensure cross-realm modification is prevented.

Expand Down
36 changes: 24 additions & 12 deletions examples/gno.land/r/demo/tests/tests_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,40 @@ import (
)

func TestAssertOriginCall(t *testing.T) {
// No-panic case
AssertOriginCall()
if !IsOriginCall() {
// CallAssertOriginCall(): no panic
CallAssertOriginCall()
if !CallIsOriginCall() {
t.Errorf("expected IsOriginCall=true but got false")
}

// Panic case
// CallAssertOriginCall() from a block: panic
expectedReason := "invalid non-origin call"
func() {
defer func() {
r := recover()
if r == nil || r.(string) != expectedReason {
t.Errorf("expected panic with '%v', got '%v'", expectedReason, r)
}
}()
// if called inside a function literal, this is no longer an origin call
// because there's one additional frame (the function literal block).
if CallIsOriginCall() {
t.Errorf("expected IsOriginCall=false but got true")
}
CallAssertOriginCall()
}()

// CallSubtestsAssertOriginCall(): panic
defer func() {
r := recover()
if r == nil || r.(string) != expectedReason {
t.Errorf("expected panic with '%v', got '%v'", expectedReason, r)
}
}()
func() {
// if called inside a function literal, this is no longer an origin call
// because there's one additional frame (the function literal).
if IsOriginCall() {
t.Errorf("expected IsOriginCall=false but got true")
}
AssertOriginCall()
}()
if CallSubtestsIsOriginCall() {
t.Errorf("expected IsOriginCall=false but got true")
}
CallSubtestsAssertOriginCall()
}

func TestPrevRealm(t *testing.T) {
Expand Down
28 changes: 14 additions & 14 deletions examples/gno.land/r/demo/tests/z0_filetest.gno
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ import (
)

func main() {
println("IsOriginCall:", tests.IsOriginCall())
tests.AssertOriginCall()
println("AssertOriginCall doesn't panic when called directly")
println("tests.CallIsOriginCall:", tests.CallIsOriginCall())
tests.CallAssertOriginCall()
println("tests.CallAssertOriginCall doesn't panic when called directly")

func() {
// if called inside a function literal, this is no longer an origin call
// because there's one additional frame (the function literal).
println("IsOriginCall:", tests.IsOriginCall())
{
// if called inside a block, this is no longer an origin call because
// there's one additional frame (the block).
println("tests.CallIsOriginCall:", tests.CallIsOriginCall())
defer func() {
r := recover()
println("AssertOriginCall panics if when called inside a function literal:", r)
println("tests.AssertOriginCall panics if when called inside a function literal:", r)
}()
tests.AssertOriginCall()
}()
tests.CallAssertOriginCall()
}
}

// Output:
// IsOriginCall: true
// AssertOriginCall doesn't panic when called directly
// IsOriginCall: false
// AssertOriginCall panics if when called inside a function literal: invalid non-origin call
// tests.CallIsOriginCall: true
// tests.CallAssertOriginCall doesn't panic when called directly
// tests.CallIsOriginCall: true
// tests.AssertOriginCall panics if when called inside a function literal: undefined
254 changes: 254 additions & 0 deletions gno.land/cmd/gnoland/testdata/assertorigincall.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
# This test ensures the consistency of the std.AssertOriginCall function, in
# the following situations:
#
# | Num | Msg Type | Call from | Entry Point | Result |
# |-----|:--------:|:-------------------:|:----------------------:|:------:|
# | 1 | MsgCall | wallet direct | myrealm.A() | PANIC |
# | 2 | | | myrealm.B() | pass |
# | 3 | | | myrealm.C() | pass |
# | 4 | | through /r/foo | myrealm.A() | PANIC |
# | 5 | | | myrealm.B() | pass |
# | 6 | | | myrealm.C() | PANIC |
# | 7 | | through /p/demo/bar | myrealm.A() | PANIC |
# | 8 | | | myrealm.B() | pass |
# | 9 | | | myrealm.C() | PANIC |
# | 10 | MsgRun | wallet direct | myrealm.A() | PANIC |
# | 11 | | | myrealm.B() | pass |
# | 12 | | | myrealm.C() | PANIC |
# | 13 | | through /r/foo | myrealm.A() | PANIC |
# | 14 | | | myrealm.B() | pass |
# | 15 | | | myrealm.C() | PANIC |
# | 16 | | through /p/demo/bar | myrealm.A() | PANIC |
# | 17 | | | myrealm.B() | pass |
# | 18 | | | myrealm.C() | PANIC |
# | 19 | MsgCall | wallet direct | std.AssertOriginCall() | pass |
# | 20 | MsgRun | wallet direct | std.AssertOriginCall() | PANIC |

# 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 2000000 -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!'

# Test cases
## 1. MsgCall -> myrlm.A: PANIC
! gnokey maketx call -pkgpath gno.land/r/myrlm -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1
stderr 'invalid non-origin call'

## 2. MsgCall -> myrlm.B: PASS
gnokey maketx call -pkgpath gno.land/r/myrlm -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1
stdout 'OK!'

## 3. MsgCall -> myrlm.C: PASS
gnokey maketx call -pkgpath gno.land/r/myrlm -func C -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1
stdout 'OK!'

## 4. MsgCall -> r/foo.A -> myrlm.A: PANIC
! gnokey maketx call -pkgpath gno.land/r/foo -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1
stderr 'invalid non-origin call'

## 5. MsgCall -> r/foo.B -> myrlm.B: PASS
gnokey maketx call -pkgpath gno.land/r/foo -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1
stdout 'OK!'

## 6. MsgCall -> r/foo.C -> myrlm.C: PANIC
! 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'

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

## 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!'

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

## 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
stderr 'invalid non-origin call'

## 11. MsgRun -> run.main -> myrlm.B: PASS
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmB.gno
stdout 'OK!'

## 12. MsgRun -> run.main -> myrlm.C: PANIC
! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmC.gno
stderr 'invalid non-origin call'

## 13. MsgRun -> run.main -> foo.A: PANIC
! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooA.gno
stderr 'invalid non-origin call'

## 14. MsgRun -> run.main -> foo.B: PASS
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooB.gno
stdout 'OK!'

## 15. MsgRun -> run.main -> foo.C: PANIC
! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooC.gno
stderr 'invalid non-origin call'

## 16. MsgRun -> run.main -> bar.A: PANIC
! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barA.gno
stderr 'invalid non-origin call'

## 17. MsgRun -> run.main -> bar.B: PASS
gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barB.gno
stdout 'OK!'

## 18. MsgRun -> run.main -> bar.C: PANIC
! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barC.gno
stderr 'invalid non-origin call'

## 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!'

## 20. MsgRun -> std.AssertOriginCall: PANIC
! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/baz.gno
stderr 'invalid non-origin call'


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

import "std"

func A() {
C()
}

func B() {
if false {
C()
}
}

func C() {
std.AssertOriginCall()
}
-- r/foo/foo.gno --
package foo

import "gno.land/r/myrlm"

func A() {
myrlm.A()
}

func B() {
myrlm.B()
}

func C() {
myrlm.C()
}
-- p/demo/bar/bar.gno --
package bar

import "gno.land/r/myrlm"

func A() {
myrlm.A()
}

func B() {
myrlm.B()
}

func C() {
myrlm.C()
}
-- run/myrlmA.gno --
package main

import myrlm "gno.land/r/myrlm"

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

import "gno.land/r/myrlm"

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

import "gno.land/r/myrlm"

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

import "gno.land/r/foo"

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

import "gno.land/r/foo"

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

import "gno.land/r/foo"

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

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

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

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

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

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

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

import "std"

func main() {
std.AssertOriginCall()
}
Loading
Loading