From 36295357d892e1f92750a2d3025c45942a2ce0d0 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 22 Oct 2021 14:50:51 +0300 Subject: [PATCH] interop: add Abort() function to ABORT things Related to #2227. --- pkg/compiler/analysis.go | 2 +- pkg/compiler/codegen.go | 2 ++ pkg/compiler/interop_test.go | 12 ++++++++++++ pkg/interop/neogointernal/opcode.go | 5 +++++ pkg/interop/util/util.go | 11 ++++++++++- 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/pkg/compiler/analysis.go b/pkg/compiler/analysis.go index cc89fddbf..03f7bda06 100644 --- a/pkg/compiler/analysis.go +++ b/pkg/compiler/analysis.go @@ -17,7 +17,7 @@ var ( goBuiltins = []string{"len", "append", "panic", "make", "copy", "recover", "delete"} // Custom builtin utility functions. customBuiltins = []string{ - "FromAddress", "Equals", "Remove", + "Abort", "FromAddress", "Equals", "Remove", "ToBool", "ToBytes", "ToString", "ToInteger", } ) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 8a2bd1673..30dae42be 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -1724,6 +1724,8 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { c.emitStoreByIndex(varGlobal, c.exceptionIndex) case "delete": emit.Opcodes(c.prog.BinWriter, opcode.REMOVE) + case "Abort": + emit.Opcodes(c.prog.BinWriter, opcode.ABORT) case "Remove": if !isCompoundSlice(c.typeOf(expr.Args[0])) { c.prog.Err = errors.New("`Remove` supports only non-byte slices") diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index 135f1bc61..89624f06d 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -116,6 +116,18 @@ func TestFromAddress(t *testing.T) { }) } +func TestAbort(t *testing.T) { + src := `package foo + import "github.com/nspcc-dev/neo-go/pkg/interop/util" + func Main() int { + util.Abort() + return 1 + }` + v := vmAndCompile(t, src) + require.Error(t, v.Run()) + require.True(t, v.HasFailed()) +} + func spawnVM(t *testing.T, ic *interop.Context, src string) *vm.VM { b, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(src)) require.NoError(t, err) diff --git a/pkg/interop/neogointernal/opcode.go b/pkg/interop/neogointernal/opcode.go index 2e18b936b..e96d0a1d4 100644 --- a/pkg/interop/neogointernal/opcode.go +++ b/pkg/interop/neogointernal/opcode.go @@ -1,5 +1,10 @@ package neogointernal +// Opcode0 emits opcode without arguments. +func Opcode0(op string) interface{} { + return nil +} + // Opcode1 emits opcode with 1 argument. func Opcode1(op string, arg interface{}) interface{} { return nil diff --git a/pkg/interop/util/util.go b/pkg/interop/util/util.go index 7120759b7..79b2789bd 100644 --- a/pkg/interop/util/util.go +++ b/pkg/interop/util/util.go @@ -3,7 +3,16 @@ Package util contains some special useful functions that are provided by compile */ package util -import "github.com/nspcc-dev/neo-go/pkg/interop" +import ( + "github.com/nspcc-dev/neo-go/pkg/interop" + "github.com/nspcc-dev/neo-go/pkg/interop/neogointernal" +) + +// Abort terminates current execution, unlike exception throwing with panic() it +// can't be recovered from. +func Abort() { + _ = neogointernal.Opcode0("ABORT") +} // FromAddress is an utility function that converts a Neo address to its hash // (160 bit BE value in a 20 byte slice). It can only be used for strings known