From 9402540c3a3ca471bfd6a301d6764f872cf18cc0 Mon Sep 17 00:00:00 2001 From: dauTT <30392990+dauTT@users.noreply.github.com> Date: Fri, 29 Mar 2019 20:35:16 +0100 Subject: [PATCH] Implemented LT, GT opcode (#259) * Implemented LT, GT opcode --- pkg/vm/stack/Int.go | 14 +++++++++ pkg/vm/vm_ops.go | 3 ++ pkg/vm/vm_ops_maths.go | 32 ++++++++++++++++++++ pkg/vm/vm_ops_maths_test.go | 58 +++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+) diff --git a/pkg/vm/stack/Int.go b/pkg/vm/stack/Int.go index 52e6240d4..3226904ee 100644 --- a/pkg/vm/stack/Int.go +++ b/pkg/vm/stack/Int.go @@ -111,3 +111,17 @@ func (i *Int) Abs() (*Int, error) { return b, nil } + +// Lt returns a bool value from the comparison of two integers, a and b. +// value is true if a < b. +// value is false if a >= b. +func (i *Int) Lt(s *Int) bool { + return i.Value().Cmp(s.Value()) == -1 +} + +// Gt returns a bool value from the comparison of two integers, a and b. +// value is true if a > b. +// value is false if a <= b. +func (i *Int) Gt(s *Int) bool { + return i.Value().Cmp(s.Value()) == 1 +} diff --git a/pkg/vm/vm_ops.go b/pkg/vm/vm_ops.go index cef46a199..1854b1634 100644 --- a/pkg/vm/vm_ops.go +++ b/pkg/vm/vm_ops.go @@ -5,6 +5,9 @@ import "github.com/CityOfZion/neo-go/pkg/vm/stack" type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) var opFunc = map[stack.Instruction]stackInfo{ + + stack.LT: Lt, + stack.GT: Gt, stack.SHR: Shr, stack.SHL: Shl, stack.INC: Inc, diff --git a/pkg/vm/vm_ops_maths.go b/pkg/vm/vm_ops_maths.go index 5cbe0552a..7abd73b9f 100644 --- a/pkg/vm/vm_ops_maths.go +++ b/pkg/vm/vm_ops_maths.go @@ -300,6 +300,38 @@ func Shr(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst return NONE, nil } +// Lt pops two integers, a and b, off of the stack and pushes a boolean the stack +// whose value is true if a's value is less than b's value. +// Returns an error if either items cannot be casted to an integer +func Lt(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) { + + operandA, operandB, err := popTwoIntegers(ctx) + if err != nil { + return FAULT, err + } + res := operandB.Lt(operandA) + + ctx.Estack.Push(stack.NewBoolean(res)) + + return NONE, nil +} + +// Gt pops two integers, a and b, off of the stack and pushes a boolean the stack +// whose value is true if a's value is greated than b's value. +// Returns an error if either items cannot be casted to an integer +func Gt(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) { + + operandA, operandB, err := popTwoIntegers(ctx) + if err != nil { + return FAULT, err + } + res := operandB.Gt(operandA) + + ctx.Estack.Push(stack.NewBoolean(res)) + + return NONE, nil +} + func popTwoByteArrays(ctx *stack.Context) (*stack.ByteArray, *stack.ByteArray, error) { // Pop first stack item and cast as byte array ba1, err := ctx.Estack.PopByteArray() diff --git a/pkg/vm/vm_ops_maths_test.go b/pkg/vm/vm_ops_maths_test.go index b703751be..29d843999 100644 --- a/pkg/vm/vm_ops_maths_test.go +++ b/pkg/vm/vm_ops_maths_test.go @@ -394,3 +394,61 @@ func TestShrOp(t *testing.T) { assert.Equal(t, int64(2), item.Value().Int64()) } + +func TestLtOp(t *testing.T) { + + v := VM{} + + a, err := stack.NewInt(big.NewInt(10)) + assert.NoError(t, err) + + b, err := stack.NewInt(big.NewInt(2)) + assert.NoError(t, err) + + ctx := stack.NewContext([]byte{}) + ctx.Estack.Push(a).Push(b) + + // b is the first item pop. + // a is the second item pop. + // we perform a < b and place + // the result on top of the evaluation + // stack + v.executeOp(stack.LT, ctx) + + // Stack should have one item + assert.Equal(t, 1, ctx.Estack.Len()) + + item, err := ctx.Estack.PopBoolean() + assert.NoError(t, err) + + assert.Equal(t, false, item.Value()) +} + +func TestGtOp(t *testing.T) { + + v := VM{} + + a, err := stack.NewInt(big.NewInt(10)) + assert.NoError(t, err) + + b, err := stack.NewInt(big.NewInt(2)) + assert.NoError(t, err) + + ctx := stack.NewContext([]byte{}) + ctx.Estack.Push(a).Push(b) + + // b is the first item pop. + // a is the second item pop. + // we perform a > b and place + // the result on top of the evaluation + // stack + v.executeOp(stack.GT, ctx) + + // Stack should have one item + assert.Equal(t, 1, ctx.Estack.Len()) + + item, err := ctx.Estack.PopBoolean() + assert.NoError(t, err) + + assert.Equal(t, true, item.Value()) +}