From ca127f161596c2d7b26f9fe20b526ae648333986 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 2 Jun 2022 08:00:03 +0300 Subject: [PATCH] core: fix native NEO ABI This commit fixes T5 statediff at block #0. The reason in Management's storage state. The diff occurs because of inconsistent NEO methods order. See https://github.com/neo-project/neo/issues/2766#issue-1257870089. The current solution is to preserve C#'s order of methods to be compatible with current testnet. See also https://docs.microsoft.com/ru-ru/dotnet/api/system.stringcomparer?view=net-6.0 and https://stackoverflow.com/questions/28638714/easiest-method-to-orderby-a-string-using-stringcomparison-ordinal for more details. --- pkg/core/interop/context.go | 4 ++-- pkg/core/interop_system_core_test.go | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) 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) + } + }) + } +}