vm: implement CLEARITEMS opcode
This commit is contained in:
parent
9fd04aefa5
commit
48a41bd737
4 changed files with 65 additions and 4 deletions
|
@ -160,7 +160,7 @@ const (
|
||||||
SETITEM Opcode = 0xD0
|
SETITEM Opcode = 0xD0
|
||||||
REVERSEITEMS Opcode = 0xD1
|
REVERSEITEMS Opcode = 0xD1
|
||||||
REMOVE Opcode = 0xD2
|
REMOVE Opcode = 0xD2
|
||||||
// CLEARITEMS Opcode = 0xD3
|
CLEARITEMS Opcode = 0xD3
|
||||||
|
|
||||||
// Exceptions
|
// Exceptions
|
||||||
THROW Opcode = 0xF0
|
THROW Opcode = 0xF0
|
||||||
|
|
|
@ -138,11 +138,12 @@ func _() {
|
||||||
_ = x[SETITEM-208]
|
_ = x[SETITEM-208]
|
||||||
_ = x[REVERSEITEMS-209]
|
_ = x[REVERSEITEMS-209]
|
||||||
_ = x[REMOVE-210]
|
_ = x[REMOVE-210]
|
||||||
|
_ = x[CLEARITEMS-211]
|
||||||
_ = x[THROW-240]
|
_ = x[THROW-240]
|
||||||
_ = x[THROWIFNOT-241]
|
_ = x[THROWIFNOT-241]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPISNULLXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINSHA1SHA256HASH160HASH256CHECKSIGVERIFYCHECKMULTISIGPACKUNPACKNEWARRAY0NEWARRAYNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVETHROWTHROWIFNOT"
|
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPISNULLXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINSHA1SHA256HASH160HASH256CHECKSIGVERIFYCHECKMULTISIGPACKUNPACKNEWARRAY0NEWARRAYNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSTHROWTHROWIFNOT"
|
||||||
|
|
||||||
var _Opcode_map = map[Opcode]string{
|
var _Opcode_map = map[Opcode]string{
|
||||||
0: _Opcode_name[0:8],
|
0: _Opcode_name[0:8],
|
||||||
|
@ -273,8 +274,9 @@ var _Opcode_map = map[Opcode]string{
|
||||||
208: _Opcode_name[703:710],
|
208: _Opcode_name[703:710],
|
||||||
209: _Opcode_name[710:722],
|
209: _Opcode_name[710:722],
|
||||||
210: _Opcode_name[722:728],
|
210: _Opcode_name[722:728],
|
||||||
240: _Opcode_name[728:733],
|
211: _Opcode_name[728:738],
|
||||||
241: _Opcode_name[733:743],
|
240: _Opcode_name[738:743],
|
||||||
|
241: _Opcode_name[743:753],
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Opcode) String() string {
|
func (i Opcode) String() string {
|
||||||
|
|
22
pkg/vm/vm.go
22
pkg/vm/vm.go
|
@ -1106,6 +1106,28 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
panic("REMOVE: invalid type")
|
panic("REMOVE: invalid type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case opcode.CLEARITEMS:
|
||||||
|
elem := v.estack.Pop()
|
||||||
|
switch t := elem.value.(type) {
|
||||||
|
case *ArrayItem:
|
||||||
|
for _, item := range t.value {
|
||||||
|
v.estack.updateSizeRemove(item)
|
||||||
|
}
|
||||||
|
t.value = t.value[:0]
|
||||||
|
case *StructItem:
|
||||||
|
for _, item := range t.value {
|
||||||
|
v.estack.updateSizeRemove(item)
|
||||||
|
}
|
||||||
|
t.value = t.value[:0]
|
||||||
|
case *MapItem:
|
||||||
|
for i := range t.value {
|
||||||
|
v.estack.updateSizeRemove(t.value[i].Value)
|
||||||
|
}
|
||||||
|
t.value = t.value[:0]
|
||||||
|
default:
|
||||||
|
panic("CLEARITEMS: invalid type")
|
||||||
|
}
|
||||||
|
|
||||||
case opcode.SIZE:
|
case opcode.SIZE:
|
||||||
elem := v.estack.Pop()
|
elem := v.estack.Pop()
|
||||||
// Cause there is no native (byte) item type here, hence we need to check
|
// Cause there is no native (byte) item type here, hence we need to check
|
||||||
|
|
|
@ -2713,6 +2713,43 @@ func TestREMOVEMap(t *testing.T) {
|
||||||
assert.Equal(t, makeStackItem(false), vm.estack.Pop().value)
|
assert.Equal(t, makeStackItem(false), vm.estack.Pop().value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testCLEARITEMS(t *testing.T, item StackItem) {
|
||||||
|
prog := makeProgram(opcode.DUP, opcode.DUP, opcode.CLEARITEMS, opcode.SIZE)
|
||||||
|
v := load(prog)
|
||||||
|
v.estack.PushVal(item)
|
||||||
|
runVM(t, v)
|
||||||
|
require.Equal(t, 2, v.estack.Len())
|
||||||
|
require.EqualValues(t, 2, v.size) // empty collection + it's size
|
||||||
|
require.EqualValues(t, 0, v.estack.Pop().BigInt().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCLEARITEMS(t *testing.T) {
|
||||||
|
arr := []StackItem{NewBigIntegerItem(big.NewInt(1)), NewByteArrayItem([]byte{1})}
|
||||||
|
m := NewMapItem()
|
||||||
|
m.Add(NewBigIntegerItem(big.NewInt(1)), NewByteArrayItem([]byte{}))
|
||||||
|
m.Add(NewByteArrayItem([]byte{42}), NewBigIntegerItem(big.NewInt(2)))
|
||||||
|
|
||||||
|
testCases := map[string]StackItem{
|
||||||
|
"empty Array": NewArrayItem([]StackItem{}),
|
||||||
|
"filled Array": NewArrayItem(arr),
|
||||||
|
"empty Struct": NewStructItem([]StackItem{}),
|
||||||
|
"filled Struct": NewStructItem(arr),
|
||||||
|
"empty Map": NewMapItem(),
|
||||||
|
"filled Map": m,
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, item := range testCases {
|
||||||
|
t.Run(name, func(t *testing.T) { testCLEARITEMS(t, item) })
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("Integer", func(t *testing.T) {
|
||||||
|
prog := makeProgram(opcode.CLEARITEMS)
|
||||||
|
v := load(prog)
|
||||||
|
v.estack.PushVal(1)
|
||||||
|
checkVMFailed(t, v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestSWAPGood(t *testing.T) {
|
func TestSWAPGood(t *testing.T) {
|
||||||
prog := makeProgram(opcode.SWAP)
|
prog := makeProgram(opcode.SWAP)
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
|
|
Loading…
Reference in a new issue