vm: implement PUSHA/CALLA opcodes
This commit is contained in:
parent
7fcd537b09
commit
1d3fb3d6f5
5 changed files with 167 additions and 124 deletions
|
@ -111,7 +111,7 @@ func (c *Context) Next() (opcode.Opcode, []byte, error) {
|
||||||
numtoread = 1
|
numtoread = 1
|
||||||
case opcode.JMPL, opcode.JMPIFL, opcode.JMPIFNOTL, opcode.JMPEQL, opcode.JMPNEL,
|
case opcode.JMPL, opcode.JMPIFL, opcode.JMPIFNOTL, opcode.JMPEQL, opcode.JMPNEL,
|
||||||
opcode.JMPGTL, opcode.JMPGEL, opcode.JMPLTL, opcode.JMPLEL,
|
opcode.JMPGTL, opcode.JMPGEL, opcode.JMPLTL, opcode.JMPLEL,
|
||||||
opcode.CALLL, opcode.SYSCALL:
|
opcode.CALLL, opcode.SYSCALL, opcode.PUSHA:
|
||||||
numtoread = 4
|
numtoread = 4
|
||||||
default:
|
default:
|
||||||
if instr <= opcode.PUSHINT256 {
|
if instr <= opcode.PUSHINT256 {
|
||||||
|
|
|
@ -15,6 +15,7 @@ const (
|
||||||
PUSHINT128 Opcode = 0x04
|
PUSHINT128 Opcode = 0x04
|
||||||
PUSHINT256 Opcode = 0x05
|
PUSHINT256 Opcode = 0x05
|
||||||
|
|
||||||
|
PUSHA Opcode = 0x0A
|
||||||
PUSHNULL Opcode = 0x0B
|
PUSHNULL Opcode = 0x0B
|
||||||
|
|
||||||
PUSHDATA1 Opcode = 0x0C
|
PUSHDATA1 Opcode = 0x0C
|
||||||
|
@ -64,6 +65,7 @@ const (
|
||||||
JMPLEL Opcode = 0x33
|
JMPLEL Opcode = 0x33
|
||||||
CALL Opcode = 0x34
|
CALL Opcode = 0x34
|
||||||
CALLL Opcode = 0x35
|
CALLL Opcode = 0x35
|
||||||
|
CALLA Opcode = 0x36
|
||||||
|
|
||||||
// Exceptions
|
// Exceptions
|
||||||
ABORT Opcode = 0x37
|
ABORT Opcode = 0x37
|
||||||
|
|
|
@ -14,6 +14,7 @@ func _() {
|
||||||
_ = x[PUSHINT64-3]
|
_ = x[PUSHINT64-3]
|
||||||
_ = x[PUSHINT128-4]
|
_ = x[PUSHINT128-4]
|
||||||
_ = x[PUSHINT256-5]
|
_ = x[PUSHINT256-5]
|
||||||
|
_ = x[PUSHA-10]
|
||||||
_ = x[PUSHNULL-11]
|
_ = x[PUSHNULL-11]
|
||||||
_ = x[PUSHDATA1-12]
|
_ = x[PUSHDATA1-12]
|
||||||
_ = x[PUSHDATA2-13]
|
_ = x[PUSHDATA2-13]
|
||||||
|
@ -59,6 +60,7 @@ func _() {
|
||||||
_ = x[JMPLEL-51]
|
_ = x[JMPLEL-51]
|
||||||
_ = x[CALL-52]
|
_ = x[CALL-52]
|
||||||
_ = x[CALLL-53]
|
_ = x[CALLL-53]
|
||||||
|
_ = x[CALLA-54]
|
||||||
_ = x[ABORT-55]
|
_ = x[ABORT-55]
|
||||||
_ = x[ASSERT-56]
|
_ = x[ASSERT-56]
|
||||||
_ = x[THROW-58]
|
_ = x[THROW-58]
|
||||||
|
@ -141,7 +143,7 @@ func _() {
|
||||||
_ = x[CONVERT-219]
|
_ = x[CONVERT-219]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLABORTASSERTTHROWRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENDUPFROMALTSTACKTOALTSTACKFROMALTSTACKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT"
|
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHAPUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLCALLAABORTASSERTTHROWRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENDUPFROMALTSTACKTOALTSTACKFROMALTSTACKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT"
|
||||||
|
|
||||||
var _Opcode_map = map[Opcode]string{
|
var _Opcode_map = map[Opcode]string{
|
||||||
0: _Opcode_name[0:8],
|
0: _Opcode_name[0:8],
|
||||||
|
@ -150,128 +152,130 @@ var _Opcode_map = map[Opcode]string{
|
||||||
3: _Opcode_name[26:35],
|
3: _Opcode_name[26:35],
|
||||||
4: _Opcode_name[35:45],
|
4: _Opcode_name[35:45],
|
||||||
5: _Opcode_name[45:55],
|
5: _Opcode_name[45:55],
|
||||||
11: _Opcode_name[55:63],
|
10: _Opcode_name[55:60],
|
||||||
12: _Opcode_name[63:72],
|
11: _Opcode_name[60:68],
|
||||||
13: _Opcode_name[72:81],
|
12: _Opcode_name[68:77],
|
||||||
14: _Opcode_name[81:90],
|
13: _Opcode_name[77:86],
|
||||||
15: _Opcode_name[90:96],
|
14: _Opcode_name[86:95],
|
||||||
16: _Opcode_name[96:101],
|
15: _Opcode_name[95:101],
|
||||||
17: _Opcode_name[101:106],
|
16: _Opcode_name[101:106],
|
||||||
18: _Opcode_name[106:111],
|
17: _Opcode_name[106:111],
|
||||||
19: _Opcode_name[111:116],
|
18: _Opcode_name[111:116],
|
||||||
20: _Opcode_name[116:121],
|
19: _Opcode_name[116:121],
|
||||||
21: _Opcode_name[121:126],
|
20: _Opcode_name[121:126],
|
||||||
22: _Opcode_name[126:131],
|
21: _Opcode_name[126:131],
|
||||||
23: _Opcode_name[131:136],
|
22: _Opcode_name[131:136],
|
||||||
24: _Opcode_name[136:141],
|
23: _Opcode_name[136:141],
|
||||||
25: _Opcode_name[141:146],
|
24: _Opcode_name[141:146],
|
||||||
26: _Opcode_name[146:152],
|
25: _Opcode_name[146:151],
|
||||||
27: _Opcode_name[152:158],
|
26: _Opcode_name[151:157],
|
||||||
28: _Opcode_name[158:164],
|
27: _Opcode_name[157:163],
|
||||||
29: _Opcode_name[164:170],
|
28: _Opcode_name[163:169],
|
||||||
30: _Opcode_name[170:176],
|
29: _Opcode_name[169:175],
|
||||||
31: _Opcode_name[176:182],
|
30: _Opcode_name[175:181],
|
||||||
32: _Opcode_name[182:188],
|
31: _Opcode_name[181:187],
|
||||||
33: _Opcode_name[188:191],
|
32: _Opcode_name[187:193],
|
||||||
34: _Opcode_name[191:194],
|
33: _Opcode_name[193:196],
|
||||||
35: _Opcode_name[194:198],
|
34: _Opcode_name[196:199],
|
||||||
36: _Opcode_name[198:203],
|
35: _Opcode_name[199:203],
|
||||||
37: _Opcode_name[203:209],
|
36: _Opcode_name[203:208],
|
||||||
38: _Opcode_name[209:217],
|
37: _Opcode_name[208:214],
|
||||||
39: _Opcode_name[217:226],
|
38: _Opcode_name[214:222],
|
||||||
40: _Opcode_name[226:231],
|
39: _Opcode_name[222:231],
|
||||||
41: _Opcode_name[231:237],
|
40: _Opcode_name[231:236],
|
||||||
42: _Opcode_name[237:242],
|
41: _Opcode_name[236:242],
|
||||||
43: _Opcode_name[242:248],
|
42: _Opcode_name[242:247],
|
||||||
44: _Opcode_name[248:253],
|
43: _Opcode_name[247:253],
|
||||||
45: _Opcode_name[253:259],
|
44: _Opcode_name[253:258],
|
||||||
46: _Opcode_name[259:264],
|
45: _Opcode_name[258:264],
|
||||||
47: _Opcode_name[264:270],
|
46: _Opcode_name[264:269],
|
||||||
48: _Opcode_name[270:275],
|
47: _Opcode_name[269:275],
|
||||||
49: _Opcode_name[275:281],
|
48: _Opcode_name[275:280],
|
||||||
50: _Opcode_name[281:286],
|
49: _Opcode_name[280:286],
|
||||||
51: _Opcode_name[286:292],
|
50: _Opcode_name[286:291],
|
||||||
52: _Opcode_name[292:296],
|
51: _Opcode_name[291:297],
|
||||||
53: _Opcode_name[296:301],
|
52: _Opcode_name[297:301],
|
||||||
55: _Opcode_name[301:306],
|
53: _Opcode_name[301:306],
|
||||||
56: _Opcode_name[306:312],
|
54: _Opcode_name[306:311],
|
||||||
58: _Opcode_name[312:317],
|
55: _Opcode_name[311:316],
|
||||||
64: _Opcode_name[317:320],
|
56: _Opcode_name[316:322],
|
||||||
65: _Opcode_name[320:327],
|
58: _Opcode_name[322:327],
|
||||||
67: _Opcode_name[327:332],
|
64: _Opcode_name[327:330],
|
||||||
69: _Opcode_name[332:336],
|
65: _Opcode_name[330:337],
|
||||||
70: _Opcode_name[336:339],
|
67: _Opcode_name[337:342],
|
||||||
72: _Opcode_name[339:344],
|
69: _Opcode_name[342:346],
|
||||||
73: _Opcode_name[344:349],
|
70: _Opcode_name[346:349],
|
||||||
74: _Opcode_name[349:352],
|
72: _Opcode_name[349:354],
|
||||||
75: _Opcode_name[352:356],
|
73: _Opcode_name[354:359],
|
||||||
77: _Opcode_name[356:360],
|
74: _Opcode_name[359:362],
|
||||||
78: _Opcode_name[360:364],
|
75: _Opcode_name[362:366],
|
||||||
80: _Opcode_name[364:368],
|
77: _Opcode_name[366:370],
|
||||||
81: _Opcode_name[368:376],
|
78: _Opcode_name[370:374],
|
||||||
82: _Opcode_name[376:380],
|
80: _Opcode_name[374:378],
|
||||||
83: _Opcode_name[380:388],
|
81: _Opcode_name[378:386],
|
||||||
84: _Opcode_name[388:396],
|
82: _Opcode_name[386:390],
|
||||||
85: _Opcode_name[396:404],
|
83: _Opcode_name[390:398],
|
||||||
106: _Opcode_name[404:419],
|
84: _Opcode_name[398:406],
|
||||||
107: _Opcode_name[419:429],
|
85: _Opcode_name[406:414],
|
||||||
108: _Opcode_name[429:441],
|
106: _Opcode_name[414:429],
|
||||||
126: _Opcode_name[441:444],
|
107: _Opcode_name[429:439],
|
||||||
127: _Opcode_name[444:450],
|
108: _Opcode_name[439:451],
|
||||||
128: _Opcode_name[450:454],
|
126: _Opcode_name[451:454],
|
||||||
129: _Opcode_name[454:459],
|
127: _Opcode_name[454:460],
|
||||||
144: _Opcode_name[459:465],
|
128: _Opcode_name[460:464],
|
||||||
145: _Opcode_name[465:468],
|
129: _Opcode_name[464:469],
|
||||||
146: _Opcode_name[468:470],
|
144: _Opcode_name[469:475],
|
||||||
147: _Opcode_name[470:473],
|
145: _Opcode_name[475:478],
|
||||||
151: _Opcode_name[473:478],
|
146: _Opcode_name[478:480],
|
||||||
152: _Opcode_name[478:486],
|
147: _Opcode_name[480:483],
|
||||||
153: _Opcode_name[486:490],
|
151: _Opcode_name[483:488],
|
||||||
154: _Opcode_name[490:493],
|
152: _Opcode_name[488:496],
|
||||||
155: _Opcode_name[493:499],
|
153: _Opcode_name[496:500],
|
||||||
156: _Opcode_name[499:502],
|
154: _Opcode_name[500:503],
|
||||||
157: _Opcode_name[502:505],
|
155: _Opcode_name[503:509],
|
||||||
158: _Opcode_name[505:508],
|
156: _Opcode_name[509:512],
|
||||||
159: _Opcode_name[508:511],
|
157: _Opcode_name[512:515],
|
||||||
160: _Opcode_name[511:514],
|
158: _Opcode_name[515:518],
|
||||||
161: _Opcode_name[514:517],
|
159: _Opcode_name[518:521],
|
||||||
162: _Opcode_name[517:520],
|
160: _Opcode_name[521:524],
|
||||||
168: _Opcode_name[520:523],
|
161: _Opcode_name[524:527],
|
||||||
169: _Opcode_name[523:526],
|
162: _Opcode_name[527:530],
|
||||||
170: _Opcode_name[526:529],
|
168: _Opcode_name[530:533],
|
||||||
171: _Opcode_name[529:536],
|
169: _Opcode_name[533:536],
|
||||||
172: _Opcode_name[536:542],
|
170: _Opcode_name[536:539],
|
||||||
177: _Opcode_name[542:544],
|
171: _Opcode_name[539:546],
|
||||||
179: _Opcode_name[544:552],
|
172: _Opcode_name[546:552],
|
||||||
180: _Opcode_name[552:563],
|
177: _Opcode_name[552:554],
|
||||||
181: _Opcode_name[563:565],
|
179: _Opcode_name[554:562],
|
||||||
182: _Opcode_name[565:568],
|
180: _Opcode_name[562:573],
|
||||||
183: _Opcode_name[568:570],
|
181: _Opcode_name[573:575],
|
||||||
184: _Opcode_name[570:573],
|
182: _Opcode_name[575:578],
|
||||||
185: _Opcode_name[573:576],
|
183: _Opcode_name[578:580],
|
||||||
186: _Opcode_name[576:579],
|
184: _Opcode_name[580:583],
|
||||||
187: _Opcode_name[579:585],
|
185: _Opcode_name[583:586],
|
||||||
192: _Opcode_name[585:589],
|
186: _Opcode_name[586:589],
|
||||||
193: _Opcode_name[589:595],
|
187: _Opcode_name[589:595],
|
||||||
194: _Opcode_name[595:604],
|
192: _Opcode_name[595:599],
|
||||||
195: _Opcode_name[604:612],
|
193: _Opcode_name[599:605],
|
||||||
196: _Opcode_name[612:621],
|
194: _Opcode_name[605:614],
|
||||||
197: _Opcode_name[621:631],
|
195: _Opcode_name[614:622],
|
||||||
198: _Opcode_name[631:640],
|
196: _Opcode_name[622:631],
|
||||||
200: _Opcode_name[640:646],
|
197: _Opcode_name[631:641],
|
||||||
202: _Opcode_name[646:650],
|
198: _Opcode_name[641:650],
|
||||||
203: _Opcode_name[650:656],
|
200: _Opcode_name[650:656],
|
||||||
204: _Opcode_name[656:660],
|
202: _Opcode_name[656:660],
|
||||||
205: _Opcode_name[660:666],
|
203: _Opcode_name[660:666],
|
||||||
206: _Opcode_name[666:674],
|
204: _Opcode_name[666:670],
|
||||||
207: _Opcode_name[674:680],
|
205: _Opcode_name[670:676],
|
||||||
208: _Opcode_name[680:687],
|
206: _Opcode_name[676:684],
|
||||||
209: _Opcode_name[687:699],
|
207: _Opcode_name[684:690],
|
||||||
210: _Opcode_name[699:705],
|
208: _Opcode_name[690:697],
|
||||||
211: _Opcode_name[705:715],
|
209: _Opcode_name[697:709],
|
||||||
216: _Opcode_name[715:721],
|
210: _Opcode_name[709:715],
|
||||||
217: _Opcode_name[721:727],
|
211: _Opcode_name[715:725],
|
||||||
219: _Opcode_name[727:734],
|
216: _Opcode_name[725:731],
|
||||||
|
217: _Opcode_name[731:737],
|
||||||
|
219: _Opcode_name[737:744],
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Opcode) String() string {
|
func (i Opcode) String() string {
|
||||||
|
|
22
pkg/vm/vm.go
22
pkg/vm/vm.go
|
@ -198,6 +198,9 @@ func (v *VM) PrintOps() {
|
||||||
case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT, opcode.CALL:
|
case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT, opcode.CALL:
|
||||||
offset := int16(binary.LittleEndian.Uint16(parameter))
|
offset := int16(binary.LittleEndian.Uint16(parameter))
|
||||||
desc = fmt.Sprintf("%d (%d/%x)", ctx.ip+int(offset), offset, parameter)
|
desc = fmt.Sprintf("%d (%d/%x)", ctx.ip+int(offset), offset, parameter)
|
||||||
|
case opcode.PUSHA:
|
||||||
|
offset := int32(binary.LittleEndian.Uint32(parameter))
|
||||||
|
desc = fmt.Sprintf("%d (%x)", offset, parameter)
|
||||||
case opcode.SYSCALL:
|
case opcode.SYSCALL:
|
||||||
desc = fmt.Sprintf("%q", parameter)
|
desc = fmt.Sprintf("%q", parameter)
|
||||||
default:
|
default:
|
||||||
|
@ -529,6 +532,14 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
case opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4:
|
case opcode.PUSHDATA1, opcode.PUSHDATA2, opcode.PUSHDATA4:
|
||||||
v.estack.PushVal(parameter)
|
v.estack.PushVal(parameter)
|
||||||
|
|
||||||
|
case opcode.PUSHA:
|
||||||
|
n := int32(binary.LittleEndian.Uint32(parameter))
|
||||||
|
if n < 0 || int(n) > len(ctx.prog) {
|
||||||
|
panic(fmt.Sprintf("invalid pointer offset (%d)", n))
|
||||||
|
}
|
||||||
|
ptr := NewPointerItem(int(n), ctx.prog)
|
||||||
|
v.estack.PushVal(ptr)
|
||||||
|
|
||||||
case opcode.PUSHNULL:
|
case opcode.PUSHNULL:
|
||||||
v.estack.PushVal(NullItem{})
|
v.estack.PushVal(NullItem{})
|
||||||
|
|
||||||
|
@ -1134,6 +1145,17 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
offset := v.getJumpOffset(newCtx, parameter, 0)
|
offset := v.getJumpOffset(newCtx, parameter, 0)
|
||||||
v.jumpIf(newCtx, offset, true)
|
v.jumpIf(newCtx, offset, true)
|
||||||
|
|
||||||
|
case opcode.CALLA:
|
||||||
|
ptr := v.estack.Pop().Item().(*PointerItem)
|
||||||
|
if ptr.hash != ctx.ScriptHash() {
|
||||||
|
panic("invalid script in pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
newCtx := ctx.Copy()
|
||||||
|
newCtx.rvcount = -1
|
||||||
|
v.istack.PushVal(newCtx)
|
||||||
|
v.jumpIf(newCtx, ptr.pos, true)
|
||||||
|
|
||||||
case opcode.SYSCALL:
|
case opcode.SYSCALL:
|
||||||
interopID := GetInteropID(parameter)
|
interopID := GetInteropID(parameter)
|
||||||
ifunc := v.GetInteropByID(interopID)
|
ifunc := v.GetInteropByID(interopID)
|
||||||
|
|
|
@ -909,6 +909,21 @@ func TestJMPs(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPUSHA(t *testing.T) {
|
||||||
|
t.Run("Negative", getTestFuncForVM(makeProgram(opcode.PUSHA, 0xFF, 0xFF, 0xFF, 0xFF), nil))
|
||||||
|
t.Run("TooBig", getTestFuncForVM(makeProgram(opcode.PUSHA, 10, 0, 0, 0), nil))
|
||||||
|
t.Run("Good", func(t *testing.T) {
|
||||||
|
prog := makeProgram(opcode.PUSHA, 2, 0, 0, 0)
|
||||||
|
runWithArgs(t, prog, NewPointerItem(2, prog))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCALLA(t *testing.T) {
|
||||||
|
prog := makeProgram(opcode.CALLA, opcode.PUSH2, opcode.ADD, opcode.RET, opcode.PUSH3, opcode.RET)
|
||||||
|
t.Run("InvalidScript", getTestFuncForVM(prog, nil, NewPointerItem(4, []byte{1})))
|
||||||
|
t.Run("Good", getTestFuncForVM(prog, 5, NewPointerItem(4, prog)))
|
||||||
|
}
|
||||||
|
|
||||||
func TestNOT(t *testing.T) {
|
func TestNOT(t *testing.T) {
|
||||||
prog := makeProgram(opcode.NOT)
|
prog := makeProgram(opcode.NOT)
|
||||||
t.Run("Bool", getTestFuncForVM(prog, true, false))
|
t.Run("Bool", getTestFuncForVM(prog, true, false))
|
||||||
|
|
Loading…
Reference in a new issue