vm: implement ASSERT/ABORT opcodes

Rename THROWIFNOT to ASSERT, add ABORT opcode.
ABORT cannot be caught, but the implementation should be postponed until
exception handling is implemented.
This commit is contained in:
Evgenii Stratonikov 2020-05-06 15:54:18 +03:00
parent 963a70d54a
commit 977c431bf1
9 changed files with 104 additions and 98 deletions

View file

@ -424,7 +424,7 @@ func TestCreateBasicChain(t *testing.T) {
func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Transaction {
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, sc, "transfer", from, to, amount)
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
emit.Opcode(w.BinWriter, opcode.ASSERT)
script := w.Bytes()
return transaction.NewInvocationTX(script, 0)

View file

@ -105,7 +105,7 @@ func (c *Client) TransferNEP5(acc *wallet.Account, to util.Uint160, token *walle
// 2 round trips instead of one.
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, token.Hash, "transfer", from, to, amount)
emit.Opcode(w.BinWriter, opcode.THROWIFNOT)
emit.Opcode(w.BinWriter, opcode.ASSERT)
tx := transaction.NewInvocationTX(w.Bytes(), gas)
tx.Sender = from

View file

@ -48,18 +48,18 @@ type rpcTestCase struct {
check func(t *testing.T, e *executor, result interface{})
}
const testContractHash = "76751a2fdde4dc6c7489799a28bb539bc09d1f54"
const testContractHash = "2077e1382aab3983aa342e68f7bbc94e69f204b9"
var rpcTestCases = map[string][]rpcTestCase{
"getapplicationlog": {
{
name: "positive",
params: `["113437bd8dfc44e3a6dfe77b750fcff246cbe933ca9667311f45d794cf0410cc"]`,
params: `["16c26d67f06770a5b0cda4b1c5ccc28d12c0197c7239a7fe30c2eb523b58f54d"]`,
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
check: func(t *testing.T, e *executor, acc interface{}) {
res, ok := acc.(*result.ApplicationLog)
require.True(t, ok)
expectedTxHash, err := util.Uint256DecodeStringLE("113437bd8dfc44e3a6dfe77b750fcff246cbe933ca9667311f45d794cf0410cc")
expectedTxHash, err := util.Uint256DecodeStringLE("16c26d67f06770a5b0cda4b1c5ccc28d12c0197c7239a7fe30c2eb523b58f54d")
require.NoError(t, err)
assert.Equal(t, expectedTxHash, res.TxHash)
assert.Equal(t, 1, len(res.Executions))

Binary file not shown.

Binary file not shown.

View file

@ -65,6 +65,11 @@ const (
CALL Opcode = 0x34
CALLL Opcode = 0x35
// Exceptions
ABORT Opcode = 0x37
ASSERT Opcode = 0x38
THROW Opcode = 0x3A
// Stack
DEPTH Opcode = 0x43
DROP Opcode = 0x45
@ -158,8 +163,4 @@ const (
ISNULL Opcode = 0xD8
ISTYPE Opcode = 0xD9
CONVERT Opcode = 0xDB
// Exceptions
THROW Opcode = 0xF0
THROWIFNOT Opcode = 0xF1
)

View file

@ -59,6 +59,9 @@ func _() {
_ = x[JMPLEL-51]
_ = x[CALL-52]
_ = x[CALLL-53]
_ = x[ABORT-55]
_ = x[ASSERT-56]
_ = x[THROW-58]
_ = x[DEPTH-67]
_ = x[DROP-69]
_ = x[NIP-70]
@ -138,11 +141,9 @@ func _() {
_ = x[ISNULL-216]
_ = x[ISTYPE-217]
_ = x[CONVERT-219]
_ = x[THROW-240]
_ = x[THROWIFNOT-241]
}
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENRETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERTTHROWTHROWIFNOT"
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLABORTASSERTTHROWDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENRETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT"
var _Opcode_map = map[Opcode]string{
0: _Opcode_name[0:8],
@ -194,86 +195,87 @@ var _Opcode_map = map[Opcode]string{
51: _Opcode_name[286:292],
52: _Opcode_name[292:296],
53: _Opcode_name[296:301],
67: _Opcode_name[301:306],
69: _Opcode_name[306:310],
70: _Opcode_name[310:313],
72: _Opcode_name[313:318],
73: _Opcode_name[318:323],
74: _Opcode_name[323:326],
75: _Opcode_name[326:330],
77: _Opcode_name[330:334],
78: _Opcode_name[334:338],
80: _Opcode_name[338:342],
81: _Opcode_name[342:350],
82: _Opcode_name[350:354],
83: _Opcode_name[354:362],
84: _Opcode_name[362:370],
85: _Opcode_name[370:378],
102: _Opcode_name[378:381],
103: _Opcode_name[381:388],
104: _Opcode_name[388:395],
105: _Opcode_name[395:403],
106: _Opcode_name[403:418],
107: _Opcode_name[418:428],
108: _Opcode_name[428:440],
126: _Opcode_name[440:443],
127: _Opcode_name[443:449],
128: _Opcode_name[449:453],
129: _Opcode_name[453:458],
144: _Opcode_name[458:464],
145: _Opcode_name[464:467],
146: _Opcode_name[467:469],
147: _Opcode_name[469:472],
151: _Opcode_name[472:477],
152: _Opcode_name[477:485],
153: _Opcode_name[485:489],
154: _Opcode_name[489:492],
155: _Opcode_name[492:498],
156: _Opcode_name[498:501],
157: _Opcode_name[501:504],
158: _Opcode_name[504:507],
159: _Opcode_name[507:510],
160: _Opcode_name[510:513],
161: _Opcode_name[513:516],
162: _Opcode_name[516:519],
168: _Opcode_name[519:522],
169: _Opcode_name[522:525],
170: _Opcode_name[525:528],
171: _Opcode_name[528:535],
172: _Opcode_name[535:541],
177: _Opcode_name[541:543],
179: _Opcode_name[543:551],
180: _Opcode_name[551:562],
181: _Opcode_name[562:564],
182: _Opcode_name[564:567],
183: _Opcode_name[567:569],
184: _Opcode_name[569:572],
185: _Opcode_name[572:575],
186: _Opcode_name[575:578],
187: _Opcode_name[578:584],
192: _Opcode_name[584:588],
193: _Opcode_name[588:594],
194: _Opcode_name[594:603],
195: _Opcode_name[603:611],
196: _Opcode_name[611:620],
197: _Opcode_name[620:630],
198: _Opcode_name[630:639],
200: _Opcode_name[639:645],
202: _Opcode_name[645:649],
203: _Opcode_name[649:655],
204: _Opcode_name[655:659],
205: _Opcode_name[659:665],
206: _Opcode_name[665:673],
207: _Opcode_name[673:679],
208: _Opcode_name[679:686],
209: _Opcode_name[686:698],
210: _Opcode_name[698:704],
211: _Opcode_name[704:714],
216: _Opcode_name[714:720],
217: _Opcode_name[720:726],
219: _Opcode_name[726:733],
240: _Opcode_name[733:738],
241: _Opcode_name[738:748],
55: _Opcode_name[301:306],
56: _Opcode_name[306:312],
58: _Opcode_name[312:317],
67: _Opcode_name[317:322],
69: _Opcode_name[322:326],
70: _Opcode_name[326:329],
72: _Opcode_name[329:334],
73: _Opcode_name[334:339],
74: _Opcode_name[339:342],
75: _Opcode_name[342:346],
77: _Opcode_name[346:350],
78: _Opcode_name[350:354],
80: _Opcode_name[354:358],
81: _Opcode_name[358:366],
82: _Opcode_name[366:370],
83: _Opcode_name[370:378],
84: _Opcode_name[378:386],
85: _Opcode_name[386:394],
102: _Opcode_name[394:397],
103: _Opcode_name[397:404],
104: _Opcode_name[404:411],
105: _Opcode_name[411:419],
106: _Opcode_name[419:434],
107: _Opcode_name[434:444],
108: _Opcode_name[444:456],
126: _Opcode_name[456:459],
127: _Opcode_name[459:465],
128: _Opcode_name[465:469],
129: _Opcode_name[469:474],
144: _Opcode_name[474:480],
145: _Opcode_name[480:483],
146: _Opcode_name[483:485],
147: _Opcode_name[485:488],
151: _Opcode_name[488:493],
152: _Opcode_name[493:501],
153: _Opcode_name[501:505],
154: _Opcode_name[505:508],
155: _Opcode_name[508:514],
156: _Opcode_name[514:517],
157: _Opcode_name[517:520],
158: _Opcode_name[520:523],
159: _Opcode_name[523:526],
160: _Opcode_name[526:529],
161: _Opcode_name[529:532],
162: _Opcode_name[532:535],
168: _Opcode_name[535:538],
169: _Opcode_name[538:541],
170: _Opcode_name[541:544],
171: _Opcode_name[544:551],
172: _Opcode_name[551:557],
177: _Opcode_name[557:559],
179: _Opcode_name[559:567],
180: _Opcode_name[567:578],
181: _Opcode_name[578:580],
182: _Opcode_name[580:583],
183: _Opcode_name[583:585],
184: _Opcode_name[585:588],
185: _Opcode_name[588:591],
186: _Opcode_name[591:594],
187: _Opcode_name[594:600],
192: _Opcode_name[600:604],
193: _Opcode_name[604:610],
194: _Opcode_name[610:619],
195: _Opcode_name[619:627],
196: _Opcode_name[627:636],
197: _Opcode_name[636:646],
198: _Opcode_name[646:655],
200: _Opcode_name[655:661],
202: _Opcode_name[661:665],
203: _Opcode_name[665:671],
204: _Opcode_name[671:675],
205: _Opcode_name[675:681],
206: _Opcode_name[681:689],
207: _Opcode_name[689:695],
208: _Opcode_name[695:702],
209: _Opcode_name[702:714],
210: _Opcode_name[714:720],
211: _Opcode_name[720:730],
216: _Opcode_name[730:736],
217: _Opcode_name[736:742],
219: _Opcode_name[742:749],
}
func (i Opcode) String() string {

View file

@ -9,10 +9,10 @@ import (
// Nothing more to test here, really.
func TestStringer(t *testing.T) {
tests := map[Opcode]string{
ADD: "ADD",
SUB: "SUB",
THROWIFNOT: "THROWIFNOT",
0xff: "Opcode(255)",
ADD: "ADD",
SUB: "SUB",
ASSERT: "ASSERT",
0xff: "Opcode(255)",
}
for o, s := range tests {
assert.Equal(t, s, o.String())

View file

@ -1298,9 +1298,12 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
case opcode.THROW:
panic("THROW")
case opcode.THROWIFNOT:
case opcode.ABORT:
panic("ABORT")
case opcode.ASSERT:
if !v.estack.Pop().Bool() {
panic("THROWIFNOT")
panic("ASSERT failed")
}
default: