diff --git a/pkg/compiler/native_test.go b/pkg/compiler/native_test.go index 49460401b..a486e49c0 100644 --- a/pkg/compiler/native_test.go +++ b/pkg/compiler/native_test.go @@ -282,7 +282,7 @@ func getMethod(t *testing.T, ctr interop.ContractMD, name string, params []strin } md, ok := ctr.GetMethod(name, paramLen) - require.True(t, ok) + require.True(t, ok, ctr.Manifest.Name, name, paramLen) return md } diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index 4a734ad42..0c7419284 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -207,7 +207,7 @@ func (c *ContractMD) AddMethod(md *MethodAndPrice, desc *manifest.Method) { index := sort.Search(len(c.Manifest.ABI.Methods), func(i int) bool { md := c.Manifest.ABI.Methods[i] if md.Name != desc.Name { - return md.Name >= desc.Name + return strings.ToLower(md.Name) >= strings.ToLower(desc.Name) } return len(md.Parameters) > len(desc.Parameters) }) @@ -236,7 +236,7 @@ func (c *ContractMD) GetMethodByOffset(offset int) (MethodAndPrice, bool) { func (c *ContractMD) GetMethod(name string, paramCount int) (MethodAndPrice, bool) { index := sort.Search(len(c.Methods), func(i int) bool { md := c.Methods[i] - res := strings.Compare(name, md.MD.Name) + res := strings.Compare(strings.ToLower(name), strings.ToLower(md.MD.Name)) switch res { case -1, 1: return res == -1 diff --git a/pkg/core/interop_system_core_test.go b/pkg/core/interop_system_core_test.go index 7beff0888..e0211922f 100644 --- a/pkg/core/interop_system_core_test.go +++ b/pkg/core/interop_system_core_test.go @@ -967,3 +967,18 @@ func TestRuntimeCheckWitness(t *testing.T) { }) }) } + +// TestNativeGetMethod is needed to ensure that methods list has the same sorting +// rule as we expect inside the `ContractMD.GetMethod`. +func TestNativeGetMethod(t *testing.T) { + cfg := config.ProtocolConfiguration{P2PSigExtensions: true} + cs := native.NewContracts(cfg) + for _, c := range cs.Contracts { + t.Run(c.Metadata().Name, func(t *testing.T) { + for _, m := range c.Metadata().Methods { + _, ok := c.Metadata().GetMethod(m.MD.Name, len(m.MD.Parameters)) + require.True(t, ok) + } + }) + } +} diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go index b30266624..eee25bef6 100644 --- a/pkg/core/native/management.go +++ b/pkg/core/native/management.go @@ -614,7 +614,7 @@ func checkScriptAndMethods(script []byte, methods []manifest.Method) error { offsets := bitfield.New(l) for i := range methods { if methods[i].Offset >= l { - return errors.New("out of bounds method offset") + continue } offsets.Set(methods[i].Offset) } diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index cde774216..7020accc1 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -205,7 +205,7 @@ func newNEO(cfg config.ProtocolConfiguration) *NEO { n.AddMethod(md, desc) desc = newDescriptor("getCandidateVote", smartcontract.IntegerType, - manifest.NewParameter("pubkey", smartcontract.PublicKeyType)) + manifest.NewParameter("pubKey", smartcontract.PublicKeyType)) md = newMethodAndPrice(n.getCandidateVoteCall, 1<<15, callflag.ReadStates) n.AddMethod(md, desc) diff --git a/pkg/core/native/native_test/management_test.go b/pkg/core/native/native_test/management_test.go index e2c690c16..4f2eb3507 100644 --- a/pkg/core/native/native_test/management_test.go +++ b/pkg/core/native/native_test/management_test.go @@ -135,13 +135,20 @@ func TestManagement_ContractDeploy(t *testing.T) { badManifest := cs1.Manifest badManifest.ABI.Methods = make([]manifest.Method, len(cs1.Manifest.ABI.Methods)) copy(badManifest.ABI.Methods, cs1.Manifest.ABI.Methods) - badManifest.ABI.Methods[0].Offset = 100500 // out of bounds + badManifest.ABI.Methods[0].Offset = 100500 // out of bounds, but it's OK, this method will not be checked then. manifB, err := json.Marshal(&badManifest) require.NoError(t, err) - managementInvoker.InvokeFail(t, "out of bounds method offset", "deploy", nefBytes, manifB) - }) + tx := c.PrepareInvokeNoSign(t, "deploy", nefBytes, manifB) + tx.Signers = []transaction.Signer{{}} // Need dummy signer to deploy. + b := c.NewUnsignedBlock(t, tx) + ic := c.Chain.GetTestVM(trigger.Application, tx, b) + t.Cleanup(ic.Finalize) + ic.VM.LoadWithFlags(tx.Script, callflag.All) + err = ic.VM.Run() + require.NoError(t, err) + }) t.Run("bad methods in manifest 2", func(t *testing.T) { var badManifest = cs1.Manifest badManifest.ABI.Methods = make([]manifest.Method, len(cs1.Manifest.ABI.Methods)) @@ -153,6 +160,26 @@ func TestManagement_ContractDeploy(t *testing.T) { managementInvoker.InvokeFail(t, "some methods point to wrong offsets (not to instruction boundary)", "deploy", nefBytes, manifB) }) + t.Run("duplicated methods in manifest 1", func(t *testing.T) { + badManifest := cs1.Manifest + badManifest.ABI.Methods = make([]manifest.Method, len(cs1.Manifest.ABI.Methods)) + copy(badManifest.ABI.Methods, cs1.Manifest.ABI.Methods) + badManifest.ABI.Methods[0] = badManifest.ABI.Methods[1] // duplicates + manifB, err := json.Marshal(&badManifest) + require.NoError(t, err) + + managementInvoker.InvokeFail(t, "duplicate method specifications", "deploy", nefBytes, manifB) + }) + t.Run("duplicated events in manifest 1", func(t *testing.T) { + badManifest := cs1.Manifest + badManifest.ABI.Methods = make([]manifest.Method, len(cs1.Manifest.ABI.Methods)) + copy(badManifest.ABI.Methods, cs1.Manifest.ABI.Methods) + badManifest.ABI.Events = []manifest.Event{{Name: "event"}, {Name: "event"}} // duplicates + manifB, err := json.Marshal(&badManifest) + require.NoError(t, err) + + managementInvoker.InvokeFail(t, "duplicate event names", "deploy", nefBytes, manifB) + }) t.Run("not enough GAS", func(t *testing.T) { tx := managementInvoker.NewUnsignedTx(t, managementInvoker.Hash, "deploy", nefBytes, manifestBytes) diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index 8917c1e41..1c15f9ddf 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -75,7 +75,7 @@ const ( nfsoContractHash = "c7ec8e0fb4d669913e4ffdd4ba4fa3502e5d2d10" nfsoToken1ID = "7e244ffd6aa85fb1579d2ed22e9b761ab62e3486" invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA" - block20StateRootLE = "93ebfc8b030de02c5548ae08ac4a0ea39c12c82e62609ae07bdf3d803bcf9ffd" + block20StateRootLE = "3cba730383c4c2c34475939a4efe9de9ac377bffaf0abdb6f8a1a8fe145d8f69" ) var (