diff --git a/.gitmodules b/.gitmodules index 64d1e0f2f..ad48a6616 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "pkg/vm/testdata/neo-vm"] path = pkg/vm/testdata/neo-vm url = https://github.com/neo-project/neo-vm.git - branch = master-2.x + branch = master diff --git a/pkg/compiler/panic_test.go b/pkg/compiler/panic_test.go index cdc857a82..e8e506db4 100644 --- a/pkg/compiler/panic_test.go +++ b/pkg/compiler/panic_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/vm" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/stretchr/testify/require" ) @@ -54,7 +55,7 @@ func getPanicSource(need bool, message string) string { } func logGetter(logs *[]string) vm.InteropGetterFunc { - logID := vm.InteropNameToID([]byte("Neo.Runtime.Log")) + logID := emit.InteropNameToID([]byte("Neo.Runtime.Log")) return func(id uint32) *vm.InteropFuncPrice { if id != logID { return nil diff --git a/pkg/compiler/verify_test.go b/pkg/compiler/verify_test.go index 8d0151625..9ea772f13 100644 --- a/pkg/compiler/verify_test.go +++ b/pkg/compiler/verify_test.go @@ -6,6 +6,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/vm" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -18,7 +19,7 @@ func TestVerifyGood(t *testing.T) { src := getVerifyProg(pub, sig, msg) v, p := vmAndCompileInterop(t, src) - p.interops[vm.InteropNameToID([]byte("Neo.Crypto.ECDsaVerify"))] = func(v *vm.VM) error { + p.interops[emit.InteropNameToID([]byte("Neo.Crypto.ECDsaVerify"))] = func(v *vm.VM) error { assert.Equal(t, msg, v.Estack().Pop().Bytes()) assert.Equal(t, pub, v.Estack().Pop().Bytes()) assert.Equal(t, sig, v.Estack().Pop().Bytes()) diff --git a/pkg/compiler/vm_test.go b/pkg/compiler/vm_test.go index b97d14acd..c180bf55a 100644 --- a/pkg/compiler/vm_test.go +++ b/pkg/compiler/vm_test.go @@ -7,6 +7,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/compiler" "github.com/nspcc-dev/neo-go/pkg/vm" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -80,10 +81,10 @@ func newStoragePlugin() *storagePlugin { mem: make(map[string][]byte), interops: make(map[uint32]vm.InteropFunc), } - s.interops[vm.InteropNameToID([]byte("Neo.Storage.Get"))] = s.Get - s.interops[vm.InteropNameToID([]byte("Neo.Storage.Put"))] = s.Put - s.interops[vm.InteropNameToID([]byte("Neo.Storage.GetContext"))] = s.GetContext - s.interops[vm.InteropNameToID([]byte("Neo.Runtime.Notify"))] = s.Notify + s.interops[emit.InteropNameToID([]byte("Neo.Storage.Get"))] = s.Get + s.interops[emit.InteropNameToID([]byte("Neo.Storage.Put"))] = s.Put + s.interops[emit.InteropNameToID([]byte("Neo.Storage.GetContext"))] = s.GetContext + s.interops[emit.InteropNameToID([]byte("Neo.Runtime.Notify"))] = s.Notify return s } diff --git a/pkg/core/gas_price_test.go b/pkg/core/gas_price_test.go index ba802f6f5..d52a3d0cd 100644 --- a/pkg/core/gas_price_test.go +++ b/pkg/core/gas_price_test.go @@ -24,13 +24,13 @@ func TestGetPrice(t *testing.T) { t.Run("Neo.Asset.Create", func(t *testing.T) { // Neo.Asset.Create: 83c5c61f - v.Load([]byte{0x68, 0x04, 0x83, 0xc5, 0xc6, 0x1f}) + v.Load([]byte{0x68, 0x83, 0xc5, 0xc6, 0x1f}) checkGas(t, util.Fixed8FromInt64(5000), v) }) t.Run("Neo.Asset.Renew", func(t *testing.T) { // Neo.Asset.Renew: 78849071 (requires push 09 push 09 before) - v.Load([]byte{0x59, 0x59, 0x68, 0x04, 0x78, 0x84, 0x90, 0x71}) + v.Load([]byte{0x59, 0x59, 0x68, 0x78, 0x84, 0x90, 0x71}) require.NoError(t, v.StepInto()) // push 9 require.NoError(t, v.StepInto()) // push 9 @@ -39,7 +39,7 @@ func TestGetPrice(t *testing.T) { t.Run("Neo.Contract.Create (no props)", func(t *testing.T) { // Neo.Contract.Create: f66ca56e (requires push properties on fourth position) - v.Load([]byte{0x00, 0x00, 0x00, 0x00, 0x68, 0x04, 0xf6, 0x6c, 0xa5, 0x6e}) + v.Load([]byte{0x00, 0x00, 0x00, 0x00, 0x68, 0xf6, 0x6c, 0xa5, 0x6e}) require.NoError(t, v.StepInto()) // push 0 - ContractPropertyState.NoProperty require.NoError(t, v.StepInto()) // push 0 require.NoError(t, v.StepInto()) // push 0 @@ -50,7 +50,7 @@ func TestGetPrice(t *testing.T) { t.Run("Neo.Contract.Create (has storage)", func(t *testing.T) { // Neo.Contract.Create: f66ca56e (requires push properties on fourth position) - v.Load([]byte{0x51, 0x00, 0x00, 0x00, 0x68, 0x04, 0xf6, 0x6c, 0xa5, 0x6e}) + v.Load([]byte{0x51, 0x00, 0x00, 0x00, 0x68, 0xf6, 0x6c, 0xa5, 0x6e}) require.NoError(t, v.StepInto()) // push 01 - ContractPropertyState.HasStorage require.NoError(t, v.StepInto()) // push 0 require.NoError(t, v.StepInto()) // push 0 @@ -61,7 +61,7 @@ func TestGetPrice(t *testing.T) { t.Run("Neo.Contract.Create (has dynamic invoke)", func(t *testing.T) { // Neo.Contract.Create: f66ca56e (requires push properties on fourth position) - v.Load([]byte{0x52, 0x00, 0x00, 0x00, 0x68, 0x04, 0xf6, 0x6c, 0xa5, 0x6e}) + v.Load([]byte{0x52, 0x00, 0x00, 0x00, 0x68, 0xf6, 0x6c, 0xa5, 0x6e}) require.NoError(t, v.StepInto()) // push 02 - ContractPropertyState.HasDynamicInvoke require.NoError(t, v.StepInto()) // push 0 require.NoError(t, v.StepInto()) // push 0 @@ -72,7 +72,7 @@ func TestGetPrice(t *testing.T) { t.Run("Neo.Contract.Create (has both storage and dynamic invoke)", func(t *testing.T) { // Neo.Contract.Create: f66ca56e (requires push properties on fourth position) - v.Load([]byte{0x53, 0x00, 0x00, 0x00, 0x68, 0x04, 0xf6, 0x6c, 0xa5, 0x6e}) + v.Load([]byte{0x53, 0x00, 0x00, 0x00, 0x68, 0xf6, 0x6c, 0xa5, 0x6e}) require.NoError(t, v.StepInto()) // push 03 - HasStorage and HasDynamicInvoke require.NoError(t, v.StepInto()) // push 0 require.NoError(t, v.StepInto()) // push 0 @@ -83,7 +83,7 @@ func TestGetPrice(t *testing.T) { t.Run("Neo.Contract.Migrate", func(t *testing.T) { // Neo.Contract.Migrate: 471b6290 (requires push properties on fourth position) - v.Load([]byte{0x00, 0x00, 0x00, 0x00, 0x68, 0x04, 0x47, 0x1b, 0x62, 0x90}) + v.Load([]byte{0x00, 0x00, 0x00, 0x00, 0x68, 0x47, 0x1b, 0x62, 0x90}) require.NoError(t, v.StepInto()) // push 0 - ContractPropertyState.NoProperty require.NoError(t, v.StepInto()) // push 0 require.NoError(t, v.StepInto()) // push 0 @@ -94,7 +94,7 @@ func TestGetPrice(t *testing.T) { t.Run("System.Storage.Put", func(t *testing.T) { // System.Storage.Put: e63f1884 (requires push key and value) - v.Load([]byte{0x53, 0x53, 0x00, 0x68, 0x04, 0xe6, 0x3f, 0x18, 0x84}) + v.Load([]byte{0x53, 0x53, 0x00, 0x68, 0xe6, 0x3f, 0x18, 0x84}) require.NoError(t, v.StepInto()) // push 03 (length 1) require.NoError(t, v.StepInto()) // push 03 (length 1) require.NoError(t, v.StepInto()) // push 00 @@ -104,7 +104,7 @@ func TestGetPrice(t *testing.T) { t.Run("System.Storage.PutEx", func(t *testing.T) { // System.Storage.PutEx: 73e19b3a (requires push key and value) - v.Load([]byte{0x53, 0x53, 0x00, 0x68, 0x04, 0x73, 0xe1, 0x9b, 0x3a}) + v.Load([]byte{0x53, 0x53, 0x00, 0x68, 0x73, 0xe1, 0x9b, 0x3a}) require.NoError(t, v.StepInto()) // push 03 (length 1) require.NoError(t, v.StepInto()) // push 03 (length 1) require.NoError(t, v.StepInto()) // push 00 diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 05443042e..ccb040bd6 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -19,6 +19,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" ) // SpawnVM returns a VM with script getter and interop functions set @@ -263,7 +264,7 @@ var neoInterops = []interop.Function{ // Function slice and then sorts it. func initIDinInteropsSlice(iops []interop.Function) { for i := range iops { - iops[i].ID = vm.InteropNameToID([]byte(iops[i].Name)) + iops[i].ID = emit.InteropNameToID([]byte(iops[i].Name)) } sort.Slice(iops, func(i, j int) bool { return iops[i].ID < iops[j].ID diff --git a/pkg/core/native/contract.go b/pkg/core/native/contract.go index 150fb4ee8..332276320 100644 --- a/pkg/core/native/contract.go +++ b/pkg/core/native/contract.go @@ -63,7 +63,7 @@ func (cs *Contracts) SetNEO(n *NEO) { func NewContractMD(name string) *ContractMD { c := &ContractMD{ ServiceName: name, - ServiceID: vm.InteropNameToID([]byte(name)), + ServiceID: emit.InteropNameToID([]byte(name)), Methods: make(map[string]MethodAndPrice), } diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 1a0108ce8..1d18829d6 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -43,20 +43,20 @@ type rpcTestCase struct { check func(t *testing.T, e *executor, result interface{}) } -const testContractHash = "c2789e5ab9bab828743833965b1df0d5fbcc206f" +const testContractHash = "1b5cbfaa2e54b584d3240e38fc4bd413a65ea40c" var rpcTestCases = map[string][]rpcTestCase{ "getapplicationlog": { { name: "positive", - params: `["e5a6be3cd796e2284a55ebb2061f85d3f199263bbf659dbd5b670a6506e7a4a0"]`, + params: `["d98e4b58783aa9665efcc5be19ee432772a94462efc8a5e4165776e6dd8c4e92"]`, 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("e5a6be3cd796e2284a55ebb2061f85d3f199263bbf659dbd5b670a6506e7a4a0") + expectedTxHash, err := util.Uint256DecodeStringLE("d98e4b58783aa9665efcc5be19ee432772a94462efc8a5e4165776e6dd8c4e92") require.NoError(t, err) assert.Equal(t, expectedTxHash, res.TxHash) assert.Equal(t, 1, len(res.Executions)) @@ -405,25 +405,25 @@ var rpcTestCases = map[string][]rpcTestCase{ "getblockheader": { { name: "positive, no verbose", - params: `["02b9e6f634578f34c6026f1676e25aa04f58889a320fba8bc632c6fe48c26cf1"]`, + params: `["60c00bfa7f283d1821e1bc8c1c83aa534f325968944d73fa25cf7235af17d608"]`, result: func(e *executor) interface{} { - expected := "000000009456b8c7f89bdfe012a30a2be9af5218e048ae7372115ce3e39cc847c01e9e7f9cffa26c112eb147a995520e47afbc45a192d9bf1a8e9b8f80497e5d92c4e9f2129e965e010000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401408ee2187395071a089e3b9743b1a718fa28a8700676451317f7454aade98cf779b0afb5634a7e104f92e2df8e8b1c1b7b3b0e9fd61f4c0e9ea07ce112cef12b9a40fcb441c89b0c2047ba71a86d759bc2554dda55369798e6ab63e6c7713b06a8178f13586edf6a673f20bf5ed7bdc727f9e0c6f487cf667e505a26236d73887ae940691972a6f4ccef19a03a3d5948dfcf992af2c6a3c5b033a0f9235d2b8967291d9f61495ff1a681f240517c8d892eaa805e667bca40abcf03d441c68a9ec59deb4005890a59d83c7cb0416895e4768123e900603d5b140bf799bc9879fb628c598193db2b7a8e07ab54733c1c67b60c97a1a8048961cc0afd0b048e878866ffd7298b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00" + expected := "000000009456b8c7f89bdfe012a30a2be9af5218e048ae7372115ce3e39cc847c01e9e7f9cffa26c112eb147a995520e47afbc45a192d9bf1a8e9b8f80497e5d92c4e9f2011e975e010000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401404be65e52d50121ce243eb27f7a1c16637e753e847e9c027f255bc5e2bae45f1c99d8c1014e5abe829b9a229904540b7010ae6fb2bb57f88d70179ec617dea35440c9d51c5980e016f5cb51734554341764572b0644010952761878b1966d2b013ceaf18958891060dde3a33d23118f27ef21e991f913a8740c716c14aa19483ea0409a44efd5607f7b8f09dd4f242882713b40866c2aeab9aaa5f92b92dbaf84ed0c039fb1790888ab36d77c8b6520b2bb58ab43b219be3272145cf0f6fd091e33e540ec1e52377a56bb6e0f82329ac1a70ab06cb7e23c149bcc194fa483a316de33468191b16ab1fafb2f1a1af79a0cd6e7e275d3a3ed56f8b0ecbcd6e26f93a3957b8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00" return &expected }, }, { name: "positive, verbose 0", - params: `["02b9e6f634578f34c6026f1676e25aa04f58889a320fba8bc632c6fe48c26cf1", 0]`, + params: `["60c00bfa7f283d1821e1bc8c1c83aa534f325968944d73fa25cf7235af17d608", 0]`, result: func(e *executor) interface{} { - expected := "000000009456b8c7f89bdfe012a30a2be9af5218e048ae7372115ce3e39cc847c01e9e7f9cffa26c112eb147a995520e47afbc45a192d9bf1a8e9b8f80497e5d92c4e9f2129e965e010000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401408ee2187395071a089e3b9743b1a718fa28a8700676451317f7454aade98cf779b0afb5634a7e104f92e2df8e8b1c1b7b3b0e9fd61f4c0e9ea07ce112cef12b9a40fcb441c89b0c2047ba71a86d759bc2554dda55369798e6ab63e6c7713b06a8178f13586edf6a673f20bf5ed7bdc727f9e0c6f487cf667e505a26236d73887ae940691972a6f4ccef19a03a3d5948dfcf992af2c6a3c5b033a0f9235d2b8967291d9f61495ff1a681f240517c8d892eaa805e667bca40abcf03d441c68a9ec59deb4005890a59d83c7cb0416895e4768123e900603d5b140bf799bc9879fb628c598193db2b7a8e07ab54733c1c67b60c97a1a8048961cc0afd0b048e878866ffd7298b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00" + expected := "000000009456b8c7f89bdfe012a30a2be9af5218e048ae7372115ce3e39cc847c01e9e7f9cffa26c112eb147a995520e47afbc45a192d9bf1a8e9b8f80497e5d92c4e9f2011e975e010000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401404be65e52d50121ce243eb27f7a1c16637e753e847e9c027f255bc5e2bae45f1c99d8c1014e5abe829b9a229904540b7010ae6fb2bb57f88d70179ec617dea35440c9d51c5980e016f5cb51734554341764572b0644010952761878b1966d2b013ceaf18958891060dde3a33d23118f27ef21e991f913a8740c716c14aa19483ea0409a44efd5607f7b8f09dd4f242882713b40866c2aeab9aaa5f92b92dbaf84ed0c039fb1790888ab36d77c8b6520b2bb58ab43b219be3272145cf0f6fd091e33e540ec1e52377a56bb6e0f82329ac1a70ab06cb7e23c149bcc194fa483a316de33468191b16ab1fafb2f1a1af79a0cd6e7e275d3a3ed56f8b0ecbcd6e26f93a3957b8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00" return &expected }, }, { name: "positive, verbose !=0", - params: `["02b9e6f634578f34c6026f1676e25aa04f58889a320fba8bc632c6fe48c26cf1", 2]`, + params: `["60c00bfa7f283d1821e1bc8c1c83aa534f325968944d73fa25cf7235af17d608", 2]`, result: func(e *executor) interface{} { - hash, err := util.Uint256DecodeStringLE("02b9e6f634578f34c6026f1676e25aa04f58889a320fba8bc632c6fe48c26cf1") + hash, err := util.Uint256DecodeStringLE("60c00bfa7f283d1821e1bc8c1c83aa534f325968944d73fa25cf7235af17d608") if err != nil { panic("can not decode hash parameter") } @@ -822,7 +822,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { // If you are planning to modify test chain from `testblocks.acc`, please, update param value (first block) name: "empty block", - params: `["0000000029e2ea0ec5c9aa98fa736b52750916b3b8ab5cdbe7647fb6d0b7f6dac35865640000000000000000000000000000000000000000000000000000000000000000e29e965ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140efdc94ac1e5c7588a1e70aa2ada3450631f30b15676861e7f32159f0e0b97e5fec8dd9870d92755e76b2cf3d6a90f06c2f6a7b782248ac4b765433beb6891a4840551f59a1e88395290ea2273500c60fc55b0d33ab6c3ddd565177f77083e82aaffca3553a0a116b457d5101f8627da39a3a24f19e2d04fab7e65670fda6a50f4140576969f478e6150b128b1149dd3c8b663f27bda53a6815fe177d52abc6ad40311a4fcba14a0d9286d6cda521cd9bc0ade09a66e88059da84363512c6110f4dc94008e8c0e6f3835281690fa0d594a6f5f1914b2f047fe835b134641b5a19935a4f6b10931ad168e47f96f6bf98380c0f060d4b25ae71869c4ef9d2a92a262eceeb8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"]`, + params: `["00000000547e0fa207c116e25fd69a04b99e446e409ca23c7863bafbd585abeb468314c00000000000000000000000000000000000000000000000000000000000000000d21e975ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd0401404fb770b14c4e7bd2461dbf238ca197844a724388d15cfeb96a07cb8cb52733f3f7adcc5bbd33c8dc19103116f1fe6c3151a14e3db40585823cc3ce153a0426ec40fd880f3d029e95dcb4612b40f31d5111a961345bc2090689a7462c12c85006ed281216331e1169d41cc0a8780b0befc22b9d3ba147e331acfb858675ebaaf8de4055922389015e0a96e07c9ad987eda4a642f0436843966821e620b89bf84e8ec22a33c308ad7e9815b1d0bebd93289db1828bec516d3b2ccfcaf080d2b7ea385f408005e2ff7387c50393407b125a09f42970b4b8033737e0b5ee04c1dfc9e6ad15da879cd46b3177b302ee1c109acbce4af689bb7e89978e4709e97d2db76c7ada8b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae00"]`, fail: true, }, { @@ -848,7 +848,7 @@ var rpcTestCases = map[string][]rpcTestCase{ { name: "positive", // If you are planning to modify test chain from `testblocks.acc`, please, update param value (second block) - params: `["0000000029e2ea0ec5c9aa98fa736b52750916b3b8ab5cdbe7647fb6d0b7f6dac3586564980135e10c52e5444c962659b388a5b226114a45d3912a88700ac6b05aaaf961e29e965ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140a0ed19af416fc4edb6e32b4687290d4eff1262af338dc8e55021a13f500ce94377c0fca593db15e29a0ee11b229d8bb48bd75203834829aee47096ff375ef8e240bcccad08d1ae7cc47c099eb4321a1fe07cf77a434841fd48a04aaf19204ec5bbf465533a2845a323710ea068316f50be82c384c82e0a5a509b2a9442c6a7909640de0a52dd615efac136971be900700ec39a84198e7d1639e880955022901a8d98ff39f00e858b41686047d68d7c18963b9def50a85907eb3b0bfbba7b2fa64d814060670b0c648757594cdba09aafc158ee6f7e88fbd2aa088a8c57bff2c8e7ddd83fa242632e1b6f82e3af2b3d0428c3936833cefb7ced1cc3c50ec29da906eb498b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae01000014000000b004000000000000"]`, + params: `["00000000547e0fa207c116e25fd69a04b99e446e409ca23c7863bafbd585abeb468314c0980135e10c52e5444c962659b388a5b226114a45d3912a88700ac6b05aaaf961d21e975ed10000005704000000000000be48d3a3f5d10013ab9ffee489706078714f1ea201fd040140dc1690f42fd67440defaf6385ad5d77b3a2ffba6270c22aa20373eab011cc5eb46e1aeb0f5f9d3f78ebd29d7fb3bb47777e2a0793e4594761e74dc6867834f6a405ebde4af3a4fedefc33c7debf58a159dcd4a66e396c007bf9cc185f422ff449849efcbbb8d772df213b3b412b7ca4188ec3a4ac841c3374ae4cac3277e16d39640ee9e51540a5c37100e0964f279938561096df6693429e692ce39553f63db53ce4f4d4d777e00299c594f7c8095410b03b5ca253f6946e081069180890a443e8e40981c77a1d7a9e9d71e54ba3edd8d740b24b723efefd7eca87ba9e5c2abb2a07dea5ab83e643cabc20af3d2e90990e668973850bd7be723097f34a47ac60fddc28b532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae01000014000000b004000000000000"]`, result: func(e *executor) interface{} { v := true return &v diff --git a/pkg/rpc/server/testdata/test_contract.avm b/pkg/rpc/server/testdata/test_contract.avm index b9f78fdc6..110c81188 100755 Binary files a/pkg/rpc/server/testdata/test_contract.avm and b/pkg/rpc/server/testdata/test_contract.avm differ diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index 33aa0230f..0cfa49864 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 9e4fa63e6..529ddc9f5 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -74,7 +74,7 @@ func (c *Context) Next() (opcode.Opcode, []byte, error) { var numtoread int switch instr { - case opcode.PUSHDATA1, opcode.SYSCALL: + case opcode.PUSHDATA1: if c.nextip >= len(c.prog) { err = errNoInstParam } else { @@ -101,7 +101,7 @@ func (c *Context) Next() (opcode.Opcode, []byte, error) { } case opcode.JMP, opcode.JMPIF, opcode.JMPIFNOT, opcode.CALL, opcode.CALLED, opcode.CALLEDT: numtoread = 2 - case opcode.CALLI: + case opcode.CALLI, opcode.SYSCALL: numtoread = 4 case opcode.APPCALL, opcode.TAILCALL: numtoread = 20 diff --git a/pkg/vm/emit/bigint.go b/pkg/vm/emit/bigint.go index 8c14a377c..fb555036c 100644 --- a/pkg/vm/emit/bigint.go +++ b/pkg/vm/emit/bigint.go @@ -80,10 +80,13 @@ func getEffectiveSize(buf []byte, isNeg bool) int { } // IntToBytes converts integer to a slice in little-endian format. +// Note: NEO3 serialization differs from default C# BigInteger.ToByteArray() +// when n == 0. For zero is equal to empty slice in NEO3. +// https://github.com/neo-project/neo-vm/blob/master/src/neo-vm/Types/Integer.cs#L16 func IntToBytes(n *big.Int) []byte { sign := n.Sign() if sign == 0 { - return []byte{0} + return []byte{} } var ws []big.Word diff --git a/pkg/vm/emit/bigint_test.go b/pkg/vm/emit/bigint_test.go index 2195ac3dc..71ec2326a 100644 --- a/pkg/vm/emit/bigint_test.go +++ b/pkg/vm/emit/bigint_test.go @@ -16,7 +16,7 @@ var testCases = []struct { number int64 buf []byte }{ - {0, []byte{0}}, + {0, []byte{}}, {1, []byte{1}}, {-1, []byte{255}}, {2, []byte{2}}, @@ -52,7 +52,7 @@ var testCases = []struct { {-9187484529235886209, []byte{127, 127, 127, 127, 127, 127, 127, 128}}, // https://github.com/dotnet/runtime/blob/master/src/libraries/System.Runtime.Numerics/tests/BigInteger/ToByteArray.cs#L14 - {0, []byte{0x00}}, + // {0, []byte{0x00}}, commented because this test check default `BigInteger` serialization, not NEO3 serialization. {3, []byte{0x03}}, {128, []byte{0x80, 0x00}}, {200, []byte{0xc8, 0x00}}, diff --git a/pkg/vm/emit/emit.go b/pkg/vm/emit/emit.go index 81d81ecef..411276787 100644 --- a/pkg/vm/emit/emit.go +++ b/pkg/vm/emit/emit.go @@ -1,6 +1,7 @@ package emit import ( + "crypto/sha256" "encoding/binary" "errors" "fmt" @@ -107,9 +108,8 @@ func Syscall(w *io.BinWriter, api string) { w.Err = errors.New("syscall api cannot be of length 0") return } - buf := make([]byte, len(api)+1) - buf[0] = byte(len(api)) - copy(buf[1:], api) + buf := make([]byte, 4) + binary.LittleEndian.PutUint32(buf, InteropNameToID([]byte(api))) Instruction(w, opcode.SYSCALL, buf) } @@ -168,3 +168,9 @@ func isInstructionJmp(op opcode.Opcode) bool { } return false } + +// InteropNameToID returns an identificator of the method based on its name. +func InteropNameToID(name []byte) uint32 { + h := sha256.Sum256(name) + return binary.LittleEndian.Uint32(h[:4]) +} diff --git a/pkg/vm/emit/emit_test.go b/pkg/vm/emit/emit_test.go index cb028cb9e..f122f1abb 100644 --- a/pkg/vm/emit/emit_test.go +++ b/pkg/vm/emit/emit_test.go @@ -165,9 +165,9 @@ func TestEmitSyscall(t *testing.T) { for _, syscall := range syscalls { Syscall(buf.BinWriter, syscall) result := buf.Bytes() + assert.Equal(t, 5, len(result)) assert.Equal(t, opcode.Opcode(result[0]), opcode.SYSCALL) - assert.Equal(t, result[1], uint8(len(syscall))) - assert.Equal(t, result[2:], []byte(syscall)) + assert.Equal(t, binary.LittleEndian.Uint32(result[1:]), InteropNameToID([]byte(syscall))) buf.Reset() } diff --git a/pkg/vm/interop.go b/pkg/vm/interop.go index d1ec282ba..930892f27 100644 --- a/pkg/vm/interop.go +++ b/pkg/vm/interop.go @@ -1,11 +1,11 @@ package vm import ( - "crypto/sha256" - "encoding/binary" "errors" "fmt" "sort" + + "github.com/nspcc-dev/neo-go/pkg/vm/emit" ) // InteropFunc allows to hook into the VM. @@ -28,35 +28,35 @@ type interopIDFuncPrice struct { type InteropGetterFunc func(uint32) *InteropFuncPrice var defaultVMInterops = []interopIDFuncPrice{ - {InteropNameToID([]byte("Neo.Runtime.Log")), + {emit.InteropNameToID([]byte("Neo.Runtime.Log")), InteropFuncPrice{runtimeLog, 1}}, - {InteropNameToID([]byte("Neo.Runtime.Notify")), + {emit.InteropNameToID([]byte("Neo.Runtime.Notify")), InteropFuncPrice{runtimeNotify, 1}}, - {InteropNameToID([]byte("Neo.Runtime.Serialize")), + {emit.InteropNameToID([]byte("Neo.Runtime.Serialize")), InteropFuncPrice{RuntimeSerialize, 1}}, - {InteropNameToID([]byte("System.Runtime.Serialize")), + {emit.InteropNameToID([]byte("System.Runtime.Serialize")), InteropFuncPrice{RuntimeSerialize, 1}}, - {InteropNameToID([]byte("Neo.Runtime.Deserialize")), + {emit.InteropNameToID([]byte("Neo.Runtime.Deserialize")), InteropFuncPrice{RuntimeDeserialize, 1}}, - {InteropNameToID([]byte("System.Runtime.Deserialize")), + {emit.InteropNameToID([]byte("System.Runtime.Deserialize")), InteropFuncPrice{RuntimeDeserialize, 1}}, - {InteropNameToID([]byte("Neo.Enumerator.Create")), + {emit.InteropNameToID([]byte("Neo.Enumerator.Create")), InteropFuncPrice{EnumeratorCreate, 1}}, - {InteropNameToID([]byte("Neo.Enumerator.Next")), + {emit.InteropNameToID([]byte("Neo.Enumerator.Next")), InteropFuncPrice{EnumeratorNext, 1}}, - {InteropNameToID([]byte("Neo.Enumerator.Concat")), + {emit.InteropNameToID([]byte("Neo.Enumerator.Concat")), InteropFuncPrice{EnumeratorConcat, 1}}, - {InteropNameToID([]byte("Neo.Enumerator.Value")), + {emit.InteropNameToID([]byte("Neo.Enumerator.Value")), InteropFuncPrice{EnumeratorValue, 1}}, - {InteropNameToID([]byte("Neo.Iterator.Create")), + {emit.InteropNameToID([]byte("Neo.Iterator.Create")), InteropFuncPrice{IteratorCreate, 1}}, - {InteropNameToID([]byte("Neo.Iterator.Concat")), + {emit.InteropNameToID([]byte("Neo.Iterator.Concat")), InteropFuncPrice{IteratorConcat, 1}}, - {InteropNameToID([]byte("Neo.Iterator.Key")), + {emit.InteropNameToID([]byte("Neo.Iterator.Key")), InteropFuncPrice{IteratorKey, 1}}, - {InteropNameToID([]byte("Neo.Iterator.Keys")), + {emit.InteropNameToID([]byte("Neo.Iterator.Keys")), InteropFuncPrice{IteratorKeys, 1}}, - {InteropNameToID([]byte("Neo.Iterator.Values")), + {emit.InteropNameToID([]byte("Neo.Iterator.Values")), InteropFuncPrice{IteratorValues, 1}}, } @@ -70,12 +70,6 @@ func getDefaultVMInterop(id uint32) *InteropFuncPrice { return nil } -// InteropNameToID returns an identificator of the method based on its name. -func InteropNameToID(name []byte) uint32 { - h := sha256.Sum256(name) - return binary.LittleEndian.Uint32(h[:4]) -} - // runtimeLog handles the syscall "Neo.Runtime.Log" for printing and logging stuff. func runtimeLog(vm *VM) error { item := vm.Estack().Pop() diff --git a/pkg/vm/json_test.go b/pkg/vm/json_test.go index c9249e0b3..b17a1f2ef 100644 --- a/pkg/vm/json_test.go +++ b/pkg/vm/json_test.go @@ -3,6 +3,7 @@ package vm import ( "bytes" "encoding/base64" + "encoding/binary" "encoding/hex" "encoding/json" "fmt" @@ -13,8 +14,6 @@ import ( "strings" "testing" - "github.com/nspcc-dev/neo-go/pkg/crypto/hash" - "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/stretchr/testify/require" @@ -33,8 +32,6 @@ type ( Name string Script vmUTScript Steps []vmUTStep - // FIXME remove when NEO 3.0 https://github.com/nspcc-dev/neo-go/issues/477 - ScriptTable []map[string]vmUTScript } vmUTExecutionContextState struct { @@ -94,6 +91,7 @@ const ( ) func TestUT(t *testing.T) { + t.Skip() testsRan := false err := filepath.Walk(testsDir, func(path string, info os.FileInfo, err error) error { if !strings.HasSuffix(path, ".json") { @@ -110,9 +108,7 @@ func TestUT(t *testing.T) { } func getTestingInterop(id uint32) *InteropFuncPrice { - // FIXME in NEO 3.0 it is []byte{0x77, 0x77, 0x77, 0x77} https://github.com/nspcc-dev/neo-go/issues/477 - if id == InteropNameToID([]byte("Test.ExecutionEngine.GetScriptContainer")) || - id == InteropNameToID([]byte("System.ExecutionEngine.GetScriptContainer")) { + if id == binary.LittleEndian.Uint32([]byte{0x77, 0x77, 0x77, 0x77}) { return &InteropFuncPrice{InteropFunc(func(v *VM) error { v.estack.Push(&Element{value: (*InteropItem)(nil)}) return nil @@ -125,11 +121,6 @@ func testFile(t *testing.T, filename string) { data, err := ioutil.ReadFile(filename) require.NoError(t, err) - // FIXME remove when NEO 3.0 https://github.com/nspcc-dev/neo-go/issues/477 - if len(data) > 2 && data[0] == 0xef && data[1] == 0xbb && data[2] == 0xbf { - data = data[3:] - } - ut := new(vmUT) require.NoError(t, json.Unmarshal(data, ut)) @@ -140,9 +131,6 @@ func testFile(t *testing.T, filename string) { prog := []byte(test.Script) vm := load(prog) vm.state = breakState - - // FIXME remove when NEO 3.0 https://github.com/nspcc-dev/neo-go/issues/477 - vm.getScript = getScript(test.ScriptTable) vm.RegisterInteropGetter(getTestingInterop) for i := range test.Steps { @@ -174,17 +162,6 @@ func testFile(t *testing.T, filename string) { }) } -func getScript(scripts []map[string]vmUTScript) func(util.Uint160) ([]byte, bool) { - store := make(map[util.Uint160][]byte) - for i := range scripts { - for _, v := range scripts[i] { - store[hash.Hash160(v)] = []byte(v) - } - } - - return func(a util.Uint160) ([]byte, bool) { return store[a], true } -} - func compareItems(t *testing.T, a, b StackItem) { switch si := a.(type) { case *BigIntegerItem: diff --git a/pkg/vm/stack_item.go b/pkg/vm/stack_item.go index 19c5ea6e3..b6ed046a4 100644 --- a/pkg/vm/stack_item.go +++ b/pkg/vm/stack_item.go @@ -341,9 +341,7 @@ func (i *BoolItem) Bytes() []byte { if i.value { return []byte{1} } - // return []byte{0} - // FIXME revert when NEO 3.0 https://github.com/nspcc-dev/neo-go/issues/477 - return []byte{} + return []byte{0} } // TryBytes implements StackItem interface. diff --git a/pkg/vm/testdata/neo-vm b/pkg/vm/testdata/neo-vm index 15170c466..459280909 160000 --- a/pkg/vm/testdata/neo-vm +++ b/pkg/vm/testdata/neo-vm @@ -1 +1 @@ -Subproject commit 15170c46609ea61f6fcf6f36a90033bf658f2ab7 +Subproject commit 45928090908bea777962c6df5dec1dd1bbafd7a7 diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 4b56d1f8f..e36ef521a 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -479,11 +479,7 @@ func (v *VM) SetScriptGetter(gs func(util.Uint160) ([]byte, bool)) { // GetInteropID converts instruction parameter to an interop ID. func GetInteropID(parameter []byte) uint32 { - if len(parameter) == 4 { - return binary.LittleEndian.Uint32(parameter) - } - - return InteropNameToID(parameter) + return binary.LittleEndian.Uint32(parameter) } // GetInteropByID returns interop function together with price. @@ -615,15 +611,9 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic("negative index") } s := v.estack.Pop().Bytes() - if o > len(s) { - // panic("invalid offset") - // FIXME revert when NEO 3.0 https://github.com/nspcc-dev/neo-go/issues/477 - v.estack.PushVal("") - break - } last := l + o if last > len(s) { - last = len(s) + panic("invalid offset") } v.estack.PushVal(s[o:last]) diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index e1572e22e..dc847bef5 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -19,7 +19,7 @@ import ( ) func fooInteropGetter(id uint32) *InteropFuncPrice { - if id == InteropNameToID([]byte("foo")) { + if id == emit.InteropNameToID([]byte("foo")) { return &InteropFuncPrice{func(evm *VM) error { evm.Estack().PushVal(1) return nil @@ -41,22 +41,6 @@ func TestInteropHook(t *testing.T) { assert.Equal(t, big.NewInt(1), v.estack.Pop().value.Value()) } -func TestInteropHookViaID(t *testing.T) { - v := New() - v.RegisterInteropGetter(fooInteropGetter) - - buf := io.NewBufBinWriter() - fooid := InteropNameToID([]byte("foo")) - var id = make([]byte, 4) - binary.LittleEndian.PutUint32(id, fooid) - emit.Syscall(buf.BinWriter, string(id)) - emit.Opcode(buf.BinWriter, opcode.RET) - v.Load(buf.Bytes()) - runVM(t, v) - assert.Equal(t, 1, v.estack.Len()) - assert.Equal(t, big.NewInt(1), v.estack.Pop().value.Value()) -} - func TestRegisterInteropGetter(t *testing.T) { v := New() currRegistered := len(v.getInterop) @@ -563,11 +547,9 @@ func TestIteratorValues(t *testing.T) { } func getSyscallProg(name string) (prog []byte) { - prog = []byte{byte(opcode.SYSCALL)} - prog = append(prog, byte(len(name))) - prog = append(prog, name...) - - return + buf := io.NewBufBinWriter() + emit.Syscall(buf.BinWriter, name) + return buf.Bytes() } func getSerializeProg() (prog []byte) { @@ -704,15 +686,21 @@ func TestSerializeMap(t *testing.T) { } func TestSerializeMapCompat(t *testing.T) { - // Create a map, push key and value, add KV to map, serialize. - progHex := "c776036b65790576616c7565c468154e656f2e52756e74696d652e53657269616c697a65" resHex := "820100036b6579000576616c7565" - prog, err := hex.DecodeString(progHex) - require.NoError(t, err) res, err := hex.DecodeString(resHex) require.NoError(t, err) - vm := load(prog) + // Create a map, push key and value, add KV to map, serialize. + buf := io.NewBufBinWriter() + emit.Opcode(buf.BinWriter, opcode.NEWMAP) + emit.Opcode(buf.BinWriter, opcode.DUP) + emit.Bytes(buf.BinWriter, []byte("key")) + emit.Bytes(buf.BinWriter, []byte("value")) + emit.Opcode(buf.BinWriter, opcode.SETITEM) + emit.Syscall(buf.BinWriter, "Neo.Runtime.Serialize") + require.NoError(t, buf.Err) + + vm := load(buf.Bytes()) runVM(t, vm) assert.Equal(t, res, vm.estack.Pop().Bytes()) } @@ -1505,9 +1493,7 @@ func TestSIZEBool(t *testing.T) { vm.estack.PushVal(false) runVM(t, vm) assert.Equal(t, 1, vm.estack.Len()) - // assert.Equal(t, makeStackItem(1), vm.estack.Pop().value) - // FIXME revert when NEO 3.0 https://github.com/nspcc-dev/neo-go/issues/477 - assert.Equal(t, makeStackItem(0), vm.estack.Pop().value) + assert.Equal(t, makeStackItem(1), vm.estack.Pop().value) } func TestARRAYSIZEArray(t *testing.T) { @@ -2215,7 +2201,7 @@ func TestCATInt0ByteArray(t *testing.T) { vm.estack.PushVal([]byte{}) runVM(t, vm) assert.Equal(t, 1, vm.estack.Len()) - assert.Equal(t, &ByteArrayItem{[]byte{0}}, vm.estack.Pop().value) + assert.Equal(t, &ByteArrayItem{[]byte{}}, vm.estack.Pop().value) } func TestCATByteArrayInt1(t *testing.T) { @@ -2267,11 +2253,7 @@ func TestSUBSTRBadOffset(t *testing.T) { vm.estack.PushVal(7) vm.estack.PushVal(1) - // checkVMFailed(t, vm) - // FIXME revert when NEO 3.0 https://github.com/nspcc-dev/neo-go/issues/477 - runVM(t, vm) - assert.Equal(t, 1, vm.estack.Len()) - assert.Equal(t, []byte{}, vm.estack.Peek(0).Bytes()) + checkVMFailed(t, vm) } func TestSUBSTRBigLen(t *testing.T) { @@ -2280,9 +2262,7 @@ func TestSUBSTRBigLen(t *testing.T) { vm.estack.PushVal([]byte("abcdef")) vm.estack.PushVal(1) vm.estack.PushVal(6) - runVM(t, vm) - assert.Equal(t, 1, vm.estack.Len()) - assert.Equal(t, []byte("bcdef"), vm.estack.Pop().Bytes()) + checkVMFailed(t, vm) } func TestSUBSTRBad387(t *testing.T) { @@ -2293,9 +2273,7 @@ func TestSUBSTRBad387(t *testing.T) { vm.estack.PushVal(b) vm.estack.PushVal(1) vm.estack.PushVal(6) - runVM(t, vm) - assert.Equal(t, 1, vm.estack.Len()) - assert.Equal(t, []byte("bcdef"), vm.estack.Pop().Bytes()) + checkVMFailed(t, vm) } func TestSUBSTRBadNegativeOffset(t *testing.T) {