forked from TrueCloudLab/neoneo-go
vm: implement NEWARRAYT opcode
This commit is contained in:
parent
d3b9aef8e2
commit
7c3d7c0261
5 changed files with 75 additions and 29 deletions
|
@ -101,7 +101,7 @@ func (c *Context) Next() (opcode.Opcode, []byte, error) {
|
|||
}
|
||||
case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT, opcode.JMPEQ, opcode.JMPNE,
|
||||
opcode.JMPGT, opcode.JMPGE, opcode.JMPLT, opcode.JMPLE,
|
||||
opcode.CALL, opcode.ISTYPE:
|
||||
opcode.CALL, opcode.ISTYPE, opcode.NEWARRAYT:
|
||||
numtoread = 1
|
||||
case opcode.JMPL, opcode.JMPIFL, opcode.JMPIFNOTL, opcode.JMPEQL, opcode.JMPNEL,
|
||||
opcode.JMPGTL, opcode.JMPGEL, opcode.JMPLTL, opcode.JMPLEL,
|
||||
|
|
|
@ -143,11 +143,11 @@ const (
|
|||
CHECKMULTISIG Opcode = 0xAE
|
||||
|
||||
// Advanced data structures (arrays, structures, maps)
|
||||
PACK Opcode = 0xC0
|
||||
UNPACK Opcode = 0xC1
|
||||
NEWARRAY0 Opcode = 0xC2
|
||||
NEWARRAY Opcode = 0xC3
|
||||
// NEWARRAYT Opcode = 0xC4
|
||||
PACK Opcode = 0xC0
|
||||
UNPACK Opcode = 0xC1
|
||||
NEWARRAY0 Opcode = 0xC2
|
||||
NEWARRAY Opcode = 0xC3
|
||||
NEWARRAYT Opcode = 0xC4
|
||||
NEWSTRUCT0 Opcode = 0xC5
|
||||
NEWSTRUCT Opcode = 0xC6
|
||||
NEWMAP Opcode = 0xC8
|
||||
|
|
|
@ -126,6 +126,7 @@ func _() {
|
|||
_ = x[UNPACK-193]
|
||||
_ = x[NEWARRAY0-194]
|
||||
_ = x[NEWARRAY-195]
|
||||
_ = x[NEWARRAYT-196]
|
||||
_ = x[NEWSTRUCT0-197]
|
||||
_ = x[NEWSTRUCT-198]
|
||||
_ = x[NEWMAP-200]
|
||||
|
@ -139,11 +140,12 @@ func _() {
|
|||
_ = x[REVERSEITEMS-209]
|
||||
_ = x[REMOVE-210]
|
||||
_ = x[CLEARITEMS-211]
|
||||
_ = x[ISTYPE-217]
|
||||
_ = x[THROW-240]
|
||||
_ = x[THROWIFNOT-241]
|
||||
}
|
||||
|
||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPISNULLXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINSHA1SHA256HASH160HASH256CHECKSIGVERIFYCHECKMULTISIGPACKUNPACKNEWARRAY0NEWARRAYNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSTHROWTHROWIFNOT"
|
||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLOLDPUSH1RETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKXDROPISNULLXSWAPXTUCKDEPTHDROPDUPNIPOVERPICKROLLROTSWAPTUCKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALINCDECSIGNNEGATEABSNOTNZADDSUBMULDIVMODSHLSHRBOOLANDBOOLORNUMEQUALNUMNOTEQUALLTGTLTEGTEMINMAXWITHINSHA1SHA256HASH160HASH256CHECKSIGVERIFYCHECKMULTISIGPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISTYPETHROWTHROWIFNOT"
|
||||
|
||||
var _Opcode_map = map[Opcode]string{
|
||||
0: _Opcode_name[0:8],
|
||||
|
@ -262,21 +264,23 @@ var _Opcode_map = map[Opcode]string{
|
|||
193: _Opcode_name[621:627],
|
||||
194: _Opcode_name[627:636],
|
||||
195: _Opcode_name[636:644],
|
||||
197: _Opcode_name[644:654],
|
||||
198: _Opcode_name[654:663],
|
||||
200: _Opcode_name[663:669],
|
||||
202: _Opcode_name[669:673],
|
||||
203: _Opcode_name[673:679],
|
||||
204: _Opcode_name[679:683],
|
||||
205: _Opcode_name[683:689],
|
||||
206: _Opcode_name[689:697],
|
||||
207: _Opcode_name[697:703],
|
||||
208: _Opcode_name[703:710],
|
||||
209: _Opcode_name[710:722],
|
||||
210: _Opcode_name[722:728],
|
||||
211: _Opcode_name[728:738],
|
||||
240: _Opcode_name[738:743],
|
||||
241: _Opcode_name[743:753],
|
||||
196: _Opcode_name[644:653],
|
||||
197: _Opcode_name[653:663],
|
||||
198: _Opcode_name[663:672],
|
||||
200: _Opcode_name[672:678],
|
||||
202: _Opcode_name[678:682],
|
||||
203: _Opcode_name[682:688],
|
||||
204: _Opcode_name[688:692],
|
||||
205: _Opcode_name[692:698],
|
||||
206: _Opcode_name[698:706],
|
||||
207: _Opcode_name[706:712],
|
||||
208: _Opcode_name[712:719],
|
||||
209: _Opcode_name[719:731],
|
||||
210: _Opcode_name[731:737],
|
||||
211: _Opcode_name[737:747],
|
||||
217: _Opcode_name[747:753],
|
||||
240: _Opcode_name[753:758],
|
||||
241: _Opcode_name[758:768],
|
||||
}
|
||||
|
||||
func (i Opcode) String() string {
|
||||
|
|
26
pkg/vm/vm.go
26
pkg/vm/vm.go
|
@ -919,7 +919,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
case opcode.NEWARRAY0:
|
||||
v.estack.PushVal(&ArrayItem{[]StackItem{}})
|
||||
|
||||
case opcode.NEWARRAY:
|
||||
case opcode.NEWARRAY, opcode.NEWARRAYT:
|
||||
item := v.estack.Pop()
|
||||
switch t := item.value.(type) {
|
||||
case *StructItem:
|
||||
|
@ -933,7 +933,11 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
if n > MaxArraySize {
|
||||
panic("too long array")
|
||||
}
|
||||
items := makeArrayOfFalses(int(n))
|
||||
typ := BooleanT
|
||||
if op == opcode.NEWARRAYT {
|
||||
typ = StackItemType(parameter[0])
|
||||
}
|
||||
items := makeArrayOfType(int(n), typ)
|
||||
v.estack.PushVal(&ArrayItem{items})
|
||||
}
|
||||
|
||||
|
@ -954,7 +958,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
if n > MaxArraySize {
|
||||
panic("too long struct")
|
||||
}
|
||||
items := makeArrayOfFalses(int(n))
|
||||
items := makeArrayOfType(int(n), BooleanT)
|
||||
v.estack.PushVal(&StructItem{items})
|
||||
}
|
||||
|
||||
|
@ -1492,10 +1496,22 @@ func cloneIfStruct(item StackItem) StackItem {
|
|||
}
|
||||
}
|
||||
|
||||
func makeArrayOfFalses(n int) []StackItem {
|
||||
func makeArrayOfType(n int, typ StackItemType) []StackItem {
|
||||
if !typ.IsValid() {
|
||||
panic(fmt.Sprintf("invalid stack item type: %d", typ))
|
||||
}
|
||||
items := make([]StackItem, n)
|
||||
for i := range items {
|
||||
items[i] = &BoolItem{false}
|
||||
switch typ {
|
||||
case BooleanT:
|
||||
items[i] = NewBoolItem(false)
|
||||
case IntegerT:
|
||||
items[i] = NewBigIntegerItem(big.NewInt(0))
|
||||
case ByteArrayT:
|
||||
items[i] = NewByteArrayItem([]byte{})
|
||||
default:
|
||||
items[i] = NullItem{}
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
|
|
@ -660,7 +660,7 @@ func TestSerializeArray(t *testing.T) {
|
|||
|
||||
func TestSerializeArrayBad(t *testing.T) {
|
||||
vm := load(getSerializeProg())
|
||||
item := NewArrayItem(makeArrayOfFalses(2))
|
||||
item := NewArrayItem(makeArrayOfType(2, BooleanT))
|
||||
item.value[1] = item
|
||||
|
||||
vm.estack.Push(&Element{value: item})
|
||||
|
@ -1337,7 +1337,7 @@ func testNEWARRAYIssue437(t *testing.T, i1, i2 opcode.Opcode, appended bool) {
|
|||
vm := load(prog)
|
||||
vm.Run()
|
||||
|
||||
arr := makeArrayOfFalses(4)
|
||||
arr := makeArrayOfType(4, BooleanT)
|
||||
arr[2] = makeStackItem(3)
|
||||
arr[3] = makeStackItem(4)
|
||||
if appended {
|
||||
|
@ -1379,6 +1379,32 @@ func TestNEWARRAYByteArray(t *testing.T) {
|
|||
assert.Equal(t, &ArrayItem{[]StackItem{}}, vm.estack.Pop().value)
|
||||
}
|
||||
|
||||
func testNEWARRAYT(t *testing.T, typ StackItemType, item StackItem) {
|
||||
prog := makeProgram(opcode.NEWARRAYT, opcode.Opcode(typ), opcode.PUSH0, opcode.PICKITEM)
|
||||
v := load(prog)
|
||||
v.estack.PushVal(1)
|
||||
if item == nil {
|
||||
checkVMFailed(t, v)
|
||||
return
|
||||
}
|
||||
runVM(t, v)
|
||||
require.Equal(t, 1, v.estack.Len())
|
||||
require.Equal(t, item, v.estack.Pop().Item())
|
||||
}
|
||||
|
||||
func TestNEWARRAYT(t *testing.T) {
|
||||
testCases := map[StackItemType]StackItem{
|
||||
BooleanT: NewBoolItem(false),
|
||||
IntegerT: NewBigIntegerItem(big.NewInt(0)),
|
||||
ByteArrayT: NewByteArrayItem([]byte{}),
|
||||
ArrayT: NullItem{},
|
||||
0xFF: nil,
|
||||
}
|
||||
for typ, item := range testCases {
|
||||
t.Run(typ.String(), func(t *testing.T) { testNEWARRAYT(t, typ, item) })
|
||||
}
|
||||
}
|
||||
|
||||
func TestNEWARRAYBadSize(t *testing.T) {
|
||||
prog := makeProgram(opcode.NEWARRAY)
|
||||
vm := load(prog)
|
||||
|
|
Loading…
Reference in a new issue