diff --git a/pkg/vm/state.go b/pkg/vm/state.go new file mode 100644 index 000000000..4090ec86e --- /dev/null +++ b/pkg/vm/state.go @@ -0,0 +1,10 @@ +package vm + +type vmstate byte + +const ( + NONE = 0 + HALT = 1 << 0 + FAULT = 1 << 1 + BREAK = 1 << 2 +) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go new file mode 100644 index 000000000..1793be031 --- /dev/null +++ b/pkg/vm/vm.go @@ -0,0 +1,38 @@ +package vm + +import ( + "fmt" + + "github.com/CityOfZion/neo-go/pkg/vm/stack" +) + +// VM represents an instance of a Neo Virtual Machine +type VM struct { + InvocationStack stack.Invocation + state vmstate +} + +//NewVM loads in a script +// uses the script to initiate a Context object +// pushes the context to the invocation stack +func NewVM(script []byte) *VM { + ctx := stack.NewContext(script) + v := &VM{ + state: NONE, + } + v.InvocationStack.Push(ctx) + return v +} + +// ExecuteOp will execute one opcode for a given context +func (v *VM) ExecuteOp(op stack.Instruction, ctx *stack.Context) error { + handleOp, ok := opFunc[op] + if !ok { + return fmt.Errorf("unknown opcode entered %v", op) + } + err := handleOp(ctx, &v.InvocationStack) + if err != nil { + return err + } + return nil +} diff --git a/pkg/vm/vm_ops_maths_test.go b/pkg/vm/vm_ops_maths_test.go new file mode 100644 index 000000000..a9d80373a --- /dev/null +++ b/pkg/vm/vm_ops_maths_test.go @@ -0,0 +1,39 @@ +package vm + +import ( + "math/big" + "testing" + + "github.com/CityOfZion/neo-go/pkg/vm/stack" + "github.com/stretchr/testify/assert" +) + +func TestAddOp(t *testing.T) { + + v := VM{} + + a, err := stack.NewInt(big.NewInt(20)) + if err != nil { + t.Fail() + } + b, err := stack.NewInt(big.NewInt(23)) + if err != nil { + t.Fail() + } + + ctx := stack.NewContext([]byte{}) + ctx.Estack.Push(a).Push(b) + + v.ExecuteOp(stack.ADD, 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(43), item.Value().Int64()) + +}