From 5f0f9e1638b66a75e54c87c5a2f4d60360ecc5cb Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 5 Sep 2019 15:18:04 +0300 Subject: [PATCH] vm: implement PICK instruction --- pkg/vm/vm.go | 8 ++++++++ pkg/vm/vm_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index a8c1df58c..11c7b3647 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -337,6 +337,14 @@ func (v *VM) execute(ctx *Context, op Instruction) { v.estack.Push(b) v.estack.Push(a) + case PICK: + n := int(v.estack.Pop().BigInt().Int64()) + if n < 0 { + panic("negative stack item returned") + } + a := v.estack.Peek(n) + v.estack.Push(a) + case ROLL: n := int(v.estack.Pop().BigInt().Int64()) if n < 0 { diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index b9ec5ee74..e80eabfb0 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -264,6 +264,39 @@ func TestNZfalse(t *testing.T) { assert.Equal(t, false, vm.estack.Pop().Bool()) } +func TestPICKbadNoitem(t *testing.T) { + prog := makeProgram(PICK) + vm := load(prog) + vm.estack.PushVal(1) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestPICKbadNegative(t *testing.T) { + prog := makeProgram(PICK) + vm := load(prog) + vm.estack.PushVal(-1) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestPICKgood(t *testing.T) { + prog := makeProgram(PICK) + result := 2 + vm := load(prog) + vm.estack.PushVal(0) + vm.estack.PushVal(1) + vm.estack.PushVal(result) + vm.estack.PushVal(3) + vm.estack.PushVal(4) + vm.estack.PushVal(5) + vm.estack.PushVal(3) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, int64(result), vm.estack.Pop().BigInt().Int64()) +} + + func makeProgram(opcodes ...Instruction) []byte { prog := make([]byte, len(opcodes)+1) // RET for i := 0; i < len(opcodes); i++ {