forked from TrueCloudLab/neoneo-go
Merge pull request #1598 from nspcc-dev/compiler/callex
Implement `contract.CallEx` in compiler
This commit is contained in:
commit
982de99cd6
10 changed files with 150 additions and 50 deletions
|
@ -3,7 +3,6 @@ package timer
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
"github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/engine"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||||
|
@ -54,7 +53,7 @@ func Tick() bool {
|
||||||
ticksLeft = ticksLeft.(int) - 1
|
ticksLeft = ticksLeft.(int) - 1
|
||||||
if ticksLeft == 0 {
|
if ticksLeft == 0 {
|
||||||
runtime.Log("Fired!")
|
runtime.Log("Fired!")
|
||||||
return engine.AppCall(runtime.GetExecutingScriptHash(), "selfDestroy").(bool)
|
return contract.Call(runtime.GetExecutingScriptHash(), "selfDestroy").(bool)
|
||||||
}
|
}
|
||||||
storage.Put(ctx, ticksKey, ticksLeft)
|
storage.Put(ctx, ticksKey, ticksLeft)
|
||||||
i := binary.Itoa(ticksLeft.(int), 10)
|
i := binary.Itoa(ticksLeft.(int), 10)
|
||||||
|
|
|
@ -43,11 +43,13 @@ func (c *codegen) getIdentName(pkg string, name string) string {
|
||||||
// Same for `_deploy()` functions (see docs/compiler.md).
|
// Same for `_deploy()` functions (see docs/compiler.md).
|
||||||
func (c *codegen) traverseGlobals() (int, int, int) {
|
func (c *codegen) traverseGlobals() (int, int, int) {
|
||||||
var hasDefer bool
|
var hasDefer bool
|
||||||
var n int
|
var n, nConst int
|
||||||
initLocals := -1
|
initLocals := -1
|
||||||
deployLocals := -1
|
deployLocals := -1
|
||||||
c.ForEachFile(func(f *ast.File, _ *types.Package) {
|
c.ForEachFile(func(f *ast.File, _ *types.Package) {
|
||||||
n += countGlobals(f)
|
nv, nc := countGlobals(f)
|
||||||
|
n += nv
|
||||||
|
nConst += nc
|
||||||
if initLocals == -1 || deployLocals == -1 || !hasDefer {
|
if initLocals == -1 || deployLocals == -1 || !hasDefer {
|
||||||
ast.Inspect(f, func(node ast.Node) bool {
|
ast.Inspect(f, func(node ast.Node) bool {
|
||||||
switch n := node.(type) {
|
switch n := node.(type) {
|
||||||
|
@ -75,7 +77,7 @@ func (c *codegen) traverseGlobals() (int, int, int) {
|
||||||
if hasDefer {
|
if hasDefer {
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
if n != 0 || initLocals > -1 {
|
if n+nConst != 0 || initLocals > -1 {
|
||||||
if n > 255 {
|
if n > 255 {
|
||||||
c.prog.BinWriter.Err = errors.New("too many global variables")
|
c.prog.BinWriter.Err = errors.New("too many global variables")
|
||||||
return 0, initLocals, deployLocals
|
return 0, initLocals, deployLocals
|
||||||
|
@ -88,7 +90,7 @@ func (c *codegen) traverseGlobals() (int, int, int) {
|
||||||
}
|
}
|
||||||
seenBefore := false
|
seenBefore := false
|
||||||
c.ForEachPackage(func(pkg *loader.PackageInfo) {
|
c.ForEachPackage(func(pkg *loader.PackageInfo) {
|
||||||
if n > 0 {
|
if n+nConst > 0 {
|
||||||
for _, f := range pkg.Files {
|
for _, f := range pkg.Files {
|
||||||
c.fillImportMap(f, pkg.Pkg)
|
c.fillImportMap(f, pkg.Pkg)
|
||||||
c.convertGlobals(f, pkg.Pkg)
|
c.convertGlobals(f, pkg.Pkg)
|
||||||
|
@ -116,7 +118,9 @@ func (c *codegen) traverseGlobals() (int, int, int) {
|
||||||
|
|
||||||
// countGlobals counts the global variables in the program to add
|
// countGlobals counts the global variables in the program to add
|
||||||
// them with the stack size of the function.
|
// them with the stack size of the function.
|
||||||
func countGlobals(f ast.Node) (i int) {
|
// Second returned argument contains amount of global constants.
|
||||||
|
func countGlobals(f ast.Node) (int, int) {
|
||||||
|
var numVar, numConst int
|
||||||
ast.Inspect(f, func(node ast.Node) bool {
|
ast.Inspect(f, func(node ast.Node) bool {
|
||||||
switch n := node.(type) {
|
switch n := node.(type) {
|
||||||
// Skip all function declarations if we have already encountered `defer`.
|
// Skip all function declarations if we have already encountered `defer`.
|
||||||
|
@ -125,11 +129,16 @@ func countGlobals(f ast.Node) (i int) {
|
||||||
// After skipping all funcDecls we are sure that each value spec
|
// After skipping all funcDecls we are sure that each value spec
|
||||||
// is a global declared variable or constant.
|
// is a global declared variable or constant.
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
if n.Tok == token.VAR {
|
isVar := n.Tok == token.VAR
|
||||||
|
if isVar || n.Tok == token.CONST {
|
||||||
for _, s := range n.Specs {
|
for _, s := range n.Specs {
|
||||||
for _, id := range s.(*ast.ValueSpec).Names {
|
for _, id := range s.(*ast.ValueSpec).Names {
|
||||||
if id.Name != "_" {
|
if id.Name != "_" {
|
||||||
i++
|
if isVar {
|
||||||
|
numVar++
|
||||||
|
} else {
|
||||||
|
numConst++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +147,7 @@ func countGlobals(f ast.Node) (i int) {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return
|
return numVar, numConst
|
||||||
}
|
}
|
||||||
|
|
||||||
// isExprNil looks if the given expression is a `nil`.
|
// isExprNil looks if the given expression is a `nil`.
|
||||||
|
|
|
@ -850,7 +850,14 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
emit.Opcodes(c.prog.BinWriter, opcode.PACK)
|
emit.Opcodes(c.prog.BinWriter, opcode.PACK)
|
||||||
numArgs -= varSize - 1
|
numArgs -= varSize - 1
|
||||||
}
|
}
|
||||||
c.emitReverse(numArgs)
|
// CallFlag in CallEx interop should be the last argument
|
||||||
|
// but this can't be reflected in signature due to varargs.
|
||||||
|
// It is first in compiler interop though, thus we just need to reverse 1 values less.
|
||||||
|
if f != nil && isSyscall(f) && f.pkg.Name() == "contract" && f.name == "CallEx" {
|
||||||
|
c.emitReverse(numArgs - 1)
|
||||||
|
} else {
|
||||||
|
c.emitReverse(numArgs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check builtin first to avoid nil pointer on funcScope!
|
// Check builtin first to avoid nil pointer on funcScope!
|
||||||
|
|
|
@ -202,12 +202,22 @@ func TestExportedVariable(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExportedConst(t *testing.T) {
|
func TestExportedConst(t *testing.T) {
|
||||||
src := `package foo
|
t.Run("with vars", func(t *testing.T) {
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/multi"
|
src := `package foo
|
||||||
func Main() int {
|
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/multi"
|
||||||
return multi.SomeConst
|
func Main() int {
|
||||||
}`
|
return multi.SomeConst
|
||||||
eval(t, src, big.NewInt(42))
|
}`
|
||||||
|
eval(t, src, big.NewInt(42))
|
||||||
|
})
|
||||||
|
t.Run("const only", func(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/constonly"
|
||||||
|
func Main() int {
|
||||||
|
return constonly.Answer
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(42))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultipleFuncSameName(t *testing.T) {
|
func TestMultipleFuncSameName(t *testing.T) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
|
cinterop "github.com/nspcc-dev/neo-go/pkg/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
|
@ -85,8 +86,26 @@ func spawnVM(t *testing.T, ic *interop.Context, src string) *vm.VM {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAppCall(t *testing.T) {
|
func TestAppCall(t *testing.T) {
|
||||||
srcInner := `
|
srcDeep := `package foo
|
||||||
package foo
|
func Get42() int {
|
||||||
|
return 42
|
||||||
|
}`
|
||||||
|
barCtr, di, err := compiler.CompileWithDebugInfo("bar.go", strings.NewReader(srcDeep))
|
||||||
|
require.NoError(t, err)
|
||||||
|
mBar, err := di.ConvertToManifest("Bar", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
barH := hash.Hash160(barCtr)
|
||||||
|
ic := interop.NewContext(trigger.Application, nil, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false), nil, nil, nil, zaptest.NewLogger(t))
|
||||||
|
require.NoError(t, ic.DAO.PutContractState(&state.Contract{
|
||||||
|
Hash: barH,
|
||||||
|
Script: barCtr,
|
||||||
|
Manifest: *mBar,
|
||||||
|
}))
|
||||||
|
|
||||||
|
srcInner := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop"
|
||||||
var a int = 3
|
var a int = 3
|
||||||
func Main(a []byte, b []byte) []byte {
|
func Main(a []byte, b []byte) []byte {
|
||||||
panic("Main was called")
|
panic("Main was called")
|
||||||
|
@ -97,7 +116,11 @@ func TestAppCall(t *testing.T) {
|
||||||
func Add3(n int) int {
|
func Add3(n int) int {
|
||||||
return a + n
|
return a + n
|
||||||
}
|
}
|
||||||
`
|
func CallInner() int {
|
||||||
|
return contract.Call(%s, "get42").(int)
|
||||||
|
}`
|
||||||
|
srcInner = fmt.Sprintf(srcInner,
|
||||||
|
fmt.Sprintf("%#v", cinterop.Hash160(barH.BytesBE())))
|
||||||
|
|
||||||
inner, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(srcInner))
|
inner, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(srcInner))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -105,7 +128,6 @@ func TestAppCall(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ih := hash.Hash160(inner)
|
ih := hash.Hash160(inner)
|
||||||
ic := interop.NewContext(trigger.Application, nil, dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false), nil, nil, nil, zaptest.NewLogger(t))
|
|
||||||
require.NoError(t, ic.DAO.PutContractState(&state.Contract{
|
require.NoError(t, ic.DAO.PutContractState(&state.Contract{
|
||||||
Hash: ih,
|
Hash: ih,
|
||||||
Script: inner,
|
Script: inner,
|
||||||
|
@ -120,6 +142,19 @@ func TestAppCall(t *testing.T) {
|
||||||
assertResult(t, v, []byte{1, 2, 3, 4})
|
assertResult(t, v, []byte{1, 2, 3, 4})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("callEx, valid", func(t *testing.T) {
|
||||||
|
src := getCallExScript(fmt.Sprintf("%#v", ih.BytesBE()), "contract.AllowCall")
|
||||||
|
v := spawnVM(t, ic, src)
|
||||||
|
require.NoError(t, v.Run())
|
||||||
|
|
||||||
|
assertResult(t, v, big.NewInt(42))
|
||||||
|
})
|
||||||
|
t.Run("callEx, missing flags", func(t *testing.T) {
|
||||||
|
src := getCallExScript(fmt.Sprintf("%#v", ih.BytesBE()), "contract.NoneFlag")
|
||||||
|
v := spawnVM(t, ic, src)
|
||||||
|
require.Error(t, v.Run())
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("missing script", func(t *testing.T) {
|
t.Run("missing script", func(t *testing.T) {
|
||||||
h := ih
|
h := ih
|
||||||
h[0] = ^h[0]
|
h[0] = ^h[0]
|
||||||
|
@ -132,12 +167,12 @@ func TestAppCall(t *testing.T) {
|
||||||
t.Run("convert from string constant", func(t *testing.T) {
|
t.Run("convert from string constant", func(t *testing.T) {
|
||||||
src := `
|
src := `
|
||||||
package foo
|
package foo
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
const scriptHash = ` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `
|
const scriptHash = ` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `
|
||||||
func Main() []byte {
|
func Main() []byte {
|
||||||
x := []byte{1, 2}
|
x := []byte{1, 2}
|
||||||
y := []byte{3, 4}
|
y := []byte{3, 4}
|
||||||
result := engine.AppCall([]byte(scriptHash), "append", x, y)
|
result := contract.Call([]byte(scriptHash), "append", x, y)
|
||||||
return result.([]byte)
|
return result.([]byte)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
@ -151,12 +186,12 @@ func TestAppCall(t *testing.T) {
|
||||||
t.Run("convert from var", func(t *testing.T) {
|
t.Run("convert from var", func(t *testing.T) {
|
||||||
src := `
|
src := `
|
||||||
package foo
|
package foo
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
func Main() []byte {
|
func Main() []byte {
|
||||||
x := []byte{1, 2}
|
x := []byte{1, 2}
|
||||||
y := []byte{3, 4}
|
y := []byte{3, 4}
|
||||||
var addr = []byte(` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `)
|
var addr = []byte(` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `)
|
||||||
result := engine.AppCall(addr, "append", x, y)
|
result := contract.Call(addr, "append", x, y)
|
||||||
return result.([]byte)
|
return result.([]byte)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
@ -169,10 +204,10 @@ func TestAppCall(t *testing.T) {
|
||||||
|
|
||||||
t.Run("InitializedGlobals", func(t *testing.T) {
|
t.Run("InitializedGlobals", func(t *testing.T) {
|
||||||
src := `package foo
|
src := `package foo
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
func Main() int {
|
func Main() int {
|
||||||
var addr = []byte(` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `)
|
var addr = []byte(` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `)
|
||||||
result := engine.AppCall(addr, "add3", 39)
|
result := contract.Call(addr, "add3", 39)
|
||||||
return result.(int)
|
return result.(int)
|
||||||
}`
|
}`
|
||||||
|
|
||||||
|
@ -184,10 +219,10 @@ func TestAppCall(t *testing.T) {
|
||||||
|
|
||||||
t.Run("AliasPackage", func(t *testing.T) {
|
t.Run("AliasPackage", func(t *testing.T) {
|
||||||
src := `package foo
|
src := `package foo
|
||||||
import ee "github.com/nspcc-dev/neo-go/pkg/interop/engine"
|
import ee "github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
func Main() int {
|
func Main() int {
|
||||||
var addr = []byte(` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `)
|
var addr = []byte(` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `)
|
||||||
result := ee.AppCall(addr, "add3", 39)
|
result := ee.Call(addr, "add3", 39)
|
||||||
return result.(int)
|
return result.(int)
|
||||||
}`
|
}`
|
||||||
v := spawnVM(t, ic, src)
|
v := spawnVM(t, ic, src)
|
||||||
|
@ -199,16 +234,25 @@ func TestAppCall(t *testing.T) {
|
||||||
func getAppCallScript(h string) string {
|
func getAppCallScript(h string) string {
|
||||||
return `
|
return `
|
||||||
package foo
|
package foo
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/engine"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
func Main() []byte {
|
func Main() []byte {
|
||||||
x := []byte{1, 2}
|
x := []byte{1, 2}
|
||||||
y := []byte{3, 4}
|
y := []byte{3, 4}
|
||||||
result := engine.AppCall(` + h + `, "append", x, y)
|
result := contract.Call(` + h + `, "append", x, y)
|
||||||
return result.([]byte)
|
return result.([]byte)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getCallExScript(h string, flags string) string {
|
||||||
|
return `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
|
func Main() int {
|
||||||
|
result := contract.CallEx(` + flags + `, ` + h + `, "callInner")
|
||||||
|
return result.(int)
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuiltinDoesNotCompile(t *testing.T) {
|
func TestBuiltinDoesNotCompile(t *testing.T) {
|
||||||
src := `package foo
|
src := `package foo
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/util"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||||
|
|
|
@ -23,6 +23,8 @@ var syscalls = map[string]map[string]string{
|
||||||
"GetTransactionHeight": interopnames.SystemBlockchainGetTransactionHeight,
|
"GetTransactionHeight": interopnames.SystemBlockchainGetTransactionHeight,
|
||||||
},
|
},
|
||||||
"contract": {
|
"contract": {
|
||||||
|
"Call": interopnames.SystemContractCall,
|
||||||
|
"CallEx": interopnames.SystemContractCallEx,
|
||||||
"Create": interopnames.SystemContractCreate,
|
"Create": interopnames.SystemContractCreate,
|
||||||
"CreateStandardAccount": interopnames.SystemContractCreateStandardAccount,
|
"CreateStandardAccount": interopnames.SystemContractCreateStandardAccount,
|
||||||
"Destroy": interopnames.SystemContractDestroy,
|
"Destroy": interopnames.SystemContractDestroy,
|
||||||
|
@ -44,9 +46,6 @@ var syscalls = map[string]map[string]string{
|
||||||
"Next": interopnames.SystemEnumeratorNext,
|
"Next": interopnames.SystemEnumeratorNext,
|
||||||
"Value": interopnames.SystemEnumeratorValue,
|
"Value": interopnames.SystemEnumeratorValue,
|
||||||
},
|
},
|
||||||
"engine": {
|
|
||||||
"AppCall": interopnames.SystemContractCall,
|
|
||||||
},
|
|
||||||
"iterator": {
|
"iterator": {
|
||||||
"Concat": interopnames.SystemIteratorConcat,
|
"Concat": interopnames.SystemIteratorConcat,
|
||||||
"Create": interopnames.SystemIteratorCreate,
|
"Create": interopnames.SystemIteratorCreate,
|
||||||
|
|
|
@ -4,11 +4,24 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Checks that changes in `smartcontract` are reflected in compiler interop package.
|
||||||
|
func TestCallFlags(t *testing.T) {
|
||||||
|
require.EqualValues(t, contract.AllowStates, smartcontract.AllowStates)
|
||||||
|
require.EqualValues(t, contract.AllowModifyStates, smartcontract.AllowModifyStates)
|
||||||
|
require.EqualValues(t, contract.AllowCall, smartcontract.AllowCall)
|
||||||
|
require.EqualValues(t, contract.AllowNotify, smartcontract.AllowNotify)
|
||||||
|
require.EqualValues(t, contract.ReadOnly, smartcontract.ReadOnly)
|
||||||
|
require.EqualValues(t, contract.All, smartcontract.All)
|
||||||
|
require.EqualValues(t, contract.NoneFlag, smartcontract.NoneFlag)
|
||||||
|
}
|
||||||
|
|
||||||
func TestStoragePutGet(t *testing.T) {
|
func TestStoragePutGet(t *testing.T) {
|
||||||
src := `
|
src := `
|
||||||
package foo
|
package foo
|
||||||
|
|
4
pkg/compiler/testdata/constonly/const.go
vendored
Normal file
4
pkg/compiler/testdata/constonly/const.go
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package constonly
|
||||||
|
|
||||||
|
// Answer is the only thing you will ever need.
|
||||||
|
const Answer = 42
|
|
@ -14,6 +14,21 @@ type Contract struct {
|
||||||
Manifest []byte
|
Manifest []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CallFlag specifies valid call flags.
|
||||||
|
type CallFlag byte
|
||||||
|
|
||||||
|
// Using `smartcontract` package from compiled contract requires moderate
|
||||||
|
// compiler refactoring, thus all flags are mirrored here.
|
||||||
|
const (
|
||||||
|
AllowStates CallFlag = 1 << iota
|
||||||
|
AllowModifyStates
|
||||||
|
AllowCall
|
||||||
|
AllowNotify
|
||||||
|
ReadOnly = AllowStates | AllowCall | AllowNotify
|
||||||
|
All = ReadOnly | AllowModifyStates
|
||||||
|
NoneFlag CallFlag = 0
|
||||||
|
)
|
||||||
|
|
||||||
// Create creates a new contract using a set of input parameters:
|
// Create creates a new contract using a set of input parameters:
|
||||||
// script contract's bytecode (limited in length by 1M)
|
// script contract's bytecode (limited in length by 1M)
|
||||||
// manifest contract's manifest (limited in length by 2 KiB)
|
// manifest contract's manifest (limited in length by 2 KiB)
|
||||||
|
@ -55,3 +70,19 @@ func CreateStandardAccount(pub interop.PublicKey) []byte {
|
||||||
func GetCallFlags() int64 {
|
func GetCallFlags() int64 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call executes previously deployed blockchain contract with specified hash
|
||||||
|
// (20 bytes in BE form) using provided arguments.
|
||||||
|
// It returns whatever this contract returns. This function uses
|
||||||
|
// `System.Contract.Call` syscall.
|
||||||
|
func Call(scriptHash interop.Hash160, method string, args ...interface{}) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallEx executes previously deployed blockchain contract with specified hash
|
||||||
|
// (20 bytes in BE form) using provided arguments and call flags.
|
||||||
|
// It returns whatever this contract returns. This function uses
|
||||||
|
// `System.Contract.CallEx` syscall.
|
||||||
|
func CallEx(f CallFlag, scriptHash interop.Hash160, method string, args ...interface{}) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
/*
|
|
||||||
Package engine allows to make contract calls.
|
|
||||||
It's roughly similar in function to ExecutionEngine class in the Neo .net
|
|
||||||
framework.
|
|
||||||
*/
|
|
||||||
package engine
|
|
||||||
|
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop"
|
|
||||||
|
|
||||||
// AppCall executes previously deployed blockchain contract with specified hash
|
|
||||||
// (160 bit in BE form represented as 20-byte slice) using provided arguments.
|
|
||||||
// It returns whatever this contract returns. This function uses
|
|
||||||
// `System.Contract.Call` syscall.
|
|
||||||
func AppCall(scriptHash interop.Hash160, method string, args ...interface{}) interface{} {
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Reference in a new issue