nspcc-dev / neo-go

Go Node and SDK for the Neo blockchain
MIT License
125 stars 79 forks source link

compiler: problems with converting builtin `append` expression with byte slice argument #2696

Closed AnnaShaleva closed 2 years ago

AnnaShaleva commented 2 years ago

Given the following function defined in pkg/interop/util/util.go:

// Hash160ToAddress is an utility function that converts given Hash160 to
// Base58-encoded Neo address.
func Hash160ToAddress(hash interop.Hash160) string {
    b := append([]byte{AddressPrefix}, hash...)
    return std.Base58CheckEncode(b)
}

And the following contract that uses this function:

func TestAddressToFromHash160(t *testing.T) {
    a := "NQRLhCpAru9BjGsMwk67vdMwmzKMRgsnnN"
    h, err := address.StringToUint160(a)
    require.NoError(t, err)

    bc, acc := chain.NewSingle(t)
    e := neotest.NewExecutor(t, bc, acc, acc)
    src := `package foo
        import "github.com/nspcc-dev/neo-go/pkg/interop/util"

        func ToHash160(hash []byte) string {
            return util.Hash160ToAddress(hash)
        }`
    ctr := neotest.CompileSource(t, e.CommitteeHash, strings.NewReader(src), &compiler.Options{Name: "Helper"})
    e.DeployContract(t, ctr, nil)
    c := e.CommitteeInvoker(ctr.Hash)

    c.Invoke(t, stackitem.NewByteArray([]byte(a)), "toHash160", h.BytesBE())
}

Compilation panic occurs:

=== RUN   TestAddressToFromHash160
    logger.go:130: 2022-09-16T19:57:10.980+0300 INFO    initial gas supply is not set or wrong, setting default value   {"InitialGASSupply": "52000000"}
    logger.go:130: 2022-09-16T19:57:10.980+0300 INFO    mempool size is not set or wrong, setting default value {"MemPoolSize": 50000}
    logger.go:130: 2022-09-16T19:57:10.980+0300 INFO    MaxBlockSize is not set or wrong, setting default value {"MaxBlockSize": 262144}
    logger.go:130: 2022-09-16T19:57:10.980+0300 INFO    MaxBlockSystemFee is not set or wrong, setting default value    {"MaxBlockSystemFee": 900000000000}
    logger.go:130: 2022-09-16T19:57:10.980+0300 INFO    MaxTransactionsPerBlock is not set or wrong, using default value    {"MaxTransactionsPerBlock": 512}
    logger.go:130: 2022-09-16T19:57:10.980+0300 INFO    MaxValidUntilBlockIncrement is not set or wrong, using default value    {"MaxValidUntilBlockIncrement": 86400}
    logger.go:130: 2022-09-16T19:57:10.980+0300 INFO    NativeActivations are not set, using default values
    logger.go:130: 2022-09-16T19:57:10.980+0300 INFO    Hardforks are not set, using default value
    logger.go:130: 2022-09-16T19:57:10.983+0300 INFO    no storage version found! creating genesis block
    logger.go:130: 2022-09-16T19:57:11.003+0300 INFO    persisted to disk   {"blocks": 0, "keys": 105, "headerHeight": 0, "blockHeight": 0, "took": "37.432µs"}
--- FAIL: TestAddressToFromHash160 (0.02s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
    panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x83343e]

goroutine 38 [running]:
testing.tRunner.func1.2({0xa32460, 0x11301f0})
    /usr/local/go/src/testing/testing.go:1209 +0x24e
testing.tRunner.func1()
    /usr/local/go/src/testing/testing.go:1212 +0x218
panic({0xa32460, 0x11301f0})
    /usr/local/go/src/runtime/panic.go:1038 +0x215
github.com/nspcc-dev/neo-go/pkg/compiler.isByteSlice({0x0, 0x0})
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/types.go:85 +0x1e
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).convertBuiltin(0xc000166780, 0xc0001881c0)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:1823 +0x6c5
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).Visit(0xc000166780, {0xcea708, 0xc0001881c0})
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:1027 +0x5f1c
go/ast.Walk({0xce1560, 0xc000166780}, {0xcea708, 0xc0001881c0})
    /usr/local/go/src/go/ast/walk.go:50 +0x5f
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).Visit(0xc000166780, {0xcea5c8, 0xc000188200})
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:653 +0x53ea
go/ast.Walk({0xce1560, 0xc000166780}, {0xcea5c8, 0xc000188200})
    /usr/local/go/src/go/ast/walk.go:50 +0x5f
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).Visit(0xc000166780, {0xcea6b8, 0xc000169410})
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:1198 +0x51b1
go/ast.Walk({0xce1560, 0xc000166780}, {0xcea6b8, 0xc000169410})
    /usr/local/go/src/go/ast/walk.go:50 +0x5f
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).inlineCall(0xc000166780, 0xc0002c4370, 0xc000189500)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/inline.go:119 +0xe45
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).Visit(0xc000166780, {0xcea708, 0xc000189500})
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:962 +0x1715
go/ast.Walk({0xce1560, 0xc000166780}, {0xcea708, 0xc000189500})
    /usr/local/go/src/go/ast/walk.go:50 +0x5f
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).Visit(0xc000166780, {0xceac30, 0xc00008f700})
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:741 +0x5b55
go/ast.Walk({0xce1560, 0xc000166780}, {0xceac30, 0xc00008f700})
    /usr/local/go/src/go/ast/walk.go:50 +0x5f
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).Visit(0xc000166780, {0xcea6b8, 0xc0001dc6f0})
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:1198 +0x51b1
go/ast.Walk({0xce1560, 0xc000166780}, {0xcea6b8, 0xc0001dc6f0})
    /usr/local/go/src/go/ast/walk.go:50 +0x5f
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).convertFuncDecl(0xc000166780, {0xcea938, 0xc0008fea80}, 0xc0001dc720, 0x2d)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:516 +0x99c
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).compile.func2(0xc0008fea80, 0xc00016b810)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:2182 +0x3f8
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).ForEachFile.func1(0xc0000e12c0)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/compiler.go:102 +0x82
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).ForEachPackage(0xc000166780, 0xc00030dab0)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/compiler.go:93 +0xc6
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).ForEachFile(0x9f1f40, 0xc0001da918)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/compiler.go:99 +0x45
github.com/nspcc-dev/neo-go/pkg/compiler.(*codegen).compile(0xc000166780, 0xc0001dcb70, 0x1)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:2169 +0x445
github.com/nspcc-dev/neo-go/pkg/compiler.codeGen(0xc0001dcb70)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/codegen.go:2223 +0x353
github.com/nspcc-dev/neo-go/pkg/compiler.CompileWithOptions({0xad6e1f, 0x40ef47}, {0xce2360, 0xc0002444c0}, 0xc0002f00e0)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/compiler.go:218 +0x65
github.com/nspcc-dev/neo-go/pkg/neotest.CompileSource({0xd01290, 0xc0002fe340}, {0xd8, 0xcc, 0x5a, 0x90, 0x4d, 0x52, 0x6f, 0xc9, ...}, ...)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/neotest/compile.go:32 +0xa5
github.com/nspcc-dev/neo-go/pkg/compiler_test.TestAddressToFromHash160(0x4079f9)
    /home/anna/Documents/GitProjects/nspcc-dev/neo-go/pkg/compiler/interop_test.go:195 +0x18d
testing.tRunner(0xc0002fe340, 0xc39c68)
    /usr/local/go/src/testing/testing.go:1259 +0x102
created by testing.(*T).Run
    /usr/local/go/src/testing/testing.go:1306 +0x35a

I saw somewhere that our compiler is able to use append for byte slices (not sure, couldn't find this in documentation), and interop.Hash160 is a byte slice under the hood, so I'd expect the compilation to succeed or at least not fail with panic. Need to investigate this issue.

AnnaShaleva commented 2 years ago

After that we need to refactor Hash160ToAddress interop's helper introduced in https://github.com/nspcc-dev/neo-go/pull/2698.