From 4f3de1a9af22bb129484d2f9b4f9e8c32e87c915 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Fri, 10 Sep 2021 15:29:13 +0300 Subject: [PATCH] [#822] moprh/event: Add parsers from Op struct Signed-off-by: Pavel Karpy --- pkg/morph/event/opcodes.go | 31 ++++++++++++- pkg/morph/event/opcodes_test.go | 82 +++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 pkg/morph/event/opcodes_test.go diff --git a/pkg/morph/event/opcodes.go b/pkg/morph/event/opcodes.go index 1300e4478..b4fee6fee 100644 --- a/pkg/morph/event/opcodes.go +++ b/pkg/morph/event/opcodes.go @@ -1,6 +1,11 @@ package event -import "github.com/nspcc-dev/neo-go/pkg/vm/opcode" +import ( + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" + "github.com/nspcc-dev/neo-go/pkg/vm/opcode" +) // Op is wrapper over Neo VM's opcode // and its parameter. @@ -19,3 +24,27 @@ func (o Op) Code() opcode.Opcode { func (o Op) Param() []byte { return o.param } + +// BytesFromOpcode tries to retrieve bytes from Op. +func BytesFromOpcode(op Op) ([]byte, error) { + switch code := op.Code(); code { + case opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4: + return op.Param(), nil + default: + return nil, fmt.Errorf("unexpected ByteArray opcode %s", code) + } +} + +// IntFromOpcode tries to retrieve bytes from Op. +func IntFromOpcode(op Op) (int64, error) { + switch code := op.Code(); { + case code == opcode.PUSHM1: + return -1, nil + case code >= opcode.PUSH0 && code <= opcode.PUSH16: + return int64(code - opcode.PUSH0), nil + case code <= opcode.PUSHINT256: + return bigint.FromBytes(op.Param()).Int64(), nil + default: + return 0, fmt.Errorf("unexpected INT opcode %s", code) + } +} diff --git a/pkg/morph/event/opcodes_test.go b/pkg/morph/event/opcodes_test.go new file mode 100644 index 000000000..fa8673778 --- /dev/null +++ b/pkg/morph/event/opcodes_test.go @@ -0,0 +1,82 @@ +package event + +import ( + "testing" + + "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/vm" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/stretchr/testify/require" +) + +func TestBytesFromOpcode(t *testing.T) { + tests := [...][]byte{ + []byte("test"), + []byte("test test"), + []byte(""), + []byte("1"), + } + + bw := io.NewBufBinWriter() + + for _, test := range tests { + emit.Bytes(bw.BinWriter, test) + } + + var ( + ctx = vm.NewContext(bw.Bytes()) + + op Op + + gotBytes []byte + err error + ) + + for _, test := range tests { + op = getNextOp(ctx) + + gotBytes, err = BytesFromOpcode(op) + + require.NoError(t, err) + require.Equal(t, test, gotBytes) + } +} + +func TestIntFromOpcode(t *testing.T) { + tests := [...]int64{ + -1, + -5, + 15, + 16, + 1_000_000, + } + + bw := io.NewBufBinWriter() + + for _, test := range tests { + emit.Int(bw.BinWriter, test) + } + + var ( + ctx = vm.NewContext(bw.Bytes()) + + op Op + + gotInt int64 + err error + ) + + for _, test := range tests { + op = getNextOp(ctx) + + gotInt, err = IntFromOpcode(op) + + require.NoError(t, err) + require.Equal(t, test, gotInt) + } +} + +func getNextOp(ctx *vm.Context) (op Op) { + op.code, op.param, _ = ctx.Next() + return +}