vm: fix OVER and PICK to duplicate stack items

TestPICKDup and TestOVERDup failed without this.
This commit is contained in:
Roman Khimov 2019-12-17 16:56:58 +03:00
parent 60dfa05b19
commit a6d60e387a
2 changed files with 33 additions and 2 deletions

View file

@ -622,7 +622,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
} }
case opcode.OVER: case opcode.OVER:
a := v.estack.Peek(1) a := v.estack.Dup(1)
if a == nil { if a == nil {
panic("no second element found") 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 { if n < 0 {
panic("negative stack item returned") panic("negative stack item returned")
} }
a := v.estack.Peek(n) a := v.estack.Dup(n)
if a == nil { if a == nil {
panic("no nth element found") panic("no nth element found")
} }

View file

@ -1497,6 +1497,21 @@ func TestPICKgood(t *testing.T) {
assert.Equal(t, int64(result), vm.estack.Pop().BigInt().Int64()) 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) { func TestROTBad(t *testing.T) {
prog := makeProgram(opcode.ROT) prog := makeProgram(opcode.ROT)
vm := load(prog) vm := load(prog)
@ -1663,6 +1678,22 @@ func TestOVERgood(t *testing.T) {
assert.Equal(t, 3, vm.estack.Len()) 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) { func TestNIPBadNoItem(t *testing.T) {
prog := makeProgram(opcode.NIP) prog := makeProgram(opcode.NIP)
vm := load(prog) vm := load(prog)