diff --git a/pkg/compiler/byte_conversion_test.go b/pkg/compiler/byte_conversion_test.go index 1bbacade5..e896b4022 100644 --- a/pkg/compiler/byte_conversion_test.go +++ b/pkg/compiler/byte_conversion_test.go @@ -54,3 +54,28 @@ func TestByteConversionDirectlyInFunctionCall(t *testing.T) { ` eval(t, src, []byte("foo")) } + +func TestByteConversionOfConstant(t *testing.T) { + src := ` + package foo + const foo = "foo" + func Main() []byte { + b := []byte(foo) + return b + } + ` + eval(t, src, []byte("foo")) +} + +func TestByteConversionOfVariable(t *testing.T) { + src := ` + package foo + func Main() []byte { + a := "fo" + a = a + "o" + b := []byte(a) + return b + } + ` + eval(t, src, []byte("foo")) +} diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 1023bd142..d9c0ebb41 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -349,6 +349,8 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { return nil } c.emitLoadConst(value) + } else if tv := c.typeInfo.Types[n]; tv.Value != nil { + c.emitLoadConst(tv) } else { c.emitLoadLocal(n.Name) } @@ -481,11 +483,9 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { return nil } case *ast.ArrayType: - // For now we will assume that there is only 1 argument passed which - // will be a basic literal (string kind). This only to handle string - // to byte slice conversions. E.G. []byte("foobar") - arg := n.Args[0].(*ast.BasicLit) - c.emitLoadConst(c.typeInfo.Types[arg]) + // For now we will assume that there are only byte slice conversions. + // E.g. []byte("foobar") or []byte(scriptHash). + ast.Walk(c, n.Args[0]) return nil } @@ -672,6 +672,13 @@ func (c *codegen) getByteArray(expr ast.Expr) []byte { buf[i] = byte(val) } return buf + case *ast.CallExpr: + if tv := c.typeInfo.Types[t.Args[0]]; tv.Value != nil { + val := constant.StringVal(tv.Value) + return []byte(val) + } + + return nil default: return nil } diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index f1e0e1748..29831477f 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -100,6 +100,27 @@ func TestAppCall(t *testing.T) { _, err := compiler.Compile(strings.NewReader(src)) require.Error(t, err) }) + + t.Run("convert from string constant", func(t *testing.T) { + src := ` + package foo + import "github.com/CityOfZion/neo-go/pkg/interop/engine" + const scriptHash = ` + fmt.Sprintf("%#v", string(ih.BytesBE())) + ` + func Main() int { + x := 13 + y := 29 + result := engine.AppCall([]byte(scriptHash), []interface{}{x, y}) + return result.(int) + } + ` + + v := vmAndCompile(t, src) + v.SetScriptGetter(getScript) + + require.NoError(t, v.Run()) + + assertResult(t, v, big.NewInt(42)) + }) } func getAppCallScript(h string) string {