From a6d60e387a6c53d8b629a645e7c86847a53fe977 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 17 Dec 2019 16:56:58 +0300 Subject: [PATCH] vm: fix OVER and PICK to duplicate stack items TestPICKDup and TestOVERDup failed without this. --- pkg/vm/vm.go | 4 ++-- pkg/vm/vm_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 1d36341b2..825780737 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -622,7 +622,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } case opcode.OVER: - a := v.estack.Peek(1) + a := v.estack.Dup(1) if a == nil { panic("no second element found") } @@ -633,7 +633,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro if n < 0 { panic("negative stack item returned") } - a := v.estack.Peek(n) + a := v.estack.Dup(n) if a == nil { panic("no nth element found") } diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index dc68d19e1..ef701a792 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -1497,6 +1497,21 @@ func TestPICKgood(t *testing.T) { assert.Equal(t, int64(result), vm.estack.Pop().BigInt().Int64()) } +func TestPICKDup(t *testing.T) { + prog := makeProgram(opcode.PUSHM1, opcode.PUSH0, + opcode.PUSH1, + opcode.PUSH2, + opcode.PICK, + opcode.ABS) + vm := load(prog) + runVM(t, vm) + assert.Equal(t, 4, vm.estack.Len()) + assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64()) + assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64()) + assert.Equal(t, int64(0), vm.estack.Pop().BigInt().Int64()) + assert.Equal(t, int64(-1), vm.estack.Pop().BigInt().Int64()) +} + func TestROTBad(t *testing.T) { prog := makeProgram(opcode.ROT) vm := load(prog) @@ -1663,6 +1678,22 @@ func TestOVERgood(t *testing.T) { assert.Equal(t, 3, vm.estack.Len()) } +func TestOVERDup(t *testing.T) { + prog := makeProgram(opcode.PUSHBYTES2, 1, 0, + opcode.PUSH1, + opcode.OVER, + opcode.PUSH1, + opcode.LEFT, + opcode.PUSHBYTES1, 2, + opcode.CAT) + vm := load(prog) + runVM(t, vm) + assert.Equal(t, 3, vm.estack.Len()) + assert.Equal(t, []byte{0x01, 0x02}, vm.estack.Pop().Bytes()) + assert.Equal(t, int64(1), vm.estack.Pop().BigInt().Int64()) + assert.Equal(t, []byte{0x01, 0x00}, vm.estack.Pop().Bytes()) +} + func TestNIPBadNoItem(t *testing.T) { prog := makeProgram(opcode.NIP) vm := load(prog)