diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 067db290e..4eb48ec6d 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -1080,16 +1080,12 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { case "SHA256": emit.Syscall(c.prog.BinWriter, "Neo.Crypto.SHA256") case "AppCall": - numArgs := len(expr.Args) - 1 - c.emitReverse(numArgs) - - emit.Opcode(c.prog.BinWriter, opcode.APPCALL) + c.emitReverse(len(expr.Args)) buf := c.getByteArray(expr.Args[0]) if len(buf) != 20 { c.prog.Err = errors.New("invalid script hash") } - - c.prog.WriteBytes(buf) + emit.Syscall(c.prog.BinWriter, "System.Contract.Call") case "Equals": emit.Opcode(c.prog.BinWriter, opcode.EQUAL) case "FromAddress": @@ -1111,16 +1107,14 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { // transformArgs returns a list of function arguments // which should be put on stack. // There are special cases for builtins: -// 1. When using AppCall, script hash is a part of the instruction so -// it should be emitted after APPCALL. -// 2. With FromAddress, parameter conversion is happening at compile-time +// 1. With FromAddress, parameter conversion is happening at compile-time // so there is no need to push parameters on stack and perform an actual call -// 3. With panic, generated code depends on if argument was nil or a string so +// 2. With panic, generated code depends on if argument was nil or a string so // it should be handled accordingly. func transformArgs(fun ast.Expr, args []ast.Expr) []ast.Expr { switch f := fun.(type) { case *ast.SelectorExpr: - if f.Sel.Name == "AppCall" || f.Sel.Name == "FromAddress" { + if f.Sel.Name == "FromAddress" { return args[1:] } case *ast.Ident: diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index 39435c243..efdb19654 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -6,10 +6,17 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/compiler" + "github.com/nspcc-dev/neo-go/pkg/core" + "github.com/nspcc-dev/neo-go/pkg/core/dao" + "github.com/nspcc-dev/neo-go/pkg/core/interop" + "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" + "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" ) func TestFromAddress(t *testing.T) { @@ -51,6 +58,14 @@ func TestFromAddress(t *testing.T) { }) } +func spawnVM(t *testing.T, ic *interop.Context, src string) *vm.VM { + b, err := compiler.Compile(strings.NewReader(src)) + require.NoError(t, err) + v := core.SpawnVM(ic) + v.Load(b) + return v +} + func TestAppCall(t *testing.T) { srcInner := ` package foo @@ -62,19 +77,13 @@ func TestAppCall(t *testing.T) { inner, err := compiler.Compile(strings.NewReader(srcInner)) require.NoError(t, err) - ih := hash.Hash160(inner) - getScript := func(u util.Uint160) ([]byte, bool) { - if u.Equals(ih) { - return inner, true - } - return nil, false - } + ic := interop.NewContext(trigger.Application, nil, dao.NewSimple(storage.NewMemoryStore()), nil, nil, nil, zaptest.NewLogger(t)) + require.NoError(t, ic.DAO.PutContractState(&state.Contract{Script: inner})) + ih := hash.Hash160(inner) t.Run("valid script", func(t *testing.T) { src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE())) - v := vmAndCompile(t, src) - v.SetScriptGetter(getScript) - + v := spawnVM(t, ic, src) require.NoError(t, v.Run()) assertResult(t, v, []byte{1, 2, 3, 4}) @@ -85,9 +94,7 @@ func TestAppCall(t *testing.T) { h[0] = ^h[0] src := getAppCallScript(fmt.Sprintf("%#v", h.BytesBE())) - v := vmAndCompile(t, src) - v.SetScriptGetter(getScript) - + v := spawnVM(t, ic, src) require.Error(t, v.Run()) }) @@ -111,9 +118,7 @@ func TestAppCall(t *testing.T) { } ` - v := vmAndCompile(t, src) - v.SetScriptGetter(getScript) - + v := spawnVM(t, ic, src) require.NoError(t, v.Run()) assertResult(t, v, []byte{1, 2, 3, 4}) diff --git a/pkg/core/gas_price.go b/pkg/core/gas_price.go index a4d281b5d..7d248d5ec 100644 --- a/pkg/core/gas_price.go +++ b/pkg/core/gas_price.go @@ -20,8 +20,6 @@ func getPrice(v *vm.VM, op opcode.Opcode, parameter []byte) util.Fixed8 { } switch op { - case opcode.APPCALL, opcode.TAILCALL: - return toFixed8(10) case opcode.SYSCALL: interopID := vm.GetInteropID(parameter) return getSyscallPrice(v, interopID) diff --git a/pkg/core/interops.go b/pkg/core/interops.go index b1be43361..3a6aba2ea 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -24,11 +24,11 @@ import ( // up for current blockchain. func SpawnVM(ic *interop.Context) *vm.VM { vm := vm.New() - bc := ic.Chain.(*Blockchain) - vm.SetScriptGetter(ic.GetContract) vm.RegisterInteropGetter(getSystemInterop(ic)) vm.RegisterInteropGetter(getNeoInterop(ic)) - vm.RegisterInteropGetter(bc.contracts.GetNativeInterop(ic)) + if ic.Chain != nil { + vm.RegisterInteropGetter(ic.Chain.(*Blockchain).contracts.GetNativeInterop(ic)) + } return vm } diff --git a/pkg/rpc/request/tx_builder_test.go b/pkg/rpc/request/tx_builder_test.go index 74fcc394c..a132c629f 100644 --- a/pkg/rpc/request/tx_builder_test.go +++ b/pkg/rpc/request/tx_builder_test.go @@ -19,43 +19,43 @@ func TestInvocationScriptCreationGood(t *testing.T) { ps Params script string }{{ - script: "676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "0c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "transfer"}}, - script: "0c087472616e73666572676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "0c087472616e736665720c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: NumberT, Value: 42}}, - script: "0c023432676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "0c0234320c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{}}}, - script: "10c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "10c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.ByteArrayType, Value: Param{Type: StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}}, - script: "0c1450befd26fdf6e4d957c11e078b24ebce6291456f11c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "0c1450befd26fdf6e4d957c11e078b24ebce6291456f11c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.SignatureType, Value: Param{Type: StringT, Value: "4edf5005771de04619235d5a4c7a9a11bb78e008541f1da7725f654c33380a3c87e2959a025da706d7255cb3a3fa07ebe9c6559d0d9e6213c68049168eb1056f"}}}}}}, - script: "0c404edf5005771de04619235d5a4c7a9a11bb78e008541f1da7725f654c33380a3c87e2959a025da706d7255cb3a3fa07ebe9c6559d0d9e6213c68049168eb1056f11c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "0c404edf5005771de04619235d5a4c7a9a11bb78e008541f1da7725f654c33380a3c87e2959a025da706d7255cb3a3fa07ebe9c6559d0d9e6213c68049168eb1056f11c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.StringType, Value: Param{Type: StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}}, - script: "0c283530626566643236666466366534643935376331316530373862323465626365363239313435366611c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "0c283530626566643236666466366534643935376331316530373862323465626365363239313435366611c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.Hash160Type, Value: Param{Type: StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}}, - script: "0c146f459162ceeb248b071ec157d9e4f6fd26fdbe5011c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "0c146f459162ceeb248b071ec157d9e4f6fd26fdbe5011c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.Hash256Type, Value: Param{Type: StringT, Value: "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}}}}}}, - script: "0c20e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6011c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "0c20e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6011c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.PublicKeyType, Value: Param{Type: StringT, Value: "03c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c1"}}}}}}, - script: "0c2103c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c111c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "0c2103c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c111c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.IntegerType, Value: Param{Type: NumberT, Value: 42}}}}}}, - script: "002a11c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "002a11c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.BoolType, Value: Param{Type: StringT, Value: "true"}}}}}}, - script: "1111c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "1111c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }, { ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.BoolType, Value: Param{Type: StringT, Value: "false"}}}}}}, - script: "1011c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50", + script: "1011c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", }} for _, ps := range paramScripts { script, err := CreateFunctionInvocationScript(contract, ps.ps) diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index b67906669..e038a584c 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -54,12 +54,12 @@ var rpcTestCases = map[string][]rpcTestCase{ "getapplicationlog": { { name: "positive", - params: `["caccb0e0465d87970190c90094e3fb54dbbcfa3e48683bd9a54b1fb834118d87"]`, + params: `["c296c0929350d051b9b40cace54db5a3eac4b730a8851e958795d44918f23c08"]`, 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("caccb0e0465d87970190c90094e3fb54dbbcfa3e48683bd9a54b1fb834118d87") + expectedTxHash, err := util.Uint256DecodeStringLE("c296c0929350d051b9b40cace54db5a3eac4b730a8851e958795d44918f23c08") require.NoError(t, err) assert.Equal(t, expectedTxHash, res.TxHash) assert.Equal(t, 1, len(res.Executions)) @@ -647,7 +647,7 @@ var rpcTestCases = map[string][]rpcTestCase{ check: func(t *testing.T, e *executor, inv interface{}) { res, ok := inv.(*result.Invoke) require.True(t, ok) - assert.Equal(t, "0c06717765727479676f459162ceeb248b071ec157d9e4f6fd26fdbe50", res.Script) + assert.Equal(t, "0c067177657274790c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", res.Script) assert.NotEqual(t, "", res.State) assert.NotEqual(t, 0, res.GasConsumed) }, diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index 912791f49..ea5e93376 100644 Binary files a/pkg/rpc/server/testdata/testblocks.acc and b/pkg/rpc/server/testdata/testblocks.acc differ diff --git a/pkg/vm/context.go b/pkg/vm/context.go index b20dbb088..bcc7194dd 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -113,8 +113,6 @@ func (c *Context) Next() (opcode.Opcode, []byte, error) { opcode.JMPGTL, opcode.JMPGEL, opcode.JMPLTL, opcode.JMPLEL, opcode.CALLL, opcode.SYSCALL: numtoread = 4 - case opcode.APPCALL, opcode.TAILCALL: - numtoread = 20 default: if instr <= opcode.PUSHINT256 { numtoread = 1 << instr diff --git a/pkg/vm/emit/emit.go b/pkg/vm/emit/emit.go index f510efb7d..eeb791fd6 100644 --- a/pkg/vm/emit/emit.go +++ b/pkg/vm/emit/emit.go @@ -144,11 +144,8 @@ func Jmp(w *io.BinWriter, op opcode.Opcode, label uint16) { // AppCall emits an appcall, if tailCall is true, tailCall opcode will be // emitted instead. func AppCall(w *io.BinWriter, scriptHash util.Uint160, tailCall bool) { - op := opcode.APPCALL - if tailCall { - op = opcode.TAILCALL - } - Instruction(w, op, scriptHash.BytesBE()) + Bytes(w, scriptHash.BytesBE()) + Syscall(w, "System.Contract.Call") } // AppCallWithOperationAndArgs emits an APPCALL with the given operation and arguments. diff --git a/pkg/vm/opcode/opcode.go b/pkg/vm/opcode/opcode.go index 87038dd9e..b6fcc13a1 100644 --- a/pkg/vm/opcode/opcode.go +++ b/pkg/vm/opcode/opcode.go @@ -91,9 +91,6 @@ const ( REVERSE4 Opcode = 0x54 REVERSEN Opcode = 0x55 - APPCALL Opcode = 0x67 - TAILCALL Opcode = 0x69 - // Old stack opcodes DUPFROMALTSTACK Opcode = 0x6A TOALTSTACK Opcode = 0x6B diff --git a/pkg/vm/opcode/opcode_string.go b/pkg/vm/opcode/opcode_string.go index 2c5752cac..5ff84b7b5 100644 --- a/pkg/vm/opcode/opcode_string.go +++ b/pkg/vm/opcode/opcode_string.go @@ -80,8 +80,6 @@ func _() { _ = x[REVERSE3-83] _ = x[REVERSE4-84] _ = x[REVERSEN-85] - _ = x[APPCALL-103] - _ = x[TAILCALL-105] _ = x[DUPFROMALTSTACK-106] _ = x[TOALTSTACK-107] _ = x[FROMALTSTACK-108] @@ -143,7 +141,7 @@ func _() { _ = x[CONVERT-219] } -const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLABORTASSERTTHROWRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENAPPCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT" +const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLABORTASSERTTHROWRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENDUPFROMALTSTACKTOALTSTACKFROMALTSTACKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT" var _Opcode_map = map[Opcode]string{ 0: _Opcode_name[0:8], @@ -215,67 +213,65 @@ var _Opcode_map = map[Opcode]string{ 83: _Opcode_name[380:388], 84: _Opcode_name[388:396], 85: _Opcode_name[396:404], - 103: _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], + 106: _Opcode_name[404:419], + 107: _Opcode_name[419:429], + 108: _Opcode_name[429:441], + 126: _Opcode_name[441:444], + 127: _Opcode_name[444:450], + 128: _Opcode_name[450:454], + 129: _Opcode_name[454:459], + 144: _Opcode_name[459:465], + 145: _Opcode_name[465:468], + 146: _Opcode_name[468:470], + 147: _Opcode_name[470:473], + 151: _Opcode_name[473:478], + 152: _Opcode_name[478:486], + 153: _Opcode_name[486:490], + 154: _Opcode_name[490:493], + 155: _Opcode_name[493:499], + 156: _Opcode_name[499:502], + 157: _Opcode_name[502:505], + 158: _Opcode_name[505:508], + 159: _Opcode_name[508:511], + 160: _Opcode_name[511:514], + 161: _Opcode_name[514:517], + 162: _Opcode_name[517:520], + 168: _Opcode_name[520:523], + 169: _Opcode_name[523:526], + 170: _Opcode_name[526:529], + 171: _Opcode_name[529:536], + 172: _Opcode_name[536:542], + 177: _Opcode_name[542:544], + 179: _Opcode_name[544:552], + 180: _Opcode_name[552:563], + 181: _Opcode_name[563:565], + 182: _Opcode_name[565:568], + 183: _Opcode_name[568:570], + 184: _Opcode_name[570:573], + 185: _Opcode_name[573:576], + 186: _Opcode_name[576:579], + 187: _Opcode_name[579:585], + 192: _Opcode_name[585:589], + 193: _Opcode_name[589:595], + 194: _Opcode_name[595:604], + 195: _Opcode_name[604:612], + 196: _Opcode_name[612:621], + 197: _Opcode_name[621:631], + 198: _Opcode_name[631:640], + 200: _Opcode_name[640:646], + 202: _Opcode_name[646:650], + 203: _Opcode_name[650:656], + 204: _Opcode_name[656:660], + 205: _Opcode_name[660:666], + 206: _Opcode_name[666:674], + 207: _Opcode_name[674:680], + 208: _Opcode_name[680:687], + 209: _Opcode_name[687:699], + 210: _Opcode_name[699:705], + 211: _Opcode_name[705:715], + 216: _Opcode_name[715:721], + 217: _Opcode_name[721:727], + 219: _Opcode_name[727:734], } func (i Opcode) String() string { diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 4d8540455..da444962b 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -71,9 +71,6 @@ type VM struct { // callback to get interop price getPrice func(*VM, opcode.Opcode, []byte) util.Fixed8 - // callback to get scripts. - getScript func(util.Uint160) ([]byte, bool) - istack *Stack // invocation stack. estack *Stack // execution stack. astack *Stack // alt stack. @@ -95,7 +92,6 @@ type VM struct { func New() *VM { vm := &VM{ getInterop: make([]InteropGetterFunc, 0, 3), // 3 functions is typical for our default usage. - getScript: nil, state: haltState, istack: NewStack("invocation"), @@ -204,8 +200,6 @@ func (v *VM) PrintOps() { desc = fmt.Sprintf("%d (%d/%x)", ctx.ip+int(offset), offset, parameter) case opcode.SYSCALL: desc = fmt.Sprintf("%q", parameter) - case opcode.APPCALL, opcode.TAILCALL: - desc = fmt.Sprintf("%x", parameter) default: if utf8.Valid(parameter) { desc = fmt.Sprintf("%x (%q)", parameter, parameter) @@ -477,11 +471,6 @@ func (v *VM) SetCheckedHash(h []byte) { copy(v.checkhash, h) } -// SetScriptGetter sets the script getter for CALL instructions. -func (v *VM) SetScriptGetter(gs func(util.Uint160) ([]byte, bool)) { - v.getScript = gs -} - // GetInteropID converts instruction parameter to an interop ID. func GetInteropID(parameter []byte) uint32 { return binary.LittleEndian.Uint32(parameter) @@ -520,25 +509,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } } - switch op { - case opcode.APPCALL, opcode.TAILCALL: - isZero := true - for i := range parameter { - if parameter[i] != 0 { - isZero = false - break - } - } - if !isZero { - break - } - - parameter = v.estack.Pop().Bytes() - if !ctx.hasDynamicInvoke { - panic("contract is not allowed to make dynamic invocations") - } - } - if op <= opcode.PUSHINT256 { v.estack.PushVal(emit.BytesToInt(parameter)) return @@ -1175,31 +1145,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic(fmt.Sprintf("failed to invoke syscall: %s", err)) } - case opcode.APPCALL, opcode.TAILCALL: - if v.getScript == nil { - panic("no getScript callback is set up") - } - - if op == opcode.APPCALL { - v.checkInvocationStackSize() - } - - hash, err := util.Uint160DecodeBytesBE(parameter) - if err != nil { - panic(err) - } - - script, hasDynamicInvoke := v.getScript(hash) - if script == nil { - panic("could not find script") - } - - if op == opcode.TAILCALL { - _ = v.istack.Pop() - } - - v.loadScriptWithHash(script, hash, hasDynamicInvoke) - case opcode.RET: oldCtx := v.istack.Pop().Value().(*Context) rvcount := oldCtx.rvcount diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index f67a760f3..ad1386d1c 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -1413,69 +1413,6 @@ func TestSIGN(t *testing.T) { t.Run("ByteArray", getTestFuncForVM(prog, 1, []byte{0, 1})) } -func TestAppCall(t *testing.T) { - prog := []byte{byte(opcode.APPCALL)} - hash := util.Uint160{1, 2} - prog = append(prog, hash.BytesBE()...) - prog = append(prog, byte(opcode.RET)) - - vm := load(prog) - vm.SetScriptGetter(func(in util.Uint160) ([]byte, bool) { - if in.Equals(hash) { - return makeProgram(opcode.DEPTH), true - } - return nil, false - }) - vm.estack.PushVal(2) - - runVM(t, vm) - elem := vm.estack.Pop() // depth should be 1 - assert.Equal(t, int64(1), elem.BigInt().Int64()) -} - -func TestAppCallDynamicBad(t *testing.T) { - prog := []byte{byte(opcode.APPCALL)} - hash := util.Uint160{} - prog = append(prog, hash.BytesBE()...) - prog = append(prog, byte(opcode.RET)) - - vm := load(prog) - vm.SetScriptGetter(func(in util.Uint160) ([]byte, bool) { - if in.Equals(hash) { - return makeProgram(opcode.DEPTH), true - } - return nil, false - }) - vm.estack.PushVal(2) - vm.estack.PushVal(hash.BytesBE()) - - checkVMFailed(t, vm) -} - -func TestAppCallDynamicGood(t *testing.T) { - prog := []byte{byte(opcode.APPCALL)} - zeroHash := util.Uint160{} - hash := util.Uint160{1, 2, 3} - prog = append(prog, zeroHash.BytesBE()...) - prog = append(prog, byte(opcode.RET)) - - vm := load(prog) - vm.SetScriptGetter(func(in util.Uint160) ([]byte, bool) { - if in.Equals(hash) { - return makeProgram(opcode.DEPTH), true - } - return nil, false - }) - vm.estack.PushVal(42) - vm.estack.PushVal(42) - vm.estack.PushVal(hash.BytesBE()) - vm.Context().hasDynamicInvoke = true - - runVM(t, vm) - elem := vm.estack.Pop() // depth should be 2 - assert.Equal(t, int64(2), elem.BigInt().Int64()) -} - func TestSimpleCall(t *testing.T) { buf := io.NewBufBinWriter() w := buf.BinWriter