Merge pull request #651 from nspcc-dev/fix/appcall
compiler: refactor AppCall
This commit is contained in:
commit
f148798291
4 changed files with 37 additions and 31 deletions
4
go.sum
4
go.sum
|
@ -97,8 +97,8 @@ github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae h1:T5V1QANlNMKun0EP
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY=
|
github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY=
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a h1:ajvxgEe9qY4vvoSmrADqdDx7hReodKTnT2IXN++qZG8=
|
github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a h1:ajvxgEe9qY4vvoSmrADqdDx7hReodKTnT2IXN++qZG8=
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk=
|
github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk=
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20200130105505-02c208d154bf h1:7QLeZnBQZ8eJeYksP7tnENG2ZEOZhHTJBC6LkFt4Ok8=
|
github.com/nspcc-dev/dbft v0.0.0-20200203121303-549ecf2daaa1 h1:feHDSBix9oAVt5QzGABQczZo7dNWyeDKClLGwKvSJ/w=
|
||||||
github.com/nspcc-dev/dbft v0.0.0-20200130105505-02c208d154bf/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ=
|
github.com/nspcc-dev/dbft v0.0.0-20200203121303-549ecf2daaa1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ=
|
||||||
github.com/nspcc-dev/neofs-crypto v0.2.0 h1:ftN+59WqxSWz/RCgXYOfhmltOOqU+udsNQSvN6wkFck=
|
github.com/nspcc-dev/neofs-crypto v0.2.0 h1:ftN+59WqxSWz/RCgXYOfhmltOOqU+udsNQSvN6wkFck=
|
||||||
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
|
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
|
||||||
github.com/nspcc-dev/neofs-crypto v0.2.3 h1:aca3X2aly92ENRbFK+kH6Hd+J9EQ4Eu6XMVoITSIKtc=
|
github.com/nspcc-dev/neofs-crypto v0.2.3 h1:aca3X2aly92ENRbFK+kH6Hd+J9EQ4Eu6XMVoITSIKtc=
|
||||||
|
|
|
@ -540,17 +540,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
}
|
}
|
||||||
// Do not swap for builtin functions.
|
// Do not swap for builtin functions.
|
||||||
if !isBuiltin {
|
if !isBuiltin {
|
||||||
if numArgs == 2 {
|
c.emitReverse(numArgs)
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.SWAP)
|
|
||||||
} else if numArgs == 3 {
|
|
||||||
emit.Int(c.prog.BinWriter, 2)
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.XSWAP)
|
|
||||||
} else {
|
|
||||||
for i := 1; i < numArgs; i++ {
|
|
||||||
emit.Int(c.prog.BinWriter, int64(i))
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.ROLL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check builtin first to avoid nil pointer on funcScope!
|
// Check builtin first to avoid nil pointer on funcScope!
|
||||||
|
@ -680,6 +670,22 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emitReverse reverses top num items of the stack.
|
||||||
|
func (c *codegen) emitReverse(num int) {
|
||||||
|
switch num {
|
||||||
|
case 2:
|
||||||
|
emit.Opcode(c.prog.BinWriter, opcode.SWAP)
|
||||||
|
case 3:
|
||||||
|
emit.Int(c.prog.BinWriter, 2)
|
||||||
|
emit.Opcode(c.prog.BinWriter, opcode.XSWAP)
|
||||||
|
default:
|
||||||
|
for i := 1; i < num; i++ {
|
||||||
|
emit.Int(c.prog.BinWriter, int64(i))
|
||||||
|
emit.Opcode(c.prog.BinWriter, opcode.ROLL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *codegen) getEqualityOpcode(expr ast.Expr) opcode.Opcode {
|
func (c *codegen) getEqualityOpcode(expr ast.Expr) opcode.Opcode {
|
||||||
t, ok := c.typeInfo.Types[expr].Type.Underlying().(*types.Basic)
|
t, ok := c.typeInfo.Types[expr].Type.Underlying().(*types.Basic)
|
||||||
if ok && t.Info()&types.IsNumeric != 0 {
|
if ok && t.Info()&types.IsNumeric != 0 {
|
||||||
|
@ -780,6 +786,9 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
|
||||||
case "VerifySignature":
|
case "VerifySignature":
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.VERIFY)
|
emit.Opcode(c.prog.BinWriter, opcode.VERIFY)
|
||||||
case "AppCall":
|
case "AppCall":
|
||||||
|
numArgs := len(expr.Args) - 1
|
||||||
|
c.emitReverse(numArgs)
|
||||||
|
|
||||||
emit.Opcode(c.prog.BinWriter, opcode.APPCALL)
|
emit.Opcode(c.prog.BinWriter, opcode.APPCALL)
|
||||||
buf := c.getByteArray(expr.Args[0])
|
buf := c.getByteArray(expr.Args[0])
|
||||||
if len(buf) != 20 {
|
if len(buf) != 20 {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package compiler_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -55,10 +54,8 @@ func TestFromAddress(t *testing.T) {
|
||||||
func TestAppCall(t *testing.T) {
|
func TestAppCall(t *testing.T) {
|
||||||
srcInner := `
|
srcInner := `
|
||||||
package foo
|
package foo
|
||||||
func Main(args []interface{}) int {
|
func Main(a []byte, b []byte) []byte {
|
||||||
a := args[0].(int)
|
return append(a, b...)
|
||||||
b := args[1].(int)
|
|
||||||
return a + b
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -80,7 +77,7 @@ func TestAppCall(t *testing.T) {
|
||||||
|
|
||||||
require.NoError(t, v.Run())
|
require.NoError(t, v.Run())
|
||||||
|
|
||||||
assertResult(t, v, big.NewInt(42))
|
assertResult(t, v, []byte{1, 2, 3, 4})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("missing script", func(t *testing.T) {
|
t.Run("missing script", func(t *testing.T) {
|
||||||
|
@ -106,11 +103,11 @@ func TestAppCall(t *testing.T) {
|
||||||
package foo
|
package foo
|
||||||
import "github.com/CityOfZion/neo-go/pkg/interop/engine"
|
import "github.com/CityOfZion/neo-go/pkg/interop/engine"
|
||||||
const scriptHash = ` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `
|
const scriptHash = ` + fmt.Sprintf("%#v", string(ih.BytesBE())) + `
|
||||||
func Main() int {
|
func Main() []byte {
|
||||||
x := 13
|
x := []byte{1, 2}
|
||||||
y := 29
|
y := []byte{3, 4}
|
||||||
result := engine.AppCall([]byte(scriptHash), []interface{}{x, y})
|
result := engine.AppCall([]byte(scriptHash), x, y)
|
||||||
return result.(int)
|
return result.([]byte)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -119,7 +116,7 @@ func TestAppCall(t *testing.T) {
|
||||||
|
|
||||||
require.NoError(t, v.Run())
|
require.NoError(t, v.Run())
|
||||||
|
|
||||||
assertResult(t, v, big.NewInt(42))
|
assertResult(t, v, []byte{1, 2, 3, 4})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,11 +124,11 @@ func getAppCallScript(h string) string {
|
||||||
return `
|
return `
|
||||||
package foo
|
package foo
|
||||||
import "github.com/CityOfZion/neo-go/pkg/interop/engine"
|
import "github.com/CityOfZion/neo-go/pkg/interop/engine"
|
||||||
func Main() int {
|
func Main() []byte {
|
||||||
x := 13
|
x := []byte{1, 2}
|
||||||
y := 29
|
y := []byte{3, 4}
|
||||||
result := engine.AppCall(` + h + `, []interface{}{x, y})
|
result := engine.AppCall(` + h + `, x, y)
|
||||||
return result.(int)
|
return result.([]byte)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,6 @@ func GetEntryScriptHash() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppCall executes script with specified hash using provided arguments.
|
// AppCall executes script with specified hash using provided arguments.
|
||||||
func AppCall(scriptHash []byte, args []interface{}) interface{} {
|
func AppCall(scriptHash []byte, args ...interface{}) interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue