VM: Implemented SIGN, NEGATE opcode (#232)

* Implemented SIGN, NEGATE opcode
This commit is contained in:
dauTT 2019-03-28 19:30:36 +01:00 committed by decentralisedkev
parent d8e399f67d
commit 14e0ab48dd
3 changed files with 95 additions and 2 deletions

View file

@ -7,6 +7,8 @@ type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invo
var opFunc = map[stack.Instruction]stackInfo{ var opFunc = map[stack.Instruction]stackInfo{
stack.INC: Inc, stack.INC: Inc,
stack.DEC: Dec, stack.DEC: Dec,
stack.SIGN: Sign,
stack.NEGATE: Negate,
stack.ADD: Add, stack.ADD: Add,
stack.SUB: Sub, stack.SUB: Sub,
stack.PUSHBYTES1: PushNBytes, stack.PUSHBYTES1: PushNBytes,

View file

@ -46,7 +46,7 @@ func Sub(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
// Inc increments the stack Item's value by 1. // Inc increments the stack Item's value by 1.
// Returns an error if the item cannot be casted to an integer // Returns an error if the item cannot be casted to an integer
// or if 1 cannot be added to the item // or if 1 cannot be added to the item.
func Inc(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) { func Inc(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
i, err := ctx.Estack.PopInt() i, err := ctx.Estack.PopInt()
@ -71,7 +71,7 @@ func Inc(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
// Dec decrements the stack Item's value by 1. // Dec decrements the stack Item's value by 1.
// Returns an error if the item cannot be casted to an integer // Returns an error if the item cannot be casted to an integer
// or if 1 cannot be subtracted to the item // or if 1 cannot be subtracted to the item.
func Dec(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) { func Dec(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
i, err := ctx.Estack.PopInt() i, err := ctx.Estack.PopInt()
@ -94,6 +94,47 @@ func Dec(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
return NONE, nil return NONE, nil
} }
// Sign puts the sign of the top stack Item on top of the stack.
// If value is negative, put -1;
// If positive, put 1;
// If value is zero, put 0.
func Sign(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
i, err := ctx.Estack.PopInt()
if err != nil {
return FAULT, err
}
s := int64(i.Value().Sign())
sign, err := stack.NewInt(big.NewInt(s))
if err != nil {
return FAULT, err
}
ctx.Estack.Push(sign)
return NONE, nil
}
// Negate flips the sign of the stack Item.
func Negate(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
i, err := ctx.Estack.PopInt()
if err != nil {
return FAULT, err
}
a := big.NewInt(0).Neg(i.Value())
b, err := stack.NewInt(a)
if err != nil {
return FAULT, err
}
ctx.Estack.Push(b)
return NONE, nil
}
func popTwoIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, error) { func popTwoIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, error) {
operandA, err := ctx.Estack.PopInt() operandA, err := ctx.Estack.PopInt()
if err != nil { if err != nil {

View file

@ -117,3 +117,53 @@ func TestSubOp(t *testing.T) {
assert.Equal(t, int64(-10), item.Value().Int64()) assert.Equal(t, int64(-10), item.Value().Int64())
} }
func TestSignOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(-20))
if err != nil {
t.Fail()
}
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a)
v.executeOp(stack.SIGN, ctx)
// Stack should have one item
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Equal(t, int64(-1), item.Value().Int64())
}
func TestNegateOp(t *testing.T) {
v := VM{}
a, err := stack.NewInt(big.NewInt(-20))
if err != nil {
t.Fail()
}
ctx := stack.NewContext([]byte{})
ctx.Estack.Push(a)
v.executeOp(stack.NEGATE, ctx)
// Stack should have one item
assert.Equal(t, 1, ctx.Estack.Len())
item, err := ctx.Estack.PopInt()
if err != nil {
t.Fail()
}
assert.Equal(t, int64(20), item.Value().Int64())
}