VM:Implement THROW opcode (#219)

[VM]

- Changed vmstate from HALT to FAULT in Sub opcode
- Implemented THROW opcode + tests
- Renamed TestSimpleRun test to TestThrowIfNot
This commit is contained in:
dauTT 2019-03-26 22:19:41 +01:00 committed by decentralisedkev
parent 9951f04099
commit 24cd21bd8c
4 changed files with 36 additions and 2 deletions

View file

@ -12,6 +12,7 @@ var opFunc = map[stack.Instruction]stackInfo{
stack.RET: RET, stack.RET: RET,
stack.EQUAL: EQUAL, stack.EQUAL: EQUAL,
stack.THROWIFNOT: THROWIFNOT, stack.THROWIFNOT: THROWIFNOT,
stack.THROW: THROW,
} }
func init() { func init() {

View file

@ -31,3 +31,9 @@ func THROWIFNOT(op stack.Instruction, ctx *stack.Context, istack *stack.Invocati
} }
return NONE, nil return NONE, nil
} }
// THROW returns a FAULT VM state. This indicate that there is an error in the
// current context loaded program.
func THROW(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
return FAULT, errors.New("the execution of the script program end with an error")
}

View file

@ -34,7 +34,7 @@ func Sub(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
} }
res, err := operandB.Sub(operandA) res, err := operandB.Sub(operandA)
if err != nil { if err != nil {
return HALT, err return FAULT, err
} }
ctx.Estack.Push(res) ctx.Estack.Push(res)

View file

@ -61,7 +61,7 @@ func TestPushAdd(t *testing.T) {
} }
func TestSimpleRun(t *testing.T) { func TestThrowIfNot(t *testing.T) {
// Program pushes 20 and 34 to the stack // Program pushes 20 and 34 to the stack
// Adds them together // Adds them together
@ -89,6 +89,33 @@ func TestSimpleRun(t *testing.T) {
// ResultStack should be nil // ResultStack should be nil
assert.Equal(t, -1, vm.ResultStack.Len()) assert.Equal(t, -1, vm.ResultStack.Len())
// InvocationStack should be empty
assert.Equal(t, 0, vm.InvocationStack.Len())
}
func TestThrow(t *testing.T) {
// Program pushes 20 to the stack
// exits with an error
// Push(20)
// THROW
builder := stack.NewBuilder()
builder.EmitInt(20).EmitOpcode(stack.THROW)
// Pass program to VM
vm := NewVM(builder.Bytes())
// Runs vm with program
_, err := vm.Run()
assert.NotNil(t, err)
ctx, err := vm.InvocationStack.CurrentContext()
assert.Equal(t, nil, err)
assert.Equal(t, 1, ctx.Estack.Len())
assert.Equal(t, -1, ctx.Astack.Len())
} }
// returns true if the value at the top of the evaluation stack is a integer // returns true if the value at the top of the evaluation stack is a integer