From bcc5fd09563fde07893cd59b4d07d402727d6b10 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Aug 2024 00:24:40 +0800 Subject: [PATCH 01/25] add hardofork HF_Echidna --- src/Neo.CLI/config.fs.mainnet.json | 3 ++- src/Neo.CLI/config.json | 3 ++- src/Neo.CLI/config.mainnet.json | 3 ++- src/Neo.CLI/config.testnet.json | 3 ++- src/Neo/Hardfork.cs | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Neo.CLI/config.fs.mainnet.json b/src/Neo.CLI/config.fs.mainnet.json index 6879232732..c12372b43b 100644 --- a/src/Neo.CLI/config.fs.mainnet.json +++ b/src/Neo.CLI/config.fs.mainnet.json @@ -40,7 +40,8 @@ "HF_Aspidochelone": 3000000, "HF_Basilisk": 4500000, "HF_Cockatrice": 5800000, - "HF_Domovoi": 5800000 + "HF_Domovoi": 5800000, + "HF_Echidna": 0 }, "StandbyCommittee": [ "026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086", diff --git a/src/Neo.CLI/config.json b/src/Neo.CLI/config.json index 772a221714..9e97ec1f00 100644 --- a/src/Neo.CLI/config.json +++ b/src/Neo.CLI/config.json @@ -38,7 +38,8 @@ "HF_Aspidochelone": 1730000, "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, - "HF_Domovoi": 5570000 + "HF_Domovoi": 5570000, + "HF_Echidna": 0 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.mainnet.json b/src/Neo.CLI/config.mainnet.json index 772a221714..9e97ec1f00 100644 --- a/src/Neo.CLI/config.mainnet.json +++ b/src/Neo.CLI/config.mainnet.json @@ -38,7 +38,8 @@ "HF_Aspidochelone": 1730000, "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, - "HF_Domovoi": 5570000 + "HF_Domovoi": 5570000, + "HF_Echidna": 0 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.testnet.json b/src/Neo.CLI/config.testnet.json index dc102be54b..88a04794f0 100644 --- a/src/Neo.CLI/config.testnet.json +++ b/src/Neo.CLI/config.testnet.json @@ -38,7 +38,8 @@ "HF_Aspidochelone": 210000, "HF_Basilisk": 2680000, "HF_Cockatrice": 3967000, - "HF_Domovoi": 4144000 + "HF_Domovoi": 4144000, + "HF_Echidna": 0 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo/Hardfork.cs b/src/Neo/Hardfork.cs index 7bd3cc0aef..9276c9c07d 100644 --- a/src/Neo/Hardfork.cs +++ b/src/Neo/Hardfork.cs @@ -16,6 +16,7 @@ public enum Hardfork : byte HF_Aspidochelone, HF_Basilisk, HF_Cockatrice, - HF_Domovoi + HF_Domovoi, + HF_Echidna } } From e63f10b3ad7d96ab2cf456f7faf101724f406e17 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 8 Aug 2024 01:54:41 -0700 Subject: [PATCH 02/25] Add entries to `Designation` event (#3397) * Add entries to Designation event * Change to HF_Echidna * Add UT * Add count --- .../SmartContract/Native/RoleManagement.cs | 24 +++++++++++++++++-- .../SmartContract/Native/UT_NativeContract.cs | 18 ++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/Native/RoleManagement.cs b/src/Neo/SmartContract/Native/RoleManagement.cs index d0437594c9..a0fc82f126 100644 --- a/src/Neo/SmartContract/Native/RoleManagement.cs +++ b/src/Neo/SmartContract/Native/RoleManagement.cs @@ -26,7 +26,16 @@ public sealed class RoleManagement : NativeContract { [ContractEvent(0, name: "Designation", "Role", ContractParameterType.Integer, - "BlockIndex", ContractParameterType.Integer)] + "BlockIndex", ContractParameterType.Integer, + Hardfork.HF_Echidna)] + + [ContractEvent(Hardfork.HF_Echidna, 0, name: "Designation", + "Role", ContractParameterType.Integer, + "BlockIndex", ContractParameterType.Integer, + "Old", ContractParameterType.Array, + "New", ContractParameterType.Array + )] + internal RoleManagement() : base() { } /// @@ -69,7 +78,18 @@ private void DesignateAsRole(ApplicationEngine engine, Role role, ECPoint[] node list.AddRange(nodes); list.Sort(); engine.SnapshotCache.Add(key, new StorageItem(list)); - engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, new StackItem[] { (int)role, engine.PersistingBlock.Index })); + + if (engine.IsHardforkEnabled(Hardfork.HF_Echidna)) + { + var oldNodes = new VM.Types.Array(engine.ReferenceCounter, GetDesignatedByRole(engine.Snapshot, role, index - 1).Select(u => (ByteString)u.EncodePoint(true))); + var newNodes = new VM.Types.Array(engine.ReferenceCounter, nodes.Select(u => (ByteString)u.EncodePoint(true))); + + engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, [(int)role, engine.PersistingBlock.Index, oldNodes, newNodes])); + } + else + { + engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, [(int)role, engine.PersistingBlock.Index])); + } } private class NodeList : InteroperableList diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index f9a3089f9d..627a9fdd3c 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -80,6 +80,24 @@ public void TestActiveDeprecatedIn() Assert.IsFalse(NativeContract.IsActive(new active() { ActiveIn = null, DeprecatedIn = Hardfork.HF_Cockatrice }, settings.IsHardforkEnabled, 20)); } + [TestMethod] + public void TestActiveDeprecatedInRoleManagement() + { + string json = UT_ProtocolSettings.CreateHKSettings("\"HF_Echidna\": 20"); + var file = Path.GetTempFileName(); + File.WriteAllText(file, json); + ProtocolSettings settings = ProtocolSettings.Load(file, false); + File.Delete(file); + + var before = NativeContract.RoleManagement.GetContractState(settings.IsHardforkEnabled, 19); + var after = NativeContract.RoleManagement.GetContractState(settings.IsHardforkEnabled, 20); + + Assert.AreEqual(2, before.Manifest.Abi.Events[0].Parameters.Length); + Assert.AreEqual(1, before.Manifest.Abi.Events.Length); + Assert.AreEqual(4, after.Manifest.Abi.Events[0].Parameters.Length); + Assert.AreEqual(1, after.Manifest.Abi.Events.Length); + } + [TestMethod] public void TestGetContract() { From 9d16c53741e1373cd96226fe98008f9e46400ce6 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Aug 2024 03:42:18 +0800 Subject: [PATCH 03/25] [Neo Core StdLib] Add Base64url (#3453) * add base64url * active in * update placehold hf height * fix hf issue and move methods to proper place. * fix test * use identifymodel instead. --- src/Neo.CLI/config.fs.mainnet.json | 2 +- src/Neo.CLI/config.json | 2 +- src/Neo.CLI/config.mainnet.json | 2 +- src/Neo.CLI/config.testnet.json | 2 +- src/Neo/Neo.csproj | 1 + src/Neo/SmartContract/Native/StdLib.cs | 23 +++++++++++++++++++ .../SmartContract/Native/UT_NativeContract.cs | 2 +- .../SmartContract/Native/UT_StdLib.cs | 20 ++++++++++++++++ 8 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/Neo.CLI/config.fs.mainnet.json b/src/Neo.CLI/config.fs.mainnet.json index c12372b43b..bbd17978e3 100644 --- a/src/Neo.CLI/config.fs.mainnet.json +++ b/src/Neo.CLI/config.fs.mainnet.json @@ -41,7 +41,7 @@ "HF_Basilisk": 4500000, "HF_Cockatrice": 5800000, "HF_Domovoi": 5800000, - "HF_Echidna": 0 + "HF_Echidna": 5800001 }, "StandbyCommittee": [ "026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086", diff --git a/src/Neo.CLI/config.json b/src/Neo.CLI/config.json index 9e97ec1f00..9590fc60fd 100644 --- a/src/Neo.CLI/config.json +++ b/src/Neo.CLI/config.json @@ -39,7 +39,7 @@ "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, "HF_Domovoi": 5570000, - "HF_Echidna": 0 + "HF_Echidna": 5570001 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.mainnet.json b/src/Neo.CLI/config.mainnet.json index 9e97ec1f00..9590fc60fd 100644 --- a/src/Neo.CLI/config.mainnet.json +++ b/src/Neo.CLI/config.mainnet.json @@ -39,7 +39,7 @@ "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, "HF_Domovoi": 5570000, - "HF_Echidna": 0 + "HF_Echidna": 5570001 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.testnet.json b/src/Neo.CLI/config.testnet.json index 88a04794f0..8bcd6d8956 100644 --- a/src/Neo.CLI/config.testnet.json +++ b/src/Neo.CLI/config.testnet.json @@ -39,7 +39,7 @@ "HF_Basilisk": 2680000, "HF_Cockatrice": 3967000, "HF_Domovoi": 4144000, - "HF_Echidna": 0 + "HF_Echidna": 4144001 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo/Neo.csproj b/src/Neo/Neo.csproj index 7c6478c33e..f4f2cb36b3 100644 --- a/src/Neo/Neo.csproj +++ b/src/Neo/Neo.csproj @@ -16,6 +16,7 @@ + diff --git a/src/Neo/SmartContract/Native/StdLib.cs b/src/Neo/SmartContract/Native/StdLib.cs index f8fa9efcc2..1b4030d9f5 100644 --- a/src/Neo/SmartContract/Native/StdLib.cs +++ b/src/Neo/SmartContract/Native/StdLib.cs @@ -11,6 +11,7 @@ #pragma warning disable IDE0051 +using Microsoft.IdentityModel.Tokens; using Neo.Cryptography; using Neo.Json; using Neo.VM.Types; @@ -131,6 +132,28 @@ public static byte[] Base64Decode([MaxLength(MaxInputLength)] string s) return Convert.FromBase64String(s); } + /// + /// Encodes a byte array into a base64Url string. + /// + /// The base64Url to be encoded. + /// The encoded base64Url string. + [ContractMethod(Hardfork.HF_Echidna, CpuFee = 1 << 5)] + public static string Base64UrlEncode([MaxLength(MaxInputLength)] string data) + { + return Base64UrlEncoder.Encode(data); + } + + /// + /// Decodes a byte array from a base64Url string. + /// + /// The base64Url string. + /// The decoded base64Url string. + [ContractMethod(Hardfork.HF_Echidna, CpuFee = 1 << 5)] + public static string Base64UrlDecode([MaxLength(MaxInputLength)] string s) + { + return Base64UrlEncoder.Decode(s); + } + /// /// Encodes a byte array into a base58 . /// diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index 627a9fdd3c..26e00a3c2d 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -41,7 +41,7 @@ public void TestSetup() _nativeStates = new Dictionary { {"ContractManagement", """{"id":-1,"updatecounter":0,"hash":"0xfffdc93764dbaddd97c48f252a53ea4643faa3fd","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"ContractManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Array","offset":0,"safe":false},{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Array","offset":7,"safe":false},{"name":"destroy","parameters":[],"returntype":"Void","offset":14,"safe":false},{"name":"getContract","parameters":[{"name":"hash","type":"Hash160"}],"returntype":"Array","offset":21,"safe":true},{"name":"getContractById","parameters":[{"name":"id","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getContractHashes","parameters":[],"returntype":"InteropInterface","offset":35,"safe":true},{"name":"getMinimumDeploymentFee","parameters":[],"returntype":"Integer","offset":42,"safe":true},{"name":"hasMethod","parameters":[{"name":"hash","type":"Hash160"},{"name":"method","type":"String"},{"name":"pcount","type":"Integer"}],"returntype":"Boolean","offset":49,"safe":true},{"name":"setMinimumDeploymentFee","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":56,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Void","offset":63,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","offset":70,"safe":false}],"events":[{"name":"Deploy","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Update","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Destroy","parameters":[{"name":"Hash","type":"Hash160"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}""" }, - {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1991619121},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":56,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":63,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":70,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":77,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":84,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":91,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":98,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":112,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":119,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":126,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":133,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":140,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, + {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2681632925},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":77,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":84,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":91,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":98,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":112,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":126,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":133,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":140,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":147,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":154,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"CryptoLib", """{"id":-3,"updatecounter":0,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"bls12381Add","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","offset":0,"safe":true},{"name":"bls12381Deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","offset":7,"safe":true},{"name":"bls12381Equal","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","offset":14,"safe":true},{"name":"bls12381Mul","parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"bls12381Pairing","parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","offset":28,"safe":true},{"name":"bls12381Serialize","parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","offset":35,"safe":true},{"name":"keccak256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"murmur32","parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","offset":49,"safe":true},{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":63,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","offset":70,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"LedgerContract", """{"id":-4,"updatecounter":0,"hash":"0xda65b600f7124ce6c79950c1772a36403104f2be","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"LedgerContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"currentHash","parameters":[],"returntype":"Hash256","offset":0,"safe":true},{"name":"currentIndex","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlock","parameters":[{"name":"indexOrHash","type":"ByteArray"}],"returntype":"Array","offset":14,"safe":true},{"name":"getTransaction","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":21,"safe":true},{"name":"getTransactionFromBlock","parameters":[{"name":"blockIndexOrHash","type":"ByteArray"},{"name":"txIndex","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getTransactionHeight","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":35,"safe":true},{"name":"getTransactionSigners","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":42,"safe":true},{"name":"getTransactionVMState","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":49,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1325686241},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":77,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":84,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":98,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":105,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":112,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":126,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs index 1dffb3d384..f9761bee07 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs @@ -406,5 +406,25 @@ public void TestRuntime_Deserialize() Assert.AreEqual(engine.ResultStack.Pop().GetInteger(), 100); Assert.AreEqual(engine.ResultStack.Pop().GetString(), "test"); } + + [TestMethod] + public void TestBase64Url() + { + var snapshotCache = TestBlockchain.GetTestSnapshotCache(); + using (var script = new ScriptBuilder()) + { + // Test encoding + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base64UrlEncode", "Subject=test@example.com&Issuer=https://example.com"); + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base64UrlDecode", "U3ViamVjdD10ZXN0QGV4YW1wbGUuY29tJklzc3Vlcj1odHRwczovL2V4YW1wbGUuY29t"); + + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache, settings: TestBlockchain.TheNeoSystem.Settings); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(2, engine.ResultStack.Count); + Assert.AreEqual("Subject=test@example.com&Issuer=https://example.com", engine.ResultStack.Pop()); + Assert.AreEqual("U3ViamVjdD10ZXN0QGV4YW1wbGUuY29tJklzc3Vlcj1odHRwczovL2V4YW1wbGUuY29t", engine.ResultStack.Pop().GetString()); + } + } } } From f746f8de81958560bbd45c8d225931a559fb3ec4 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Aug 2024 00:24:40 +0800 Subject: [PATCH 04/25] add hardofork HF_Echidna --- src/Neo.CLI/config.fs.mainnet.json | 3 ++- src/Neo.CLI/config.json | 3 ++- src/Neo.CLI/config.mainnet.json | 3 ++- src/Neo.CLI/config.testnet.json | 3 ++- src/Neo/Hardfork.cs | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Neo.CLI/config.fs.mainnet.json b/src/Neo.CLI/config.fs.mainnet.json index 6879232732..c12372b43b 100644 --- a/src/Neo.CLI/config.fs.mainnet.json +++ b/src/Neo.CLI/config.fs.mainnet.json @@ -40,7 +40,8 @@ "HF_Aspidochelone": 3000000, "HF_Basilisk": 4500000, "HF_Cockatrice": 5800000, - "HF_Domovoi": 5800000 + "HF_Domovoi": 5800000, + "HF_Echidna": 0 }, "StandbyCommittee": [ "026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086", diff --git a/src/Neo.CLI/config.json b/src/Neo.CLI/config.json index 772a221714..9e97ec1f00 100644 --- a/src/Neo.CLI/config.json +++ b/src/Neo.CLI/config.json @@ -38,7 +38,8 @@ "HF_Aspidochelone": 1730000, "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, - "HF_Domovoi": 5570000 + "HF_Domovoi": 5570000, + "HF_Echidna": 0 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.mainnet.json b/src/Neo.CLI/config.mainnet.json index 772a221714..9e97ec1f00 100644 --- a/src/Neo.CLI/config.mainnet.json +++ b/src/Neo.CLI/config.mainnet.json @@ -38,7 +38,8 @@ "HF_Aspidochelone": 1730000, "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, - "HF_Domovoi": 5570000 + "HF_Domovoi": 5570000, + "HF_Echidna": 0 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.testnet.json b/src/Neo.CLI/config.testnet.json index dc102be54b..88a04794f0 100644 --- a/src/Neo.CLI/config.testnet.json +++ b/src/Neo.CLI/config.testnet.json @@ -38,7 +38,8 @@ "HF_Aspidochelone": 210000, "HF_Basilisk": 2680000, "HF_Cockatrice": 3967000, - "HF_Domovoi": 4144000 + "HF_Domovoi": 4144000, + "HF_Echidna": 0 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo/Hardfork.cs b/src/Neo/Hardfork.cs index 7bd3cc0aef..9276c9c07d 100644 --- a/src/Neo/Hardfork.cs +++ b/src/Neo/Hardfork.cs @@ -16,6 +16,7 @@ public enum Hardfork : byte HF_Aspidochelone, HF_Basilisk, HF_Cockatrice, - HF_Domovoi + HF_Domovoi, + HF_Echidna } } From 8d7f9e8ccbd556bf488994a6944f5f3b5a443682 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 8 Aug 2024 01:54:41 -0700 Subject: [PATCH 05/25] Add entries to `Designation` event (#3397) * Add entries to Designation event * Change to HF_Echidna * Add UT * Add count --- .../SmartContract/Native/RoleManagement.cs | 24 +++++++++++++++++-- .../SmartContract/Native/UT_NativeContract.cs | 18 ++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/Native/RoleManagement.cs b/src/Neo/SmartContract/Native/RoleManagement.cs index d0437594c9..a0fc82f126 100644 --- a/src/Neo/SmartContract/Native/RoleManagement.cs +++ b/src/Neo/SmartContract/Native/RoleManagement.cs @@ -26,7 +26,16 @@ public sealed class RoleManagement : NativeContract { [ContractEvent(0, name: "Designation", "Role", ContractParameterType.Integer, - "BlockIndex", ContractParameterType.Integer)] + "BlockIndex", ContractParameterType.Integer, + Hardfork.HF_Echidna)] + + [ContractEvent(Hardfork.HF_Echidna, 0, name: "Designation", + "Role", ContractParameterType.Integer, + "BlockIndex", ContractParameterType.Integer, + "Old", ContractParameterType.Array, + "New", ContractParameterType.Array + )] + internal RoleManagement() : base() { } /// @@ -69,7 +78,18 @@ private void DesignateAsRole(ApplicationEngine engine, Role role, ECPoint[] node list.AddRange(nodes); list.Sort(); engine.SnapshotCache.Add(key, new StorageItem(list)); - engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, new StackItem[] { (int)role, engine.PersistingBlock.Index })); + + if (engine.IsHardforkEnabled(Hardfork.HF_Echidna)) + { + var oldNodes = new VM.Types.Array(engine.ReferenceCounter, GetDesignatedByRole(engine.Snapshot, role, index - 1).Select(u => (ByteString)u.EncodePoint(true))); + var newNodes = new VM.Types.Array(engine.ReferenceCounter, nodes.Select(u => (ByteString)u.EncodePoint(true))); + + engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, [(int)role, engine.PersistingBlock.Index, oldNodes, newNodes])); + } + else + { + engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, [(int)role, engine.PersistingBlock.Index])); + } } private class NodeList : InteroperableList diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index f9a3089f9d..627a9fdd3c 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -80,6 +80,24 @@ public void TestActiveDeprecatedIn() Assert.IsFalse(NativeContract.IsActive(new active() { ActiveIn = null, DeprecatedIn = Hardfork.HF_Cockatrice }, settings.IsHardforkEnabled, 20)); } + [TestMethod] + public void TestActiveDeprecatedInRoleManagement() + { + string json = UT_ProtocolSettings.CreateHKSettings("\"HF_Echidna\": 20"); + var file = Path.GetTempFileName(); + File.WriteAllText(file, json); + ProtocolSettings settings = ProtocolSettings.Load(file, false); + File.Delete(file); + + var before = NativeContract.RoleManagement.GetContractState(settings.IsHardforkEnabled, 19); + var after = NativeContract.RoleManagement.GetContractState(settings.IsHardforkEnabled, 20); + + Assert.AreEqual(2, before.Manifest.Abi.Events[0].Parameters.Length); + Assert.AreEqual(1, before.Manifest.Abi.Events.Length); + Assert.AreEqual(4, after.Manifest.Abi.Events[0].Parameters.Length); + Assert.AreEqual(1, after.Manifest.Abi.Events.Length); + } + [TestMethod] public void TestGetContract() { From 3fc8077e17df8112de51dd260395455e27c69004 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Aug 2024 03:42:18 +0800 Subject: [PATCH 06/25] [Neo Core StdLib] Add Base64url (#3453) * add base64url * active in * update placehold hf height * fix hf issue and move methods to proper place. * fix test * use identifymodel instead. --- src/Neo.CLI/config.fs.mainnet.json | 2 +- src/Neo.CLI/config.json | 2 +- src/Neo.CLI/config.mainnet.json | 2 +- src/Neo.CLI/config.testnet.json | 2 +- src/Neo/Neo.csproj | 1 + src/Neo/SmartContract/Native/StdLib.cs | 23 +++++++++++++++++++ .../SmartContract/Native/UT_NativeContract.cs | 2 +- .../SmartContract/Native/UT_StdLib.cs | 20 ++++++++++++++++ 8 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/Neo.CLI/config.fs.mainnet.json b/src/Neo.CLI/config.fs.mainnet.json index c12372b43b..bbd17978e3 100644 --- a/src/Neo.CLI/config.fs.mainnet.json +++ b/src/Neo.CLI/config.fs.mainnet.json @@ -41,7 +41,7 @@ "HF_Basilisk": 4500000, "HF_Cockatrice": 5800000, "HF_Domovoi": 5800000, - "HF_Echidna": 0 + "HF_Echidna": 5800001 }, "StandbyCommittee": [ "026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086", diff --git a/src/Neo.CLI/config.json b/src/Neo.CLI/config.json index 9e97ec1f00..9590fc60fd 100644 --- a/src/Neo.CLI/config.json +++ b/src/Neo.CLI/config.json @@ -39,7 +39,7 @@ "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, "HF_Domovoi": 5570000, - "HF_Echidna": 0 + "HF_Echidna": 5570001 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.mainnet.json b/src/Neo.CLI/config.mainnet.json index 9e97ec1f00..9590fc60fd 100644 --- a/src/Neo.CLI/config.mainnet.json +++ b/src/Neo.CLI/config.mainnet.json @@ -39,7 +39,7 @@ "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, "HF_Domovoi": 5570000, - "HF_Echidna": 0 + "HF_Echidna": 5570001 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.testnet.json b/src/Neo.CLI/config.testnet.json index 88a04794f0..8bcd6d8956 100644 --- a/src/Neo.CLI/config.testnet.json +++ b/src/Neo.CLI/config.testnet.json @@ -39,7 +39,7 @@ "HF_Basilisk": 2680000, "HF_Cockatrice": 3967000, "HF_Domovoi": 4144000, - "HF_Echidna": 0 + "HF_Echidna": 4144001 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo/Neo.csproj b/src/Neo/Neo.csproj index 7c6478c33e..f4f2cb36b3 100644 --- a/src/Neo/Neo.csproj +++ b/src/Neo/Neo.csproj @@ -16,6 +16,7 @@ + diff --git a/src/Neo/SmartContract/Native/StdLib.cs b/src/Neo/SmartContract/Native/StdLib.cs index f8fa9efcc2..1b4030d9f5 100644 --- a/src/Neo/SmartContract/Native/StdLib.cs +++ b/src/Neo/SmartContract/Native/StdLib.cs @@ -11,6 +11,7 @@ #pragma warning disable IDE0051 +using Microsoft.IdentityModel.Tokens; using Neo.Cryptography; using Neo.Json; using Neo.VM.Types; @@ -131,6 +132,28 @@ public static byte[] Base64Decode([MaxLength(MaxInputLength)] string s) return Convert.FromBase64String(s); } + /// + /// Encodes a byte array into a base64Url string. + /// + /// The base64Url to be encoded. + /// The encoded base64Url string. + [ContractMethod(Hardfork.HF_Echidna, CpuFee = 1 << 5)] + public static string Base64UrlEncode([MaxLength(MaxInputLength)] string data) + { + return Base64UrlEncoder.Encode(data); + } + + /// + /// Decodes a byte array from a base64Url string. + /// + /// The base64Url string. + /// The decoded base64Url string. + [ContractMethod(Hardfork.HF_Echidna, CpuFee = 1 << 5)] + public static string Base64UrlDecode([MaxLength(MaxInputLength)] string s) + { + return Base64UrlEncoder.Decode(s); + } + /// /// Encodes a byte array into a base58 . /// diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index 627a9fdd3c..26e00a3c2d 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -41,7 +41,7 @@ public void TestSetup() _nativeStates = new Dictionary { {"ContractManagement", """{"id":-1,"updatecounter":0,"hash":"0xfffdc93764dbaddd97c48f252a53ea4643faa3fd","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"ContractManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Array","offset":0,"safe":false},{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Array","offset":7,"safe":false},{"name":"destroy","parameters":[],"returntype":"Void","offset":14,"safe":false},{"name":"getContract","parameters":[{"name":"hash","type":"Hash160"}],"returntype":"Array","offset":21,"safe":true},{"name":"getContractById","parameters":[{"name":"id","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getContractHashes","parameters":[],"returntype":"InteropInterface","offset":35,"safe":true},{"name":"getMinimumDeploymentFee","parameters":[],"returntype":"Integer","offset":42,"safe":true},{"name":"hasMethod","parameters":[{"name":"hash","type":"Hash160"},{"name":"method","type":"String"},{"name":"pcount","type":"Integer"}],"returntype":"Boolean","offset":49,"safe":true},{"name":"setMinimumDeploymentFee","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":56,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Void","offset":63,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","offset":70,"safe":false}],"events":[{"name":"Deploy","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Update","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Destroy","parameters":[{"name":"Hash","type":"Hash160"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}""" }, - {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1991619121},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":56,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":63,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":70,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":77,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":84,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":91,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":98,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":112,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":119,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":126,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":133,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":140,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, + {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2681632925},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":77,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":84,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":91,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":98,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":112,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":126,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":133,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":140,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":147,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":154,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"CryptoLib", """{"id":-3,"updatecounter":0,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"bls12381Add","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","offset":0,"safe":true},{"name":"bls12381Deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","offset":7,"safe":true},{"name":"bls12381Equal","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","offset":14,"safe":true},{"name":"bls12381Mul","parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"bls12381Pairing","parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","offset":28,"safe":true},{"name":"bls12381Serialize","parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","offset":35,"safe":true},{"name":"keccak256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"murmur32","parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","offset":49,"safe":true},{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":63,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","offset":70,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"LedgerContract", """{"id":-4,"updatecounter":0,"hash":"0xda65b600f7124ce6c79950c1772a36403104f2be","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"LedgerContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"currentHash","parameters":[],"returntype":"Hash256","offset":0,"safe":true},{"name":"currentIndex","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlock","parameters":[{"name":"indexOrHash","type":"ByteArray"}],"returntype":"Array","offset":14,"safe":true},{"name":"getTransaction","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":21,"safe":true},{"name":"getTransactionFromBlock","parameters":[{"name":"blockIndexOrHash","type":"ByteArray"},{"name":"txIndex","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getTransactionHeight","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":35,"safe":true},{"name":"getTransactionSigners","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":42,"safe":true},{"name":"getTransactionVMState","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":49,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1325686241},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":77,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":84,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":98,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":105,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":112,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":126,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs index 1dffb3d384..f9761bee07 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs @@ -406,5 +406,25 @@ public void TestRuntime_Deserialize() Assert.AreEqual(engine.ResultStack.Pop().GetInteger(), 100); Assert.AreEqual(engine.ResultStack.Pop().GetString(), "test"); } + + [TestMethod] + public void TestBase64Url() + { + var snapshotCache = TestBlockchain.GetTestSnapshotCache(); + using (var script = new ScriptBuilder()) + { + // Test encoding + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base64UrlEncode", "Subject=test@example.com&Issuer=https://example.com"); + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base64UrlDecode", "U3ViamVjdD10ZXN0QGV4YW1wbGUuY29tJklzc3Vlcj1odHRwczovL2V4YW1wbGUuY29t"); + + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache, settings: TestBlockchain.TheNeoSystem.Settings); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(2, engine.ResultStack.Count); + Assert.AreEqual("Subject=test@example.com&Issuer=https://example.com", engine.ResultStack.Pop()); + Assert.AreEqual("U3ViamVjdD10ZXN0QGV4YW1wbGUuY29tJklzc3Vlcj1odHRwczovL2V4YW1wbGUuY29t", engine.ResultStack.Pop().GetString()); + } + } } } From 7e31d0caacfadb7634614d629c88b9244b434501 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Aug 2024 00:24:40 +0800 Subject: [PATCH 07/25] add hardofork HF_Echidna --- src/Neo.CLI/config.fs.mainnet.json | 3 ++- src/Neo.CLI/config.json | 3 ++- src/Neo.CLI/config.mainnet.json | 3 ++- src/Neo.CLI/config.testnet.json | 3 ++- src/Neo/Hardfork.cs | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Neo.CLI/config.fs.mainnet.json b/src/Neo.CLI/config.fs.mainnet.json index 6879232732..c12372b43b 100644 --- a/src/Neo.CLI/config.fs.mainnet.json +++ b/src/Neo.CLI/config.fs.mainnet.json @@ -40,7 +40,8 @@ "HF_Aspidochelone": 3000000, "HF_Basilisk": 4500000, "HF_Cockatrice": 5800000, - "HF_Domovoi": 5800000 + "HF_Domovoi": 5800000, + "HF_Echidna": 0 }, "StandbyCommittee": [ "026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086", diff --git a/src/Neo.CLI/config.json b/src/Neo.CLI/config.json index 772a221714..9e97ec1f00 100644 --- a/src/Neo.CLI/config.json +++ b/src/Neo.CLI/config.json @@ -38,7 +38,8 @@ "HF_Aspidochelone": 1730000, "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, - "HF_Domovoi": 5570000 + "HF_Domovoi": 5570000, + "HF_Echidna": 0 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.mainnet.json b/src/Neo.CLI/config.mainnet.json index 772a221714..9e97ec1f00 100644 --- a/src/Neo.CLI/config.mainnet.json +++ b/src/Neo.CLI/config.mainnet.json @@ -38,7 +38,8 @@ "HF_Aspidochelone": 1730000, "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, - "HF_Domovoi": 5570000 + "HF_Domovoi": 5570000, + "HF_Echidna": 0 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.testnet.json b/src/Neo.CLI/config.testnet.json index dc102be54b..88a04794f0 100644 --- a/src/Neo.CLI/config.testnet.json +++ b/src/Neo.CLI/config.testnet.json @@ -38,7 +38,8 @@ "HF_Aspidochelone": 210000, "HF_Basilisk": 2680000, "HF_Cockatrice": 3967000, - "HF_Domovoi": 4144000 + "HF_Domovoi": 4144000, + "HF_Echidna": 0 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo/Hardfork.cs b/src/Neo/Hardfork.cs index 7bd3cc0aef..9276c9c07d 100644 --- a/src/Neo/Hardfork.cs +++ b/src/Neo/Hardfork.cs @@ -16,6 +16,7 @@ public enum Hardfork : byte HF_Aspidochelone, HF_Basilisk, HF_Cockatrice, - HF_Domovoi + HF_Domovoi, + HF_Echidna } } From 993e3fe9dd4485387f8dd244885f616b4dd78de5 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 8 Aug 2024 01:54:41 -0700 Subject: [PATCH 08/25] Add entries to `Designation` event (#3397) * Add entries to Designation event * Change to HF_Echidna * Add UT * Add count --- .../SmartContract/Native/RoleManagement.cs | 24 +++++++++++++++++-- .../SmartContract/Native/UT_NativeContract.cs | 18 ++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/Native/RoleManagement.cs b/src/Neo/SmartContract/Native/RoleManagement.cs index e57f3f3e83..ecedba4c86 100644 --- a/src/Neo/SmartContract/Native/RoleManagement.cs +++ b/src/Neo/SmartContract/Native/RoleManagement.cs @@ -26,7 +26,16 @@ public sealed class RoleManagement : NativeContract { [ContractEvent(0, name: "Designation", "Role", ContractParameterType.Integer, - "BlockIndex", ContractParameterType.Integer)] + "BlockIndex", ContractParameterType.Integer, + Hardfork.HF_Echidna)] + + [ContractEvent(Hardfork.HF_Echidna, 0, name: "Designation", + "Role", ContractParameterType.Integer, + "BlockIndex", ContractParameterType.Integer, + "Old", ContractParameterType.Array, + "New", ContractParameterType.Array + )] + internal RoleManagement() : base() { } /// @@ -69,7 +78,18 @@ private void DesignateAsRole(ApplicationEngine engine, Role role, ECPoint[] node list.AddRange(nodes); list.Sort(); engine.SnapshotCache.Add(key, new StorageItem(list)); - engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, new StackItem[] { (int)role, engine.PersistingBlock.Index })); + + if (engine.IsHardforkEnabled(Hardfork.HF_Echidna)) + { + var oldNodes = new VM.Types.Array(engine.ReferenceCounter, GetDesignatedByRole(engine.Snapshot, role, index - 1).Select(u => (ByteString)u.EncodePoint(true))); + var newNodes = new VM.Types.Array(engine.ReferenceCounter, nodes.Select(u => (ByteString)u.EncodePoint(true))); + + engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, [(int)role, engine.PersistingBlock.Index, oldNodes, newNodes])); + } + else + { + engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, [(int)role, engine.PersistingBlock.Index])); + } } private class NodeList : InteroperableList diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index f9a3089f9d..627a9fdd3c 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -80,6 +80,24 @@ public void TestActiveDeprecatedIn() Assert.IsFalse(NativeContract.IsActive(new active() { ActiveIn = null, DeprecatedIn = Hardfork.HF_Cockatrice }, settings.IsHardforkEnabled, 20)); } + [TestMethod] + public void TestActiveDeprecatedInRoleManagement() + { + string json = UT_ProtocolSettings.CreateHKSettings("\"HF_Echidna\": 20"); + var file = Path.GetTempFileName(); + File.WriteAllText(file, json); + ProtocolSettings settings = ProtocolSettings.Load(file, false); + File.Delete(file); + + var before = NativeContract.RoleManagement.GetContractState(settings.IsHardforkEnabled, 19); + var after = NativeContract.RoleManagement.GetContractState(settings.IsHardforkEnabled, 20); + + Assert.AreEqual(2, before.Manifest.Abi.Events[0].Parameters.Length); + Assert.AreEqual(1, before.Manifest.Abi.Events.Length); + Assert.AreEqual(4, after.Manifest.Abi.Events[0].Parameters.Length); + Assert.AreEqual(1, after.Manifest.Abi.Events.Length); + } + [TestMethod] public void TestGetContract() { From 37bf0cb81a64661e2939af0f2c7d8f5af0c610af Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Aug 2024 03:42:18 +0800 Subject: [PATCH 09/25] [Neo Core StdLib] Add Base64url (#3453) * add base64url * active in * update placehold hf height * fix hf issue and move methods to proper place. * fix test * use identifymodel instead. --- src/Neo.CLI/config.fs.mainnet.json | 2 +- src/Neo.CLI/config.json | 2 +- src/Neo.CLI/config.mainnet.json | 2 +- src/Neo.CLI/config.testnet.json | 2 +- src/Neo/Neo.csproj | 1 + src/Neo/SmartContract/Native/StdLib.cs | 23 +++++++++++++++++++ .../SmartContract/Native/UT_NativeContract.cs | 2 +- .../SmartContract/Native/UT_StdLib.cs | 20 ++++++++++++++++ 8 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/Neo.CLI/config.fs.mainnet.json b/src/Neo.CLI/config.fs.mainnet.json index c12372b43b..bbd17978e3 100644 --- a/src/Neo.CLI/config.fs.mainnet.json +++ b/src/Neo.CLI/config.fs.mainnet.json @@ -41,7 +41,7 @@ "HF_Basilisk": 4500000, "HF_Cockatrice": 5800000, "HF_Domovoi": 5800000, - "HF_Echidna": 0 + "HF_Echidna": 5800001 }, "StandbyCommittee": [ "026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086", diff --git a/src/Neo.CLI/config.json b/src/Neo.CLI/config.json index 9e97ec1f00..9590fc60fd 100644 --- a/src/Neo.CLI/config.json +++ b/src/Neo.CLI/config.json @@ -39,7 +39,7 @@ "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, "HF_Domovoi": 5570000, - "HF_Echidna": 0 + "HF_Echidna": 5570001 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.mainnet.json b/src/Neo.CLI/config.mainnet.json index 9e97ec1f00..9590fc60fd 100644 --- a/src/Neo.CLI/config.mainnet.json +++ b/src/Neo.CLI/config.mainnet.json @@ -39,7 +39,7 @@ "HF_Basilisk": 4120000, "HF_Cockatrice": 5450000, "HF_Domovoi": 5570000, - "HF_Echidna": 0 + "HF_Echidna": 5570001 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo.CLI/config.testnet.json b/src/Neo.CLI/config.testnet.json index 88a04794f0..8bcd6d8956 100644 --- a/src/Neo.CLI/config.testnet.json +++ b/src/Neo.CLI/config.testnet.json @@ -39,7 +39,7 @@ "HF_Basilisk": 2680000, "HF_Cockatrice": 3967000, "HF_Domovoi": 4144000, - "HF_Echidna": 0 + "HF_Echidna": 4144001 }, "InitialGasDistribution": 5200000000000000, "ValidatorsCount": 7, diff --git a/src/Neo/Neo.csproj b/src/Neo/Neo.csproj index 89c200e31b..25d80ba91f 100644 --- a/src/Neo/Neo.csproj +++ b/src/Neo/Neo.csproj @@ -16,6 +16,7 @@ + diff --git a/src/Neo/SmartContract/Native/StdLib.cs b/src/Neo/SmartContract/Native/StdLib.cs index f8fa9efcc2..1b4030d9f5 100644 --- a/src/Neo/SmartContract/Native/StdLib.cs +++ b/src/Neo/SmartContract/Native/StdLib.cs @@ -11,6 +11,7 @@ #pragma warning disable IDE0051 +using Microsoft.IdentityModel.Tokens; using Neo.Cryptography; using Neo.Json; using Neo.VM.Types; @@ -131,6 +132,28 @@ public static byte[] Base64Decode([MaxLength(MaxInputLength)] string s) return Convert.FromBase64String(s); } + /// + /// Encodes a byte array into a base64Url string. + /// + /// The base64Url to be encoded. + /// The encoded base64Url string. + [ContractMethod(Hardfork.HF_Echidna, CpuFee = 1 << 5)] + public static string Base64UrlEncode([MaxLength(MaxInputLength)] string data) + { + return Base64UrlEncoder.Encode(data); + } + + /// + /// Decodes a byte array from a base64Url string. + /// + /// The base64Url string. + /// The decoded base64Url string. + [ContractMethod(Hardfork.HF_Echidna, CpuFee = 1 << 5)] + public static string Base64UrlDecode([MaxLength(MaxInputLength)] string s) + { + return Base64UrlEncoder.Decode(s); + } + /// /// Encodes a byte array into a base58 . /// diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index 627a9fdd3c..26e00a3c2d 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -41,7 +41,7 @@ public void TestSetup() _nativeStates = new Dictionary { {"ContractManagement", """{"id":-1,"updatecounter":0,"hash":"0xfffdc93764dbaddd97c48f252a53ea4643faa3fd","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"ContractManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Array","offset":0,"safe":false},{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Array","offset":7,"safe":false},{"name":"destroy","parameters":[],"returntype":"Void","offset":14,"safe":false},{"name":"getContract","parameters":[{"name":"hash","type":"Hash160"}],"returntype":"Array","offset":21,"safe":true},{"name":"getContractById","parameters":[{"name":"id","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getContractHashes","parameters":[],"returntype":"InteropInterface","offset":35,"safe":true},{"name":"getMinimumDeploymentFee","parameters":[],"returntype":"Integer","offset":42,"safe":true},{"name":"hasMethod","parameters":[{"name":"hash","type":"Hash160"},{"name":"method","type":"String"},{"name":"pcount","type":"Integer"}],"returntype":"Boolean","offset":49,"safe":true},{"name":"setMinimumDeploymentFee","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":56,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Void","offset":63,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","offset":70,"safe":false}],"events":[{"name":"Deploy","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Update","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Destroy","parameters":[{"name":"Hash","type":"Hash160"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}""" }, - {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1991619121},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":56,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":63,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":70,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":77,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":84,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":91,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":98,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":112,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":119,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":126,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":133,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":140,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, + {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2681632925},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":77,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":84,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":91,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":98,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":112,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":126,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":133,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":140,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":147,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":154,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"CryptoLib", """{"id":-3,"updatecounter":0,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"bls12381Add","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","offset":0,"safe":true},{"name":"bls12381Deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","offset":7,"safe":true},{"name":"bls12381Equal","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","offset":14,"safe":true},{"name":"bls12381Mul","parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"bls12381Pairing","parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","offset":28,"safe":true},{"name":"bls12381Serialize","parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","offset":35,"safe":true},{"name":"keccak256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"murmur32","parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","offset":49,"safe":true},{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":63,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","offset":70,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"LedgerContract", """{"id":-4,"updatecounter":0,"hash":"0xda65b600f7124ce6c79950c1772a36403104f2be","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"LedgerContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"currentHash","parameters":[],"returntype":"Hash256","offset":0,"safe":true},{"name":"currentIndex","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlock","parameters":[{"name":"indexOrHash","type":"ByteArray"}],"returntype":"Array","offset":14,"safe":true},{"name":"getTransaction","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":21,"safe":true},{"name":"getTransactionFromBlock","parameters":[{"name":"blockIndexOrHash","type":"ByteArray"},{"name":"txIndex","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getTransactionHeight","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":35,"safe":true},{"name":"getTransactionSigners","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":42,"safe":true},{"name":"getTransactionVMState","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":49,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1325686241},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":77,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":84,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":98,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":105,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":112,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":126,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs index 1dffb3d384..f9761bee07 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_StdLib.cs @@ -406,5 +406,25 @@ public void TestRuntime_Deserialize() Assert.AreEqual(engine.ResultStack.Pop().GetInteger(), 100); Assert.AreEqual(engine.ResultStack.Pop().GetString(), "test"); } + + [TestMethod] + public void TestBase64Url() + { + var snapshotCache = TestBlockchain.GetTestSnapshotCache(); + using (var script = new ScriptBuilder()) + { + // Test encoding + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base64UrlEncode", "Subject=test@example.com&Issuer=https://example.com"); + script.EmitDynamicCall(NativeContract.StdLib.Hash, "base64UrlDecode", "U3ViamVjdD10ZXN0QGV4YW1wbGUuY29tJklzc3Vlcj1odHRwczovL2V4YW1wbGUuY29t"); + + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache, settings: TestBlockchain.TheNeoSystem.Settings); + engine.LoadScript(script.ToArray()); + + Assert.AreEqual(engine.Execute(), VMState.HALT); + Assert.AreEqual(2, engine.ResultStack.Count); + Assert.AreEqual("Subject=test@example.com&Issuer=https://example.com", engine.ResultStack.Pop()); + Assert.AreEqual("U3ViamVjdD10ZXN0QGV4YW1wbGUuY29tJklzc3Vlcj1odHRwczovL2V4YW1wbGUuY29t", engine.ResultStack.Pop().GetString()); + } + } } } From 7dba1303c9b3d7b7f8b6a470e7d185d8d0903302 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Wed, 6 Nov 2024 12:42:42 +0800 Subject: [PATCH 10/25] format --- src/Neo/SmartContract/Native/RoleManagement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/SmartContract/Native/RoleManagement.cs b/src/Neo/SmartContract/Native/RoleManagement.cs index ecedba4c86..084d6fdd36 100644 --- a/src/Neo/SmartContract/Native/RoleManagement.cs +++ b/src/Neo/SmartContract/Native/RoleManagement.cs @@ -78,7 +78,7 @@ private void DesignateAsRole(ApplicationEngine engine, Role role, ECPoint[] node list.AddRange(nodes); list.Sort(); engine.SnapshotCache.Add(key, new StorageItem(list)); - + if (engine.IsHardforkEnabled(Hardfork.HF_Echidna)) { var oldNodes = new VM.Types.Array(engine.ReferenceCounter, GetDesignatedByRole(engine.Snapshot, role, index - 1).Select(u => (ByteString)u.EncodePoint(true))); From 6e780c049b441f2b4ddf5e4e5975f9500b4a2101 Mon Sep 17 00:00:00 2001 From: Christopher Schuchardt Date: Sun, 17 Nov 2024 07:44:14 -0500 Subject: [PATCH 11/25] Fixed typo --- tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index 26e00a3c2d..240e202d9b 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -83,7 +83,7 @@ public void TestActiveDeprecatedIn() [TestMethod] public void TestActiveDeprecatedInRoleManagement() { - string json = UT_ProtocolSettings.CreateHKSettings("\"HF_Echidna\": 20"); + string json = UT_ProtocolSettings.CreateHFSettings("\"HF_Echidna\": 20"); var file = Path.GetTempFileName(); File.WriteAllText(file, json); ProtocolSettings settings = ProtocolSettings.Load(file, false); From 02d6ab9e30354863207cf14018946963adc39d27 Mon Sep 17 00:00:00 2001 From: Christopher Schuchardt Date: Sun, 17 Nov 2024 09:12:56 -0500 Subject: [PATCH 12/25] Added back #3397 --- .../SmartContract/Native/RoleManagement.cs | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/Native/RoleManagement.cs b/src/Neo/SmartContract/Native/RoleManagement.cs index e57f3f3e83..2577300720 100644 --- a/src/Neo/SmartContract/Native/RoleManagement.cs +++ b/src/Neo/SmartContract/Native/RoleManagement.cs @@ -26,7 +26,16 @@ public sealed class RoleManagement : NativeContract { [ContractEvent(0, name: "Designation", "Role", ContractParameterType.Integer, - "BlockIndex", ContractParameterType.Integer)] + "BlockIndex", ContractParameterType.Integer, + Hardfork.HF_Echidna)] + + [ContractEvent(Hardfork.HF_Echidna, 0, name: "Designation", + "Role", ContractParameterType.Integer, + "BlockIndex", ContractParameterType.Integer, + "Old", ContractParameterType.Array, + "New", ContractParameterType.Array + )] + internal RoleManagement() : base() { } /// @@ -51,6 +60,7 @@ public ECPoint[] GetDesignatedByRole(DataCache snapshot, Role role, uint index) } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] + [Obsolete] private void DesignateAsRole(ApplicationEngine engine, Role role, ECPoint[] nodes) { if (nodes.Length == 0 || nodes.Length > 32) @@ -69,7 +79,17 @@ private void DesignateAsRole(ApplicationEngine engine, Role role, ECPoint[] node list.AddRange(nodes); list.Sort(); engine.SnapshotCache.Add(key, new StorageItem(list)); - engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, new StackItem[] { (int)role, engine.PersistingBlock.Index })); + if (engine.IsHardforkEnabled(Hardfork.HF_Echidna)) + { + var oldNodes = new VM.Types.Array(engine.ReferenceCounter, GetDesignatedByRole(engine.Snapshot, role, index - 1).Select(u => (ByteString)u.EncodePoint(true))); + var newNodes = new VM.Types.Array(engine.ReferenceCounter, nodes.Select(u => (ByteString)u.EncodePoint(true))); + + engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, [(int)role, engine.PersistingBlock.Index, oldNodes, newNodes])); + } + else + { + engine.SendNotification(Hash, "Designation", new VM.Types.Array(engine.ReferenceCounter, [(int)role, engine.PersistingBlock.Index])); + } } private class NodeList : InteroperableList From 8fb30df9dd7a129a68eef69db7d879cbbdade91f Mon Sep 17 00:00:00 2001 From: Christopher Schuchardt Date: Sun, 17 Nov 2024 09:25:12 -0500 Subject: [PATCH 13/25] Fixed tests --- global.json | 2 +- tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/global.json b/global.json index beefe210a1..41c9ad2ed8 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.202", + "version": "9.0.100", "rollForward": "latestFeature", "allowPrerelease": false } diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index 240e202d9b..5de9448013 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -41,13 +41,13 @@ public void TestSetup() _nativeStates = new Dictionary { {"ContractManagement", """{"id":-1,"updatecounter":0,"hash":"0xfffdc93764dbaddd97c48f252a53ea4643faa3fd","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"ContractManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Array","offset":0,"safe":false},{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Array","offset":7,"safe":false},{"name":"destroy","parameters":[],"returntype":"Void","offset":14,"safe":false},{"name":"getContract","parameters":[{"name":"hash","type":"Hash160"}],"returntype":"Array","offset":21,"safe":true},{"name":"getContractById","parameters":[{"name":"id","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getContractHashes","parameters":[],"returntype":"InteropInterface","offset":35,"safe":true},{"name":"getMinimumDeploymentFee","parameters":[],"returntype":"Integer","offset":42,"safe":true},{"name":"hasMethod","parameters":[{"name":"hash","type":"Hash160"},{"name":"method","type":"String"},{"name":"pcount","type":"Integer"}],"returntype":"Boolean","offset":49,"safe":true},{"name":"setMinimumDeploymentFee","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":56,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Void","offset":63,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","offset":70,"safe":false}],"events":[{"name":"Deploy","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Update","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Destroy","parameters":[{"name":"Hash","type":"Hash160"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}""" }, - {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2681632925},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":77,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":84,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":91,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":98,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":112,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":126,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":133,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":140,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":147,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":154,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, + {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2681632925},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"String","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"String"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":77,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":84,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":91,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":98,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":112,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":126,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":133,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":140,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":147,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":154,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"CryptoLib", """{"id":-3,"updatecounter":0,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"bls12381Add","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","offset":0,"safe":true},{"name":"bls12381Deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","offset":7,"safe":true},{"name":"bls12381Equal","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","offset":14,"safe":true},{"name":"bls12381Mul","parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"bls12381Pairing","parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","offset":28,"safe":true},{"name":"bls12381Serialize","parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","offset":35,"safe":true},{"name":"keccak256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"murmur32","parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","offset":49,"safe":true},{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":63,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","offset":70,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"LedgerContract", """{"id":-4,"updatecounter":0,"hash":"0xda65b600f7124ce6c79950c1772a36403104f2be","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"LedgerContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"currentHash","parameters":[],"returntype":"Hash256","offset":0,"safe":true},{"name":"currentIndex","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlock","parameters":[{"name":"indexOrHash","type":"ByteArray"}],"returntype":"Array","offset":14,"safe":true},{"name":"getTransaction","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":21,"safe":true},{"name":"getTransactionFromBlock","parameters":[{"name":"blockIndexOrHash","type":"ByteArray"},{"name":"txIndex","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getTransactionHeight","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":35,"safe":true},{"name":"getTransactionSigners","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":42,"safe":true},{"name":"getTransactionVMState","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":49,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1325686241},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":77,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":84,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":98,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":105,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":112,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":126,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"GasToken", """{"id":-6,"updatecounter":0,"hash":"0xd2a4cff31913016155e38e474a2c06d08be276cf","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"GasToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"symbol","parameters":[],"returntype":"String","offset":14,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":28,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"PolicyContract", """{"id":-7,"updatecounter":0,"hash":"0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"PolicyContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"blockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":0,"safe":false},{"name":"getAttributeFee","parameters":[{"name":"attributeType","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"getExecFeeFactor","parameters":[],"returntype":"Integer","offset":14,"safe":true},{"name":"getFeePerByte","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"getStoragePrice","parameters":[],"returntype":"Integer","offset":28,"safe":true},{"name":"isBlocked","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":35,"safe":true},{"name":"setAttributeFee","parameters":[{"name":"attributeType","type":"Integer"},{"name":"value","type":"Integer"}],"returntype":"Void","offset":42,"safe":false},{"name":"setExecFeeFactor","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":49,"safe":false},{"name":"setFeePerByte","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":56,"safe":false},{"name":"setStoragePrice","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":63,"safe":false},{"name":"unblockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":70,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, - {"RoleManagement", """{"id":-8,"updatecounter":0,"hash":"0x49cf4e5378ffcd4dec034fd98a174c5491e395e2","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0A=","checksum":983638438},"manifest":{"name":"RoleManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"designateAsRole","parameters":[{"name":"role","type":"Integer"},{"name":"nodes","type":"Array"}],"returntype":"Void","offset":0,"safe":false},{"name":"getDesignatedByRole","parameters":[{"name":"role","type":"Integer"},{"name":"index","type":"Integer"}],"returntype":"Array","offset":7,"safe":true}],"events":[{"name":"Designation","parameters":[{"name":"Role","type":"Integer"},{"name":"BlockIndex","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, + {"RoleManagement", """{"id":-8,"updatecounter":0,"hash":"0x49cf4e5378ffcd4dec034fd98a174c5491e395e2","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0A=","checksum":983638438},"manifest":{"name":"RoleManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"designateAsRole","parameters":[{"name":"role","type":"Integer"},{"name":"nodes","type":"Array"}],"returntype":"Void","offset":0,"safe":false},{"name":"getDesignatedByRole","parameters":[{"name":"role","type":"Integer"},{"name":"index","type":"Integer"}],"returntype":"Array","offset":7,"safe":true}],"events":[{"name":"Designation","parameters":[{"name":"Role","type":"Integer"},{"name":"BlockIndex","type":"Integer"},{"name":"Old","type":"Array"},{"name":"New","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"OracleContract", """{"id":-9,"updatecounter":0,"hash":"0xfe924b7cfe89ddd271abaf7210a80a7e11178758","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"OracleContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"finish","parameters":[],"returntype":"Void","offset":0,"safe":false},{"name":"getPrice","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"request","parameters":[{"name":"url","type":"String"},{"name":"filter","type":"String"},{"name":"callback","type":"String"},{"name":"userData","type":"Any"},{"name":"gasForResponse","type":"Integer"}],"returntype":"Void","offset":14,"safe":false},{"name":"setPrice","parameters":[{"name":"price","type":"Integer"}],"returntype":"Void","offset":21,"safe":false},{"name":"verify","parameters":[],"returntype":"Boolean","offset":28,"safe":true}],"events":[{"name":"OracleRequest","parameters":[{"name":"Id","type":"Integer"},{"name":"RequestContract","type":"Hash160"},{"name":"Url","type":"String"},{"name":"Filter","type":"String"}]},{"name":"OracleResponse","parameters":[{"name":"Id","type":"Integer"},{"name":"OriginalTx","type":"Hash256"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, }; } From f9244ebb9fab915b05dee5414cbfb1c4bf9097e0 Mon Sep 17 00:00:00 2001 From: Christopher Schuchardt Date: Sun, 17 Nov 2024 09:26:53 -0500 Subject: [PATCH 14/25] fixed global.json --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 41c9ad2ed8..beefe210a1 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100", + "version": "8.0.202", "rollForward": "latestFeature", "allowPrerelease": false } From 1c82ed97a20cf39096dd438ce236ae8f0bc0c24c Mon Sep 17 00:00:00 2001 From: Christopher Schuchardt Date: Wed, 4 Dec 2024 02:58:39 -0500 Subject: [PATCH 15/25] Update src/Neo/Neo.csproj --- src/Neo/Neo.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Neo/Neo.csproj b/src/Neo/Neo.csproj index 6b2d325782..34dbfc2c21 100644 --- a/src/Neo/Neo.csproj +++ b/src/Neo/Neo.csproj @@ -12,12 +12,12 @@ - - - - - - + + + + + + From b81b127fcccd85748232b63d3cacdc9ad2e1bd5f Mon Sep 17 00:00:00 2001 From: Christopher Schuchardt Date: Wed, 4 Dec 2024 03:01:00 -0500 Subject: [PATCH 16/25] Update src/Neo/Neo.csproj --- src/Neo/Neo.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/Neo.csproj b/src/Neo/Neo.csproj index 34dbfc2c21..49dba91020 100644 --- a/src/Neo/Neo.csproj +++ b/src/Neo/Neo.csproj @@ -16,7 +16,7 @@ - + From f91b6800c32bc45eb7a25bc61340236597a4bf64 Mon Sep 17 00:00:00 2001 From: nan01ab Date: Thu, 19 Dec 2024 15:36:27 +0800 Subject: [PATCH 17/25] [`Fix`]: integer overflow in `JumpTable.SubStr ` (#3496) * fix: int overflow in SubStr * fix: int overflow in SubStr * format * Versioning change * Clean * Rename * Show change * Space * remove duplicated lines in gitignroe --------- Co-authored-by: Jimmy Co-authored-by: Shargon --- src/Neo.VM/JumpTable/JumpTable.Splice.cs | 2 +- src/Neo/SmartContract/ApplicationEngine.cs | 39 +++++++++++++++- .../Tests/OpCodes/Splice/SUBSTR.json | 44 +++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/Neo.VM/JumpTable/JumpTable.Splice.cs b/src/Neo.VM/JumpTable/JumpTable.Splice.cs index 7192872d81..0a56099b2f 100644 --- a/src/Neo.VM/JumpTable/JumpTable.Splice.cs +++ b/src/Neo.VM/JumpTable/JumpTable.Splice.cs @@ -101,7 +101,7 @@ public virtual void SubStr(ExecutionEngine engine, Instruction instruction) if (index < 0) throw new InvalidOperationException($"The index can not be negative for {nameof(OpCode.SUBSTR)}, index: {index}."); var x = engine.Pop().GetSpan(); - if (index + count > x.Length) + if (checked(index + count) > x.Length) throw new InvalidOperationException($"The index + count is out of range for {nameof(OpCode.SUBSTR)}, index: {index}, count: {count}, {index + count}/[0, {x.Length}]."); Types.Buffer result = new(count, false); x.Slice(index, count).CopyTo(result.InnerBuffer.Span); diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index f8f2332b4e..5ffb914607 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -35,6 +35,7 @@ namespace Neo.SmartContract public partial class ApplicationEngine : ExecutionEngine { protected static readonly JumpTable DefaultJumpTable = ComposeDefaultJumpTable(); + protected static readonly JumpTable NotEchidnaJumpTable = ComposeNotEchidnaJumpTable(); /// /// The maximum cost that can be spent when a contract is executed in test mode. @@ -215,6 +216,13 @@ private static JumpTable ComposeDefaultJumpTable() return table; } + public static JumpTable ComposeNotEchidnaJumpTable() + { + var jumpTable = ComposeDefaultJumpTable(); + jumpTable[OpCode.SUBSTR] = VulnerableSubStr; + return jumpTable; + } + protected static void OnCallT(ExecutionEngine engine, Instruction instruction) { if (engine is ApplicationEngine app) @@ -400,13 +408,42 @@ internal override void UnloadContext(ExecutionContext context) /// The engine instance created. public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) { + var index = persistingBlock?.Index ?? NativeContract.Ledger.CurrentIndex(snapshot); + // Adjust jump table according persistingBlock - var jumpTable = ApplicationEngine.DefaultJumpTable; + + var jumpTable = settings.IsHardforkEnabled(Hardfork.HF_Echidna, index) ? DefaultJumpTable : NotEchidnaJumpTable; return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable); } + /// + /// Extracts a substring from the specified buffer and pushes it onto the evaluation stack. + /// + /// + /// The execution engine. + /// The instruction being executed. + /// Pop 3, Push 1 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void VulnerableSubStr(ExecutionEngine engine, Instruction instruction) + { + var count = (int)engine.Pop().GetInteger(); + if (count < 0) + throw new InvalidOperationException($"The count can not be negative for {nameof(OpCode.SUBSTR)}, count: {count}."); + var index = (int)engine.Pop().GetInteger(); + if (index < 0) + throw new InvalidOperationException($"The index can not be negative for {nameof(OpCode.SUBSTR)}, index: {index}."); + var x = engine.Pop().GetSpan(); + // Note: here it's the main change + if (index + count > x.Length) + throw new InvalidOperationException($"The index + count is out of range for {nameof(OpCode.SUBSTR)}, index: {index}, count: {count}, {index + count}/[0, {x.Length}]."); + + VM.Types.Buffer result = new(count, false); + x.Slice(index, count).CopyTo(result.InnerBuffer.Span); + engine.Push(result); + } + public override void LoadContext(ExecutionContext context) { // Set default execution context state diff --git a/tests/Neo.VM.Tests/Tests/OpCodes/Splice/SUBSTR.json b/tests/Neo.VM.Tests/Tests/OpCodes/Splice/SUBSTR.json index 7b78d7e053..13bf8b9b59 100644 --- a/tests/Neo.VM.Tests/Tests/OpCodes/Splice/SUBSTR.json +++ b/tests/Neo.VM.Tests/Tests/OpCodes/Splice/SUBSTR.json @@ -473,6 +473,50 @@ } } ] + }, + { + "name": "Count Exceed Range Test", + "script": [ + "PUSHDATA1", + "0x0a", + "0x00010203040506070809", + "PUSH2", + "PUSHINT32", + "0x7FFFFFFF", + "SUBSTR" + ], + "steps": [ + { + "actions": [ + "execute" + ], + "result": { + "state": "FAULT" + } + } + ] + }, + { + "name": "Index Exceed Range Test", + "script": [ + "PUSHDATA1", + "0x0a", + "0x00010203040506070809", + "PUSHINT32", + "0x7FFFFFFF", + "PUSH2", + "SUBSTR" + ], + "steps": [ + { + "actions": [ + "execute" + ], + "result": { + "state": "FAULT" + } + } + ] } ] } From 705f4bb8cb0708dd6458608c8648a06c4051df8c Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 19 Dec 2024 08:37:19 +0100 Subject: [PATCH 18/25] Fix NEO callstates (#3599) * Allow callstates to use HF * Rename to method * Other rename * Change the way * Reduce changes * Reduce changes * Adapt name always * Avoid string when only is lower the first char * UT * Test all * Update src/Neo/ProtocolSettings.cs Co-authored-by: Christopher Schuchardt * Update src/Neo/ProtocolSettings.cs Co-authored-by: Christopher Schuchardt * Reuse Load from stream * Unify * Fix default logic * Change ContractMethod to allowMultiple * Use LowerInvariant * Move CheckingHardfork * Remove optional arg * Fix build * Avoid file not found error --------- Co-authored-by: Christopher Schuchardt --- src/Neo/ProtocolSettings.cs | 29 +++++++++--- .../Native/ContractMethodAttribute.cs | 3 +- .../Native/ContractMethodMetadata.cs | 3 +- src/Neo/SmartContract/Native/CryptoLib.cs | 2 +- .../SmartContract/Native/LedgerContract.cs | 2 +- .../SmartContract/Native/NativeContract.cs | 25 +++++++---- src/Neo/SmartContract/Native/NeoToken.cs | 9 ++-- .../SmartContract/Native/UT_NativeContract.cs | 6 +-- .../SmartContract/Native/UT_NeoToken.cs | 45 +++++++++++++++++++ tests/Neo.UnitTests/UT_ProtocolSettings.cs | 10 ++--- 10 files changed, 103 insertions(+), 31 deletions(-) diff --git a/src/Neo/ProtocolSettings.cs b/src/Neo/ProtocolSettings.cs index 19011dc24c..cef7ef6de1 100644 --- a/src/Neo/ProtocolSettings.cs +++ b/src/Neo/ProtocolSettings.cs @@ -15,6 +15,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.IO; using System.Linq; namespace Neo @@ -123,19 +124,32 @@ public record ProtocolSettings public static ProtocolSettings Custom { get; set; } + /// + /// Loads the from the specified stream. + /// + /// The stream of the settings. + /// The loaded . + public static ProtocolSettings Load(Stream stream) + { + var config = new ConfigurationBuilder().AddJsonStream(stream).Build(); + var section = config.GetSection("ProtocolConfiguration"); + return Load(section); + } + /// /// Loads the at the specified path. /// /// The path of the settings file. - /// Indicates whether the file is optional. /// The loaded . - public static ProtocolSettings Load(string path, bool optional = true) + public static ProtocolSettings Load(string path) { - IConfigurationRoot config = new ConfigurationBuilder().AddJsonFile(path, optional).Build(); - IConfigurationSection section = config.GetSection("ProtocolConfiguration"); - var settings = Load(section); - CheckingHardfork(settings); - return settings; + if (!File.Exists(path)) + { + return Default; + } + + using var stream = File.OpenRead(path); + return Load(stream); } /// @@ -165,6 +179,7 @@ public static ProtocolSettings Load(IConfigurationSection section) ? EnsureOmmitedHardforks(section.GetSection("Hardforks").GetChildren().ToDictionary(p => Enum.Parse(p.Key, true), p => uint.Parse(p.Value))).ToImmutableDictionary() : Default.Hardforks }; + CheckingHardfork(Custom); return Custom; } diff --git a/src/Neo/SmartContract/Native/ContractMethodAttribute.cs b/src/Neo/SmartContract/Native/ContractMethodAttribute.cs index 38bc065533..c13329a206 100644 --- a/src/Neo/SmartContract/Native/ContractMethodAttribute.cs +++ b/src/Neo/SmartContract/Native/ContractMethodAttribute.cs @@ -15,7 +15,8 @@ namespace Neo.SmartContract.Native { [DebuggerDisplay("{Name}")] - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false)] + // We allow multiple attributes because the fees or requiredCallFlags may change between hard forks. + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] internal class ContractMethodAttribute : Attribute, IHardforkActivable { public string Name { get; init; } diff --git a/src/Neo/SmartContract/Native/ContractMethodMetadata.cs b/src/Neo/SmartContract/Native/ContractMethodMetadata.cs index fd5a02be6a..58b67fbf01 100644 --- a/src/Neo/SmartContract/Native/ContractMethodMetadata.cs +++ b/src/Neo/SmartContract/Native/ContractMethodMetadata.cs @@ -40,7 +40,8 @@ internal class ContractMethodMetadata : IHardforkActivable public ContractMethodMetadata(MemberInfo member, ContractMethodAttribute attribute) { - Name = attribute.Name ?? member.Name.ToLower()[0] + member.Name[1..]; + Name = attribute.Name ?? member.Name; + Name = Name.ToLowerInvariant()[0] + Name[1..]; Handler = member switch { MethodInfo m => m, diff --git a/src/Neo/SmartContract/Native/CryptoLib.cs b/src/Neo/SmartContract/Native/CryptoLib.cs index 9027298752..9ee46d9490 100644 --- a/src/Neo/SmartContract/Native/CryptoLib.cs +++ b/src/Neo/SmartContract/Native/CryptoLib.cs @@ -100,7 +100,7 @@ public static bool VerifyWithECDsa(byte[] message, byte[] pubkey, byte[] signatu } // This is for solving the hardfork issue in https://github.com/neo-project/neo/pull/3209 - [ContractMethod(true, Hardfork.HF_Cockatrice, CpuFee = 1 << 15, Name = "verifyWithECDsa")] + [ContractMethod(true, Hardfork.HF_Cockatrice, CpuFee = 1 << 15, Name = nameof(VerifyWithECDsa))] public static bool VerifyWithECDsaV0(byte[] message, byte[] pubkey, byte[] signature, NamedCurveHash curve) { if (curve != NamedCurveHash.secp256k1SHA256 && curve != NamedCurveHash.secp256r1SHA256) diff --git a/src/Neo/SmartContract/Native/LedgerContract.cs b/src/Neo/SmartContract/Native/LedgerContract.cs index ec88701d9c..9cea1564ea 100644 --- a/src/Neo/SmartContract/Native/LedgerContract.cs +++ b/src/Neo/SmartContract/Native/LedgerContract.cs @@ -310,7 +310,7 @@ public Transaction GetTransaction(DataCache snapshot, UInt256 hash) return GetTransactionState(snapshot, hash)?.Transaction; } - [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates, Name = "getTransaction")] + [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates, Name = nameof(GetTransaction))] private Transaction GetTransactionForContract(ApplicationEngine engine, UInt256 hash) { TransactionState state = GetTransactionState(engine.SnapshotCache, hash); diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index 97bb0ab69a..8b355464c9 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -140,11 +140,12 @@ protected NativeContract() // Reflection to get the methods List listMethods = []; - foreach (MemberInfo member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) + foreach (var member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { - ContractMethodAttribute attribute = member.GetCustomAttribute(); - if (attribute is null) continue; - listMethods.Add(new ContractMethodMetadata(member, attribute)); + foreach (var attribute in member.GetCustomAttributes()) + { + listMethods.Add(new ContractMethodMetadata(member, attribute)); + } } _methodDescriptors = listMethods.OrderBy(p => p.Name, StringComparer.Ordinal).ThenBy(p => p.Parameters.Length).ToList().AsReadOnly(); @@ -363,6 +364,13 @@ public static NativeContract GetContract(UInt160 hash) return contract; } + internal Dictionary GetContractMethods(ApplicationEngine engine) + { + var nativeContracts = engine.GetState(() => new NativeContractsCache()); + var currentAllowedMethods = nativeContracts.GetAllowedMethods(this, engine); + return currentAllowedMethods.Methods; + } + internal async void Invoke(ApplicationEngine engine, byte version) { try @@ -370,16 +378,15 @@ internal async void Invoke(ApplicationEngine engine, byte version) if (version != 0) throw new InvalidOperationException($"The native contract of version {version} is not active."); // Get native contracts invocation cache - NativeContractsCache nativeContracts = engine.GetState(() => new NativeContractsCache()); - NativeContractsCache.CacheEntry currentAllowedMethods = nativeContracts.GetAllowedMethods(this, engine); + var currentAllowedMethods = GetContractMethods(engine); // Check if the method is allowed - ExecutionContext context = engine.CurrentContext; - ContractMethodMetadata method = currentAllowedMethods.Methods[context.InstructionPointer]; + var context = engine.CurrentContext; + var method = currentAllowedMethods[context.InstructionPointer]; if (method.ActiveIn is not null && !engine.IsHardforkEnabled(method.ActiveIn.Value)) throw new InvalidOperationException($"Cannot call this method before hardfork {method.ActiveIn}."); if (method.DeprecatedIn is not null && engine.IsHardforkEnabled(method.DeprecatedIn.Value)) throw new InvalidOperationException($"Cannot call this method after hardfork {method.DeprecatedIn}."); - ExecutionContextState state = context.GetState(); + var state = context.GetState(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) throw new InvalidOperationException($"Cannot call this method with the flag {state.CallFlags}."); // In the unit of datoshi, 1 datoshi = 1e-8 GAS diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index f0321897f2..cbc14ebb52 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -332,7 +332,8 @@ public BigInteger UnclaimedGas(DataCache snapshot, UInt160 account, uint end) return CalculateBonus(snapshot, state, end); } - [ContractMethod(RequiredCallFlags = CallFlags.States)] + [ContractMethod(true, Hardfork.HF_Echidna, RequiredCallFlags = CallFlags.States)] + [ContractMethod(Hardfork.HF_Echidna, /* */ RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) @@ -349,7 +350,8 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) return true; } - [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] + [ContractMethod(true, Hardfork.HF_Echidna, CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] + [ContractMethod(Hardfork.HF_Echidna, /* */ CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) @@ -366,7 +368,8 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) return true; } - [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] + [ContractMethod(true, Hardfork.HF_Echidna, CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] + [ContractMethod(Hardfork.HF_Echidna, /* */ CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private async ContractTask Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) { if (!engine.CheckWitnessInternal(account)) return false; diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index 471b580cf2..e7e12805a7 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -71,7 +71,7 @@ public void TestActiveDeprecatedIn() string json = UT_ProtocolSettings.CreateHFSettings("\"HF_Cockatrice\": 20"); var file = Path.GetTempFileName(); File.WriteAllText(file, json); - ProtocolSettings settings = ProtocolSettings.Load(file, false); + ProtocolSettings settings = ProtocolSettings.Load(file); File.Delete(file); Assert.IsFalse(NativeContract.IsActive(new active() { ActiveIn = Hardfork.HF_Cockatrice, DeprecatedIn = null }, settings.IsHardforkEnabled, 1)); @@ -87,7 +87,7 @@ public void TestActiveDeprecatedInRoleManagement() string json = UT_ProtocolSettings.CreateHFSettings("\"HF_Echidna\": 20"); var file = Path.GetTempFileName(); File.WriteAllText(file, json); - ProtocolSettings settings = ProtocolSettings.Load(file, false); + ProtocolSettings settings = ProtocolSettings.Load(file); File.Delete(file); var before = NativeContract.RoleManagement.GetContractState(settings.IsHardforkEnabled, 19); @@ -112,7 +112,7 @@ public void TestIsInitializeBlock() var file = Path.GetTempFileName(); File.WriteAllText(file, json); - ProtocolSettings settings = ProtocolSettings.Load(file, false); + ProtocolSettings settings = ProtocolSettings.Load(file); File.Delete(file); Assert.IsTrue(NativeContract.CryptoLib.IsInitializeBlock(settings, 0, out var hf)); diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs index 2ff07d5a69..c5f889a252 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs @@ -22,8 +22,11 @@ using Neo.VM; using Neo.Wallets; using System; +using System.IO; using System.Linq; using System.Numerics; +using System.Security.Principal; +using System.Text; using static Neo.SmartContract.Native.NeoToken; namespace Neo.UnitTests.SmartContract.Native @@ -54,6 +57,48 @@ public void TestSetup() [TestMethod] public void Check_Decimals() => NativeContract.NEO.Decimals(_snapshotCache).Should().Be(0); + [TestMethod] + public void Test_HF_EchidnaStates() + { + string json = UT_ProtocolSettings.CreateHFSettings("\"HF_Echidna\": 10"); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)); + var settings = ProtocolSettings.Load(stream); + + var clonedCache = _snapshotCache.CloneCache(); + var persistingBlock = new Block { Header = new Header() }; + + foreach (var method in new string[] { "vote", "registerCandidate", "unregisterCandidate" }) + { + // Test WITHOUT HF_Echidna + + persistingBlock.Header.Index = 9; + + using (var engine = ApplicationEngine.Create(TriggerType.Application, + new Nep17NativeContractExtensions.ManualWitness(UInt160.Zero), clonedCache, persistingBlock, settings: settings)) + { + var methods = NativeContract.NEO.GetContractMethods(engine); + var entries = methods.Values.Where(u => u.Name == method).ToArray(); + + Assert.AreEqual(entries.Length, 1); + Assert.AreEqual(entries[0].RequiredCallFlags, CallFlags.States); + } + + // Test WITH HF_Echidna + + persistingBlock.Header.Index = 10; + + using (var engine = ApplicationEngine.Create(TriggerType.Application, + new Nep17NativeContractExtensions.ManualWitness(UInt160.Zero), clonedCache, persistingBlock, settings: settings)) + { + var methods = NativeContract.NEO.GetContractMethods(engine); + var entries = methods.Values.Where(u => u.Name == method).ToArray(); + + Assert.AreEqual(entries.Length, 1); + Assert.AreEqual(entries[0].RequiredCallFlags, CallFlags.States | CallFlags.AllowNotify); + } + } + } + [TestMethod] public void Check_Vote() { diff --git a/tests/Neo.UnitTests/UT_ProtocolSettings.cs b/tests/Neo.UnitTests/UT_ProtocolSettings.cs index 97a36e5907..757ca5f174 100644 --- a/tests/Neo.UnitTests/UT_ProtocolSettings.cs +++ b/tests/Neo.UnitTests/UT_ProtocolSettings.cs @@ -56,7 +56,7 @@ public void HardForkTestBAndNotA() var file = Path.GetTempFileName(); File.WriteAllText(file, json); - ProtocolSettings settings = ProtocolSettings.Load(file, false); + ProtocolSettings settings = ProtocolSettings.Load(file); File.Delete(file); settings.Hardforks[Hardfork.HF_Aspidochelone].Should().Be(0); @@ -78,7 +78,7 @@ public void HardForkTestAAndNotB() var file = Path.GetTempFileName(); File.WriteAllText(file, json); - ProtocolSettings settings = ProtocolSettings.Load(file, false); + ProtocolSettings settings = ProtocolSettings.Load(file); File.Delete(file); settings.Hardforks[Hardfork.HF_Aspidochelone].Should().Be(0); @@ -100,7 +100,7 @@ public void HardForkTestNone() var file = Path.GetTempFileName(); File.WriteAllText(file, json); - ProtocolSettings settings = ProtocolSettings.Load(file, false); + ProtocolSettings settings = ProtocolSettings.Load(file); File.Delete(file); settings.Hardforks[Hardfork.HF_Aspidochelone].Should().Be(0); @@ -120,7 +120,7 @@ public void HardForkTestAMoreThanB() string json = CreateHFSettings("\"HF_Aspidochelone\": 4120001, \"HF_Basilisk\": 4120000"); var file = Path.GetTempFileName(); File.WriteAllText(file, json); - Assert.ThrowsException(() => ProtocolSettings.Load(file, false)); + Assert.ThrowsException(() => ProtocolSettings.Load(file)); File.Delete(file); } @@ -316,7 +316,7 @@ public void TestTimePerBlockCalculation() [TestMethod] public void TestLoad() { - var loadedSetting = ProtocolSettings.Load("test.config.json", false); + var loadedSetting = ProtocolSettings.Load("test.config.json"); // Comparing all properties TestProtocolSettings.Default.Network.Should().Be(loadedSetting.Network); From 59fe8b5b861b52ec2a002526a419f390d4257d8e Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 19 Dec 2024 20:53:13 +0800 Subject: [PATCH 19/25] fix tests error (#3636) * fux build error * Update src/Neo/SmartContract/ApplicationEngine.cs --------- Co-authored-by: Shargon --- src/Neo/SmartContract/ApplicationEngine.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 5ffb914607..2ca0f62116 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -408,12 +408,11 @@ internal override void UnloadContext(ExecutionContext context) /// The engine instance created. public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) { - var index = persistingBlock?.Index ?? NativeContract.Ledger.CurrentIndex(snapshot); + var index = persistingBlock?.Index ?? (snapshot == null ? 0 : NativeContract.Ledger.CurrentIndex(snapshot)); // Adjust jump table according persistingBlock - var jumpTable = settings.IsHardforkEnabled(Hardfork.HF_Echidna, index) ? DefaultJumpTable : NotEchidnaJumpTable; - + var jumpTable = settings == null || settings.IsHardforkEnabled(Hardfork.HF_Echidna, index) ? DefaultJumpTable : NotEchidnaJumpTable; return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic, jumpTable); } From a784c41d157cdb6dae6679b0cd46b883afdf632d Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 20 Dec 2024 06:58:30 +0300 Subject: [PATCH 20/25] NeoToken: accept candidate registration via onNEP17Payment (#3597) Solves two problems: * inability to estimate GAS needed for registerCandidate in a regular way because of its very high fee (more than what normal RPC servers allow) * inability to have MaxBlockSystemFee lower than the registration price which is very high on its own (more than practically possible to execute) Fixes #3552. Signed-off-by: Roman Khimov --- src/Neo/SmartContract/Native/NeoToken.cs | 30 ++++++++- .../SmartContract/Native/UT_NativeContract.cs | 2 +- .../SmartContract/Native/UT_NeoToken.cs | 64 +++++++++++++++++++ 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index cbc14ebb52..7e945d8481 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -332,14 +332,42 @@ public BigInteger UnclaimedGas(DataCache snapshot, UInt160 account, uint end) return CalculateBonus(snapshot, state, end); } + [ContractMethod(Hardfork.HF_Echidna, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] + private async ContractTask OnNEP17Payment(ApplicationEngine engine, UInt160 from, BigInteger amount, StackItem data) + { + if (engine.CallingScriptHash != GAS.Hash) + throw new InvalidOperationException("only GAS is accepted"); + + if ((long)amount != GetRegisterPrice(engine.SnapshotCache)) + throw new ArgumentException("incorrect GAS amount for registration"); + + var pubkey = ECPoint.DecodePoint(data.GetSpan(), ECCurve.Secp256r1); + + if (!RegisterInternal(engine, pubkey)) + throw new InvalidOperationException("failed to register candidate"); + + await GAS.Burn(engine, Hash, amount); + } + [ContractMethod(true, Hardfork.HF_Echidna, RequiredCallFlags = CallFlags.States)] [ContractMethod(Hardfork.HF_Echidna, /* */ RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) { - if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) + // This check can be removed post-Echidna if compatible, + // RegisterInternal does this anyway. + var index = engine.PersistingBlock?.Index ?? Ledger.CurrentIndex(engine.SnapshotCache); + if (!engine.ProtocolSettings.IsHardforkEnabled(Hardfork.HF_Echidna, index) && + !engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) return false; // In the unit of datoshi, 1 datoshi = 1e-8 GAS engine.AddFee(GetRegisterPrice(engine.SnapshotCache)); + return RegisterInternal(engine, pubkey); + } + + private bool RegisterInternal(ApplicationEngine engine, ECPoint pubkey) + { + if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) + return false; StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); StorageItem item = engine.SnapshotCache.GetAndChange(key, () => new StorageItem(new CandidateState())); CandidateState state = item.GetInteroperable(); diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index e7e12805a7..d5d179428c 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -45,7 +45,7 @@ public void TestSetup() {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2681632925},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"String","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"String"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":77,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":84,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":91,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":98,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":112,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":126,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":133,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":140,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":147,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":154,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"CryptoLib", """{"id":-3,"updatecounter":0,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"bls12381Add","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","offset":0,"safe":true},{"name":"bls12381Deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","offset":7,"safe":true},{"name":"bls12381Equal","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","offset":14,"safe":true},{"name":"bls12381Mul","parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"bls12381Pairing","parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","offset":28,"safe":true},{"name":"bls12381Serialize","parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","offset":35,"safe":true},{"name":"keccak256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"murmur32","parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","offset":49,"safe":true},{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":63,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","offset":70,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"LedgerContract", """{"id":-4,"updatecounter":0,"hash":"0xda65b600f7124ce6c79950c1772a36403104f2be","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"LedgerContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"currentHash","parameters":[],"returntype":"Hash256","offset":0,"safe":true},{"name":"currentIndex","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlock","parameters":[{"name":"indexOrHash","type":"ByteArray"}],"returntype":"Array","offset":14,"safe":true},{"name":"getTransaction","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":21,"safe":true},{"name":"getTransactionFromBlock","parameters":[{"name":"blockIndexOrHash","type":"ByteArray"},{"name":"txIndex","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getTransactionHeight","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":35,"safe":true},{"name":"getTransactionSigners","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":42,"safe":true},{"name":"getTransactionVMState","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":49,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, - {"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1325686241},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":77,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":84,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":98,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":105,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":112,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":126,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, + {"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1991619121},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","offset":77,"safe":false},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":84,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":98,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":105,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":112,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":119,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":126,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":140,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"GasToken", """{"id":-6,"updatecounter":0,"hash":"0xd2a4cff31913016155e38e474a2c06d08be276cf","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"GasToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"symbol","parameters":[],"returntype":"String","offset":14,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":28,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"PolicyContract", """{"id":-7,"updatecounter":0,"hash":"0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"PolicyContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"blockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":0,"safe":false},{"name":"getAttributeFee","parameters":[{"name":"attributeType","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"getExecFeeFactor","parameters":[],"returntype":"Integer","offset":14,"safe":true},{"name":"getFeePerByte","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"getStoragePrice","parameters":[],"returntype":"Integer","offset":28,"safe":true},{"name":"isBlocked","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":35,"safe":true},{"name":"setAttributeFee","parameters":[{"name":"attributeType","type":"Integer"},{"name":"value","type":"Integer"}],"returntype":"Void","offset":42,"safe":false},{"name":"setExecFeeFactor","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":49,"safe":false},{"name":"setFeePerByte","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":56,"safe":false},{"name":"setStoragePrice","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":63,"safe":false},{"name":"unblockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":70,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"RoleManagement", """{"id":-8,"updatecounter":0,"hash":"0x49cf4e5378ffcd4dec034fd98a174c5491e395e2","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0A=","checksum":983638438},"manifest":{"name":"RoleManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"designateAsRole","parameters":[{"name":"role","type":"Integer"},{"name":"nodes","type":"Array"}],"returntype":"Void","offset":0,"safe":false},{"name":"getDesignatedByRole","parameters":[{"name":"role","type":"Integer"},{"name":"index","type":"Integer"}],"returntype":"Array","offset":7,"safe":true}],"events":[{"name":"Designation","parameters":[{"name":"Role","type":"Integer"},{"name":"BlockIndex","type":"Integer"},{"name":"Old","type":"Array"},{"name":"New","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs index c5f889a252..afafc99d75 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NeoToken.cs @@ -310,6 +310,40 @@ public void Check_RegisterValidator() Assert.AreEqual(2, members.Count()); } + [TestMethod] + public void Check_RegisterValidatorViaNEP27() + { + var clonedCache = _snapshotCache.CloneCache(); + var point = ECPoint.Parse("021821807f923a3da004fb73871509d7635bcc05f41edef2a3ca5c941d8bbc1231", ECCurve.Secp256r1); + var pointData = point.EncodePoint(true); + + // Send some NEO, shouldn't be accepted + var ret = Check_RegisterValidatorViaNEP27(clonedCache, point, _persistingBlock, true, pointData, 1000_0000_0000); + ret.State.Should().BeFalse(); + + // Send improper amount of GAS, shouldn't be accepted. + ret = Check_RegisterValidatorViaNEP27(clonedCache, point, _persistingBlock, false, pointData, 1000_0000_0001); + ret.State.Should().BeFalse(); + + // Broken witness. + var badPoint = ECPoint.Parse("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", ECCurve.Secp256r1); + ret = Check_RegisterValidatorViaNEP27(clonedCache, point, _persistingBlock, false, badPoint.EncodePoint(true), 1000_0000_0000); + ret.State.Should().BeFalse(); + + // Successful case. + ret = Check_RegisterValidatorViaNEP27(clonedCache, point, _persistingBlock, false, pointData, 1000_0000_0000); + ret.State.Should().BeTrue(); + ret.Result.Should().BeTrue(); + + // Check GetRegisteredValidators + var members = NativeContract.NEO.GetCandidatesInternal(clonedCache); + Assert.AreEqual(1, members.Count()); + Assert.AreEqual(point, members.First().PublicKey); + + // No GAS should be left on the NEO account. + Assert.AreEqual(0, NativeContract.GAS.BalanceOf(clonedCache, NativeContract.NEO.Hash)); + } + [TestMethod] public void Check_UnregisterCandidate() { @@ -1099,6 +1133,36 @@ internal static (bool State, bool Result) Check_RegisterValidator(DataCache clon return (true, result.GetBoolean()); } + internal static (bool State, bool Result) Check_RegisterValidatorViaNEP27(DataCache clonedCache, ECPoint pubkey, Block persistingBlock, bool passNEO, byte[] data, BigInteger amount) + { + var keyScriptHash = Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash(); + var contractID = passNEO ? NativeContract.NEO.Id : NativeContract.GAS.Id; + var storageKey = new KeyBuilder(contractID, 20).Add(keyScriptHash); // 20 is Prefix_Account + + if (passNEO) + clonedCache.Add(storageKey, new StorageItem(new NeoAccountState { Balance = amount })); + else + clonedCache.Add(storageKey, new StorageItem(new AccountState { Balance = amount })); + + using var engine = ApplicationEngine.Create(TriggerType.Application, + new Nep17NativeContractExtensions.ManualWitness(keyScriptHash), clonedCache, persistingBlock, settings: TestBlockchain.TheNeoSystem.Settings, gas: 1_0000_0000); + + using var script = new ScriptBuilder(); + script.EmitDynamicCall(passNEO ? NativeContract.NEO.Hash : NativeContract.GAS.Hash, "transfer", keyScriptHash, NativeContract.NEO.Hash, amount, data); + engine.LoadScript(script.ToArray()); + + var execRes = engine.Execute(); + clonedCache.Delete(storageKey); // Clean up for subsequent invocations. + + if (execRes == VMState.FAULT) + return (false, false); + + var result = engine.ResultStack.Pop(); + result.Should().BeOfType(typeof(VM.Types.Boolean)); + + return (true, result.GetBoolean()); + } + internal static ECPoint[] Check_GetCommittee(DataCache clonedCache, Block persistingBlock) { using var engine = ApplicationEngine.Create(TriggerType.Application, null, clonedCache, persistingBlock, settings: TestBlockchain.TheNeoSystem.Settings); From e2acc648ce6acce174ed2af922c2ac6521bfab8f Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 20 Dec 2024 16:34:17 +0800 Subject: [PATCH 21/25] specify the argument exception information. --- src/Neo/SmartContract/Contract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/SmartContract/Contract.cs b/src/Neo/SmartContract/Contract.cs index dc60c42d50..70988a0585 100644 --- a/src/Neo/SmartContract/Contract.cs +++ b/src/Neo/SmartContract/Contract.cs @@ -103,7 +103,7 @@ public static Contract CreateMultiSigContract(int m, IReadOnlyCollection publicKeys) { if (!(1 <= m && m <= publicKeys.Count && publicKeys.Count <= 1024)) - throw new ArgumentException(); + throw new ArgumentException($"Invalid multisig parameters: m={m}, publicKeys.Count={publicKeys.Count}"); using ScriptBuilder sb = new(); sb.EmitPush(m); foreach (ECPoint publicKey in publicKeys.OrderBy(p => p)) From 216c39eddd03de2cb1f6f8aa5b3c19be60606f27 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 20 Dec 2024 02:07:42 -0800 Subject: [PATCH 22/25] Fix Ut (#3635) --- .../UT_ApplicationEngine.Contract.cs | 15 +++++- .../UT_ApplicationEngineProvider.cs | 11 ++-- .../SmartContract/UT_Contract.cs | 17 +++++- .../Neo.UnitTests/SmartContract/UT_Helper.cs | 11 ++-- .../SmartContract/UT_InteropPrices.cs | 48 ++++++++++------- .../SmartContract/UT_InteropService.NEO.cs | 8 +-- .../SmartContract/UT_InteropService.cs | 42 ++++++++------- .../SmartContract/UT_JsonSerializer.cs | 27 +++++++--- .../SmartContract/UT_NotifyEventArgs.cs | 13 ++++- .../SmartContract/UT_Syscalls.cs | 53 +++++++++++-------- tests/Neo.UnitTests/VM/UT_Helper.cs | 22 ++++++-- 11 files changed, 181 insertions(+), 86 deletions(-) diff --git a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.Contract.cs b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.Contract.cs index 2d71b97e25..1e65fe7454 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.Contract.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngine.Contract.cs @@ -12,6 +12,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Extensions; +using Neo.Persistence; using Neo.SmartContract; using Neo.VM; using System.Linq; @@ -20,11 +21,20 @@ namespace Neo.UnitTests.SmartContract { public partial class UT_ApplicationEngine { + private DataCache _snapshotCache; + + [TestInitialize] + public void TestSetup() + { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); + } + [TestMethod] public void TestCreateStandardAccount() { + var snapshot = _snapshotCache.CloneCache(); var settings = TestProtocolSettings.Default; - using var engine = ApplicationEngine.Create(TriggerType.Application, null, null, settings: TestProtocolSettings.Default, gas: 1100_00000000); + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestProtocolSettings.Default, gas: 1100_00000000); using var script = new ScriptBuilder(); script.EmitSysCall(ApplicationEngine.System_Contract_CreateStandardAccount, settings.StandbyCommittee[0].EncodePoint(true)); @@ -39,8 +49,9 @@ public void TestCreateStandardAccount() [TestMethod] public void TestCreateStandardMultisigAccount() { + var snapshot = _snapshotCache.CloneCache(); var settings = TestProtocolSettings.Default; - using var engine = ApplicationEngine.Create(TriggerType.Application, null, null, settings: TestBlockchain.TheNeoSystem.Settings, gas: 1100_00000000); + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings, gas: 1100_00000000); using var script = new ScriptBuilder(); script.EmitSysCall(ApplicationEngine.System_Contract_CreateMultisigAccount, new object[] diff --git a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs index 1d9da111e1..da52e2415d 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_ApplicationEngineProvider.cs @@ -21,9 +21,12 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_ApplicationEngineProvider { + private DataCache _snapshotCache; + [TestInitialize] - public void TestInitialize() + public void TestSetup() { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); ApplicationEngine.Provider = null; } @@ -37,15 +40,17 @@ public void TestCleanup() public void TestSetAppEngineProvider() { ApplicationEngine.Provider = new TestProvider(); + var snapshot = _snapshotCache.CloneCache(); - using var appEngine = ApplicationEngine.Create(TriggerType.Application, null, null, gas: 0, settings: TestBlockchain.TheNeoSystem.Settings); + using var appEngine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, gas: 0, settings: TestBlockchain.TheNeoSystem.Settings); (appEngine is TestEngine).Should().BeTrue(); } [TestMethod] public void TestDefaultAppEngineProvider() { - using var appEngine = ApplicationEngine.Create(TriggerType.Application, null, null, gas: 0, settings: TestBlockchain.TheNeoSystem.Settings); + var snapshot = _snapshotCache.CloneCache(); + using var appEngine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, gas: 0, settings: TestBlockchain.TheNeoSystem.Settings); (appEngine is ApplicationEngine).Should().BeTrue(); } diff --git a/tests/Neo.UnitTests/SmartContract/UT_Contract.cs b/tests/Neo.UnitTests/SmartContract/UT_Contract.cs index ecd8532faa..4971df8ad9 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_Contract.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_Contract.cs @@ -13,6 +13,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Extensions; using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; @@ -26,6 +27,14 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_Contract { + private DataCache _snapshotCache; + + [TestInitialize] + public void TestSetup() + { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); + } + [TestMethod] public void TestGetScriptHash() { @@ -158,6 +167,7 @@ public void TestCreateSignatureRedeemScript() [TestMethod] public void TestSignatureRedeemScriptFee() { + var snapshot = _snapshotCache.CloneCache(); byte[] privateKey = new byte[32]; RandomNumberGenerator rng = RandomNumberGenerator.Create(); rng.GetBytes(privateKey); @@ -167,7 +177,8 @@ public void TestSignatureRedeemScriptFee() var fee = PolicyContract.DefaultExecFeeFactor * (ApplicationEngine.OpCodePriceTable[(byte)OpCode.PUSHDATA1] * 2 + ApplicationEngine.OpCodePriceTable[(byte)OpCode.SYSCALL] + ApplicationEngine.CheckSigPrice); - using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, new Transaction { Signers = Array.Empty(), Attributes = Array.Empty() }, null, settings: TestBlockchain.TheNeoSystem.Settings)) + using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, + new Transaction { Signers = Array.Empty(), Attributes = Array.Empty() }, snapshot, settings: TestBlockchain.TheNeoSystem.Settings)) { engine.LoadScript(invocation.Concat(verification).ToArray(), configureState: p => p.CallFlags = CallFlags.None); engine.Execute(); @@ -178,6 +189,7 @@ public void TestSignatureRedeemScriptFee() [TestMethod] public void TestCreateMultiSigRedeemScriptFee() { + var snapshot = _snapshotCache.CloneCache(); byte[] privateKey1 = new byte[32]; RandomNumberGenerator rng1 = RandomNumberGenerator.Create(); rng1.GetBytes(privateKey1); @@ -195,7 +207,8 @@ public void TestCreateMultiSigRedeemScriptFee() long fee = PolicyContract.DefaultExecFeeFactor * (ApplicationEngine.OpCodePriceTable[(byte)OpCode.PUSHDATA1] * (2 + 2) + ApplicationEngine.OpCodePriceTable[(byte)OpCode.PUSHINT8] * 2 + ApplicationEngine.OpCodePriceTable[(byte)OpCode.SYSCALL] + ApplicationEngine.CheckSigPrice * 2); - using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, new Transaction { Signers = Array.Empty(), Attributes = Array.Empty() }, null, settings: TestBlockchain.TheNeoSystem.Settings)) + using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, + new Transaction { Signers = Array.Empty(), Attributes = Array.Empty() }, snapshot, settings: TestBlockchain.TheNeoSystem.Settings)) { engine.LoadScript(invocation.Concat(verification).ToArray(), configureState: p => p.CallFlags = CallFlags.None); engine.Execute(); diff --git a/tests/Neo.UnitTests/SmartContract/UT_Helper.cs b/tests/Neo.UnitTests/SmartContract/UT_Helper.cs index e629a5908f..fb7d1dd9ba 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_Helper.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_Helper.cs @@ -12,6 +12,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Cryptography.ECC; using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; @@ -27,10 +28,12 @@ namespace Neo.UnitTests.SmartContract public class UT_Helper { private KeyPair _key; + private DataCache _snapshotCache; [TestInitialize] - public void Init() + public void TestSetup() { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); var pk = new byte[32]; new Random().NextBytes(pk); _key = new KeyPair(pk); @@ -118,6 +121,7 @@ public void TestIsSignatureContract_WrongCurve() [TestMethod] public void TestSignatureContractCost() { + var snapshot = _snapshotCache.CloneCache(); var contract = Contract.CreateSignatureContract(_key.PublicKey); var tx = TestUtils.CreateRandomHashTransaction(); @@ -127,7 +131,7 @@ public void TestSignatureContractCost() invocationScript.EmitPush(Neo.Wallets.Helper.Sign(tx, _key, TestProtocolSettings.Default.Network)); tx.Witnesses = new Witness[] { new Witness() { InvocationScript = invocationScript.ToArray(), VerificationScript = contract.Script } }; - using var engine = ApplicationEngine.Create(TriggerType.Verification, tx, null, null, TestProtocolSettings.Default); + using var engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot, null, TestProtocolSettings.Default); engine.LoadScript(contract.Script); engine.LoadScript(new Script(invocationScript.ToArray(), true), configureState: p => p.CallFlags = CallFlags.None); Assert.AreEqual(VMState.HALT, engine.Execute()); @@ -139,6 +143,7 @@ public void TestSignatureContractCost() [TestMethod] public void TestMultiSignatureContractCost() { + var snapshot = _snapshotCache.CloneCache(); var contract = Contract.CreateMultiSigContract(1, new ECPoint[] { _key.PublicKey }); var tx = TestUtils.CreateRandomHashTransaction(); @@ -147,7 +152,7 @@ public void TestMultiSignatureContractCost() using ScriptBuilder invocationScript = new(); invocationScript.EmitPush(Neo.Wallets.Helper.Sign(tx, _key, TestProtocolSettings.Default.Network)); - using var engine = ApplicationEngine.Create(TriggerType.Verification, tx, null, null, TestProtocolSettings.Default); + using var engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot, null, TestProtocolSettings.Default); engine.LoadScript(contract.Script); engine.LoadScript(new Script(invocationScript.ToArray(), true), configureState: p => p.CallFlags = CallFlags.None); Assert.AreEqual(VMState.HALT, engine.Execute()); diff --git a/tests/Neo.UnitTests/SmartContract/UT_InteropPrices.cs b/tests/Neo.UnitTests/SmartContract/UT_InteropPrices.cs index dfc685f335..61ecc6c404 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_InteropPrices.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_InteropPrices.cs @@ -11,6 +11,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Persistence; using Neo.SmartContract; using Neo.UnitTests.Extensions; using Neo.VM; @@ -20,12 +21,21 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_InteropPrices { + private DataCache _snapshotCache; + + [TestInitialize] + public void TestSetup() + { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); + } + [TestMethod] public void ApplicationEngineFixedPrices() { + var snapshot = _snapshotCache.CloneCache(); // System.Runtime.CheckWitness: f827ec8c (price is 200) byte[] SyscallSystemRuntimeCheckWitnessHash = new byte[] { 0x68, 0xf8, 0x27, 0xec, 0x8c }; - using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, null, gas: 0)) + using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshot, gas: 0)) { ae.LoadScript(SyscallSystemRuntimeCheckWitnessHash); ApplicationEngine.System_Runtime_CheckWitness.FixedPrice.Should().Be(0_00001024L); @@ -33,7 +43,7 @@ public void ApplicationEngineFixedPrices() // System.Storage.GetContext: 9bf667ce (price is 1) byte[] SyscallSystemStorageGetContextHash = new byte[] { 0x68, 0x9b, 0xf6, 0x67, 0xce }; - using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, null, gas: 0)) + using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshot, gas: 0)) { ae.LoadScript(SyscallSystemStorageGetContextHash); ApplicationEngine.System_Storage_GetContext.FixedPrice.Should().Be(0_00000016L); @@ -41,7 +51,7 @@ public void ApplicationEngineFixedPrices() // System.Storage.Get: 925de831 (price is 100) byte[] SyscallSystemStorageGetHash = new byte[] { 0x68, 0x92, 0x5d, 0xe8, 0x31 }; - using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, null, gas: 0)) + using (ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshot, gas: 0)) { ae.LoadScript(SyscallSystemStorageGetHash); ApplicationEngine.System_Storage_Get.FixedPrice.Should().Be(32768L); @@ -54,6 +64,7 @@ public void ApplicationEngineFixedPrices() [TestMethod] public void ApplicationEngineRegularPut() { + var snapshot = _snapshotCache.CloneCache(); var key = new byte[] { (byte)OpCode.PUSH1 }; var value = new byte[] { (byte)OpCode.PUSH1 }; @@ -64,11 +75,10 @@ public void ApplicationEngineRegularPut() StorageKey skey = TestUtils.GetStorageKey(contractState.Id, key); StorageItem sItem = TestUtils.GetStorageItem(System.Array.Empty()); - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); - snapshotCache.Add(skey, sItem); - snapshotCache.AddContract(script.ToScriptHash(), contractState); + snapshot.Add(skey, sItem); + snapshot.AddContract(script.ToScriptHash(), contractState); - using ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + using ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshot); Debugger debugger = new(ae); ae.LoadScript(script); debugger.StepInto(); @@ -85,6 +95,7 @@ public void ApplicationEngineRegularPut() [TestMethod] public void ApplicationEngineReusedStorage_FullReuse() { + var snapshot = _snapshotCache.CloneCache(); var key = new byte[] { (byte)OpCode.PUSH1 }; var value = new byte[] { (byte)OpCode.PUSH1 }; @@ -95,11 +106,10 @@ public void ApplicationEngineReusedStorage_FullReuse() StorageKey skey = TestUtils.GetStorageKey(contractState.Id, key); StorageItem sItem = TestUtils.GetStorageItem(value); - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); - snapshotCache.Add(skey, sItem); - snapshotCache.AddContract(script.ToScriptHash(), contractState); + snapshot.Add(skey, sItem); + snapshot.AddContract(script.ToScriptHash(), contractState); - using ApplicationEngine applicationEngine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + using ApplicationEngine applicationEngine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); Debugger debugger = new(applicationEngine); applicationEngine.LoadScript(script); debugger.StepInto(); @@ -117,6 +127,7 @@ public void ApplicationEngineReusedStorage_FullReuse() [TestMethod] public void ApplicationEngineReusedStorage_PartialReuse() { + var snapshot = _snapshotCache.CloneCache(); var key = new byte[] { (byte)OpCode.PUSH1 }; var oldValue = new byte[] { (byte)OpCode.PUSH1 }; var value = new byte[] { (byte)OpCode.PUSH1, (byte)OpCode.PUSH1 }; @@ -128,11 +139,10 @@ public void ApplicationEngineReusedStorage_PartialReuse() StorageKey skey = TestUtils.GetStorageKey(contractState.Id, key); StorageItem sItem = TestUtils.GetStorageItem(oldValue); - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); - snapshotCache.Add(skey, sItem); - snapshotCache.AddContract(script.ToScriptHash(), contractState); + snapshot.Add(skey, sItem); + snapshot.AddContract(script.ToScriptHash(), contractState); - using ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + using ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshot); Debugger debugger = new(ae); ae.LoadScript(script); debugger.StepInto(); @@ -151,6 +161,7 @@ public void ApplicationEngineReusedStorage_PartialReuse() [TestMethod] public void ApplicationEngineReusedStorage_PartialReuseTwice() { + var snapshot = _snapshotCache.CloneCache(); var key = new byte[] { (byte)OpCode.PUSH1 }; var oldValue = new byte[] { (byte)OpCode.PUSH1 }; var value = new byte[] { (byte)OpCode.PUSH1, (byte)OpCode.PUSH1 }; @@ -162,11 +173,10 @@ public void ApplicationEngineReusedStorage_PartialReuseTwice() StorageKey skey = TestUtils.GetStorageKey(contractState.Id, key); StorageItem sItem = TestUtils.GetStorageItem(oldValue); - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); - snapshotCache.Add(skey, sItem); - snapshotCache.AddContract(script.ToScriptHash(), contractState); + snapshot.Add(skey, sItem); + snapshot.AddContract(script.ToScriptHash(), contractState); - using ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + using ApplicationEngine ae = ApplicationEngine.Create(TriggerType.Application, null, snapshot); Debugger debugger = new(ae); ae.LoadScript(script); debugger.StepInto(); //push value diff --git a/tests/Neo.UnitTests/SmartContract/UT_InteropService.NEO.cs b/tests/Neo.UnitTests/SmartContract/UT_InteropService.NEO.cs index e0ccdd7dcc..1dc9b53ebb 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_InteropService.NEO.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_InteropService.NEO.cs @@ -244,7 +244,7 @@ public void TestContract_Update_Invalid() [TestMethod] public void TestStorage_Find() { - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); + var snapshot = _snapshotCache.CloneCache(); var state = TestUtils.GetContract(); var storageItem = new StorageItem @@ -256,9 +256,9 @@ public void TestStorage_Find() Id = state.Id, Key = new byte[] { 0x01 } }; - snapshotCache.AddContract(state.Hash, state); - snapshotCache.Add(storageKey, storageItem); - var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + snapshot.AddContract(state.Hash, state); + snapshot.Add(storageKey, storageItem); + var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(new byte[] { 0x01 }); var iterator = engine.Find(new StorageContext diff --git a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs index 35dd3dbe37..da9d0a40c0 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_InteropService.cs @@ -19,6 +19,7 @@ using Neo.IO; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Manifest; using Neo.SmartContract.Native; @@ -35,6 +36,14 @@ namespace Neo.UnitTests.SmartContract [TestClass] public partial class UT_InteropService : TestKit { + private DataCache _snapshotCache; + + [TestInitialize] + public void TestSetup() + { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); + } + [TestMethod] public void Runtime_GetNotifications_Test() { @@ -365,7 +374,7 @@ public void TestRuntime_Log() public void TestRuntime_GetTime() { Block block = new() { Header = new Header() }; - var engine = GetEngine(true, true, hasBlock: true); + var engine = GetEngine(true, hasBlock: true); engine.GetTime().Should().Be(block.Timestamp); } @@ -391,7 +400,7 @@ public void TestRuntime_GetCurrentSigners_SysCall() // Null - using var engineA = GetEngine(hasSnapshot: true, addScript: false, hasContainer: false); + using var engineA = GetEngine(addScript: false, hasContainer: false); engineA.LoadScript(script.ToArray()); engineA.Execute(); @@ -402,7 +411,7 @@ public void TestRuntime_GetCurrentSigners_SysCall() // Not null - using var engineB = GetEngine(hasSnapshot: true, addScript: false, hasContainer: true); + using var engineB = GetEngine(addScript: false, hasContainer: true); engineB.LoadScript(script.ToArray()); engineB.Execute(); @@ -472,7 +481,7 @@ public void TestBlockchain_GetTransaction() [TestMethod] public void TestBlockchain_GetTransactionHeight() { - var engine = GetEngine(hasSnapshot: true, addScript: false); + var engine = GetEngine(addScript: false); var state = new TransactionState() { BlockIndex = 0, @@ -501,10 +510,9 @@ public void TestBlockchain_GetContract() 0x01, 0x01, 0x01, 0x01, 0x01 }; NativeContract.ContractManagement.GetContract(engine.SnapshotCache, new UInt160(data1)).Should().BeNull(); - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); var state = TestUtils.GetContract(); - snapshotCache.AddContract(state.Hash, state); - engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + engine.SnapshotCache.AddContract(state.Hash, state); + engine = ApplicationEngine.Create(TriggerType.Application, null, engine.SnapshotCache); engine.LoadScript(new byte[] { 0x01 }); NativeContract.ContractManagement.GetContract(engine.SnapshotCache, state.Hash).Hash.Should().Be(state.Hash); } @@ -533,15 +541,14 @@ public void TestBlockchain_ListContracts() var list = NativeContract.ContractManagement.ListContracts(engine.SnapshotCache); list.ForEach(p => p.Id.Should().BeLessThan(0)); - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); var state = TestUtils.GetContract(); - snapshotCache.AddContract(state.Hash, state); - engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + engine.SnapshotCache.AddContract(state.Hash, state); + engine = ApplicationEngine.Create(TriggerType.Application, null, engine.SnapshotCache); engine.LoadScript(new byte[] { 0x01 }); NativeContract.ContractManagement.GetContract(engine.SnapshotCache, state.Hash).Hash.Should().Be(state.Hash); var list2 = NativeContract.ContractManagement.ListContracts(engine.SnapshotCache); - list2.Count().Should().Be(list.Count() + 1); + list2.Count().Should().Be(list.Count()); } [TestMethod] @@ -655,7 +662,6 @@ public void TestStorage_Put() public void TestStorage_Delete() { var engine = GetEngine(false, true); - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); var state = TestUtils.GetContract(); var storageKey = new StorageKey { @@ -666,9 +672,9 @@ public void TestStorage_Delete() { Value = new byte[] { 0x01, 0x02, 0x03, 0x04 } }; - snapshotCache.AddContract(state.Hash, state); - snapshotCache.Add(storageKey, storageItem); - engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + engine.SnapshotCache.AddContract(state.Hash, state); + engine.SnapshotCache.Add(storageKey, storageItem); + engine = ApplicationEngine.Create(TriggerType.Application, null, engine.SnapshotCache); engine.LoadScript(new byte[] { 0x01 }); var key = new byte[] { 0x01 }; var storageContext = new StorageContext @@ -767,12 +773,12 @@ public static void LogEvent(object sender, LogEventArgs args) tx.Script = new byte[] { 0x01, 0x02, 0x03 }; } - private static ApplicationEngine GetEngine(bool hasContainer = false, bool hasSnapshot = false, bool hasBlock = false, bool addScript = true, long gas = 20_00000000) + private ApplicationEngine GetEngine(bool hasContainer = false, bool hasBlock = false, bool addScript = true, long gas = 20_00000000) { + var snapshot = _snapshotCache.CloneCache(); var tx = hasContainer ? TestUtils.GetTransaction(UInt160.Zero) : null; - var snapshotCache = hasSnapshot ? TestBlockchain.GetTestSnapshotCache() : null; var block = hasBlock ? new Block { Header = new Header() } : null; - var engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshotCache, block, TestBlockchain.TheNeoSystem.Settings, gas: gas); + var engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshot, block, TestBlockchain.TheNeoSystem.Settings, gas: gas); if (addScript) engine.LoadScript(new byte[] { 0x01 }); return engine; } diff --git a/tests/Neo.UnitTests/SmartContract/UT_JsonSerializer.cs b/tests/Neo.UnitTests/SmartContract/UT_JsonSerializer.cs index fc29c95c12..f418bcb086 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_JsonSerializer.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_JsonSerializer.cs @@ -11,6 +11,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Json; +using Neo.Persistence; using Neo.SmartContract; using Neo.VM; using Neo.VM.Types; @@ -24,6 +25,14 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_JsonSerializer { + private DataCache _snapshotCache; + + [TestInitialize] + public void TestSetup() + { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); + } + [TestMethod] public void JsonTest_WrongJson() { @@ -193,7 +202,8 @@ public void JsonTest_Object() [TestMethod] public void Deserialize_WrongJson() { - ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, null); + var snapshot = _snapshotCache.CloneCache(); + ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); Assert.ThrowsException(() => JsonSerializer.Deserialize(engine, JObject.Parse("x"), ExecutionEngineLimits.Default)); } @@ -228,7 +238,8 @@ public void Serialize_Null() [TestMethod] public void Deserialize_EmptyObject() { - ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, null); + var snapshot = _snapshotCache.CloneCache(); + ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); var items = JsonSerializer.Deserialize(engine, JObject.Parse("{}"), ExecutionEngineLimits.Default); Assert.IsInstanceOfType(items, typeof(Map)); @@ -247,7 +258,8 @@ public void Serialize_EmptyArray() [TestMethod] public void Deserialize_EmptyArray() { - ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, null); + var snapshot = _snapshotCache.CloneCache(); + ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); var items = JsonSerializer.Deserialize(engine, JObject.Parse("[]"), ExecutionEngineLimits.Default); Assert.IsInstanceOfType(items, typeof(VM.Types.Array)); @@ -272,7 +284,8 @@ public void Serialize_Map_Test() [TestMethod] public void Deserialize_Map_Test() { - ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, null, null, ProtocolSettings.Default); + var snapshot = _snapshotCache.CloneCache(); + ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, ProtocolSettings.Default); var items = JsonSerializer.Deserialize(engine, JObject.Parse("{\"test1\":123,\"test2\":321}"), ExecutionEngineLimits.Default); Assert.IsInstanceOfType(items, typeof(Map)); @@ -302,7 +315,8 @@ public void Serialize_Array_Bool_Str_Num() [TestMethod] public void Deserialize_Array_Bool_Str_Num() { - ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, null, null, ProtocolSettings.Default); + var snapshot = _snapshotCache.CloneCache(); + ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, ProtocolSettings.Default); var items = JsonSerializer.Deserialize(engine, JObject.Parse("[true,\"test\",123,9.05E+28]"), ExecutionEngineLimits.Default); Assert.IsInstanceOfType(items, typeof(VM.Types.Array)); @@ -333,7 +347,8 @@ public void Serialize_Array_OfArray() [TestMethod] public void Deserialize_Array_OfArray() { - ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, null, null, ProtocolSettings.Default); + var snapshot = _snapshotCache.CloneCache(); + ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, ProtocolSettings.Default); var items = JsonSerializer.Deserialize(engine, JObject.Parse("[[true,\"test1\",123],[true,\"test2\",321]]"), ExecutionEngineLimits.Default); Assert.IsInstanceOfType(items, typeof(VM.Types.Array)); diff --git a/tests/Neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs b/tests/Neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs index 59afbbb760..e761913073 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_NotifyEventArgs.cs @@ -12,6 +12,7 @@ using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.SmartContract; using Neo.VM; using Neo.VM.Types; @@ -21,6 +22,14 @@ namespace Neo.UnitTests.SmartContract [TestClass] public class UT_NotifyEventArgs { + private DataCache _snapshotCache; + + [TestInitialize] + public void TestSetup() + { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); + } + [TestMethod] public void TestGetScriptContainer() { @@ -30,11 +39,11 @@ public void TestGetScriptContainer() args.ScriptContainer.Should().Be(container); } - [TestMethod] public void TestIssue3300() // https://github.com/neo-project/neo/issues/3300 { - using var engine = ApplicationEngine.Create(TriggerType.Application, null, null, settings: TestProtocolSettings.Default, gas: 1100_00000000); + var snapshot = _snapshotCache.CloneCache(); + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestProtocolSettings.Default, gas: 1100_00000000); using (var script = new ScriptBuilder()) { // Build call script calling disallowed method. diff --git a/tests/Neo.UnitTests/SmartContract/UT_Syscalls.cs b/tests/Neo.UnitTests/SmartContract/UT_Syscalls.cs index e2f89751c1..d65e054084 100644 --- a/tests/Neo.UnitTests/SmartContract/UT_Syscalls.cs +++ b/tests/Neo.UnitTests/SmartContract/UT_Syscalls.cs @@ -15,6 +15,7 @@ using Neo.Extensions; using Neo.IO; using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.UnitTests.Extensions; @@ -28,6 +29,14 @@ namespace Neo.UnitTests.SmartContract [TestClass] public partial class UT_Syscalls : TestKit { + private DataCache _snapshotCache; + + [TestInitialize] + public void TestSetup() + { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); + } + [TestMethod] public void System_Blockchain_GetBlock() { @@ -63,14 +72,14 @@ public void System_Blockchain_GetBlock() Hashes = new[] { tx.Hash } }; - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); + var snapshot = _snapshotCache.CloneCache(); using ScriptBuilder script = new(); script.EmitDynamicCall(NativeContract.Ledger.Hash, "getBlock", block.Hash.ToArray()); // Without block - var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache, settings: TestBlockchain.TheNeoSystem.Settings); + var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); @@ -82,18 +91,18 @@ public void System_Blockchain_GetBlock() const byte Prefix_Transaction = 11; const byte Prefix_CurrentBlock = 12; - TestUtils.BlocksAdd(snapshotCache, block.Hash, block); + TestUtils.BlocksAdd(snapshot, block.Hash, block); - var height = snapshotCache[NativeContract.Ledger.CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable(); + var height = snapshot[NativeContract.Ledger.CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable(); height.Index = block.Index + TestProtocolSettings.Default.MaxTraceableBlocks; - snapshotCache.Add(NativeContract.Ledger.CreateStorageKey(Prefix_Transaction, tx.Hash), new StorageItem(new TransactionState + snapshot.Add(NativeContract.Ledger.CreateStorageKey(Prefix_Transaction, tx.Hash), new StorageItem(new TransactionState { BlockIndex = block.Index, Transaction = tx })); - engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache, settings: TestBlockchain.TheNeoSystem.Settings); + engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); @@ -102,10 +111,10 @@ public void System_Blockchain_GetBlock() // With block - height = snapshotCache[NativeContract.Ledger.CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable(); + height = snapshot[NativeContract.Ledger.CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable(); height.Index = block.Index; - engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache, settings: TestBlockchain.TheNeoSystem.Settings); + engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); @@ -118,13 +127,13 @@ public void System_Blockchain_GetBlock() [TestMethod] public void System_ExecutionEngine_GetScriptContainer() { - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); + var snapshot = _snapshotCache.CloneCache(); using ScriptBuilder script = new(); script.EmitSysCall(ApplicationEngine.System_Runtime_GetScriptContainer); // Without tx - var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.FAULT); @@ -154,7 +163,7 @@ public void System_ExecutionEngine_GetScriptContainer() Witnesses = new Witness[] { new Witness() { VerificationScript = new byte[] { 0x07 } } }, }; - engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshotCache); + engine = ApplicationEngine.Create(TriggerType.Application, tx, snapshot); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); @@ -167,7 +176,7 @@ public void System_ExecutionEngine_GetScriptContainer() [TestMethod] public void System_Runtime_GasLeft() { - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); + var snapshot = _snapshotCache.CloneCache(); using (var script = new ScriptBuilder()) { @@ -182,7 +191,7 @@ public void System_Runtime_GasLeft() // Execute - var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache, gas: 100_000_000); + var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, gas: 100_000_000); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); @@ -203,7 +212,7 @@ public void System_Runtime_GasLeft() // Execute - var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache); + var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(script.ToArray()); // Check the results @@ -218,8 +227,8 @@ public void System_Runtime_GasLeft() [TestMethod] public void System_Runtime_GetInvocationCounter() { + var snapshot = _snapshotCache.CloneCache(); ContractState contractA, contractB, contractC; - var snapshotCache = TestBlockchain.GetTestSnapshotCache(); // Create dummy contracts @@ -237,15 +246,15 @@ public void System_Runtime_GetInvocationCounter() // Init A,B,C contracts // First two drops is for drop method and arguments - snapshotCache.DeleteContract(contractA.Hash); - snapshotCache.DeleteContract(contractB.Hash); - snapshotCache.DeleteContract(contractC.Hash); + snapshot.DeleteContract(contractA.Hash); + snapshot.DeleteContract(contractB.Hash); + snapshot.DeleteContract(contractC.Hash); contractA.Manifest = TestUtils.CreateManifest("dummyMain", ContractParameterType.Any, ContractParameterType.String, ContractParameterType.Integer); contractB.Manifest = TestUtils.CreateManifest("dummyMain", ContractParameterType.Any, ContractParameterType.String, ContractParameterType.Integer); contractC.Manifest = TestUtils.CreateManifest("dummyMain", ContractParameterType.Any, ContractParameterType.String, ContractParameterType.Integer); - snapshotCache.AddContract(contractA.Hash, contractA); - snapshotCache.AddContract(contractB.Hash, contractB); - snapshotCache.AddContract(contractC.Hash, contractC); + snapshot.AddContract(contractA.Hash, contractA); + snapshot.AddContract(contractB.Hash, contractB); + snapshot.AddContract(contractC.Hash, contractC); } // Call A,B,B,C @@ -259,7 +268,7 @@ public void System_Runtime_GetInvocationCounter() // Execute - var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshotCache, null, ProtocolSettings.Default); + var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, null, ProtocolSettings.Default); engine.LoadScript(script.ToArray()); Assert.AreEqual(VMState.HALT, engine.Execute()); diff --git a/tests/Neo.UnitTests/VM/UT_Helper.cs b/tests/Neo.UnitTests/VM/UT_Helper.cs index efccf524f6..4d37dd815f 100644 --- a/tests/Neo.UnitTests/VM/UT_Helper.cs +++ b/tests/Neo.UnitTests/VM/UT_Helper.cs @@ -14,6 +14,7 @@ using Neo.Cryptography.ECC; using Neo.Extensions; using Neo.IO; +using Neo.Persistence; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; @@ -31,6 +32,14 @@ namespace Neo.UnitTests.VMT [TestClass] public class UT_Helper { + private DataCache _snapshotCache; + + [TestInitialize] + public void TestSetup() + { + _snapshotCache = TestBlockchain.GetTestSnapshotCache(); + } + [TestMethod] public void TestEmit() { @@ -85,11 +94,12 @@ public void TestEmitAppCall1() [TestMethod] public void TestEmitArray() { + var snapshot = _snapshotCache.CloneCache(); var expected = new BigInteger[] { 1, 2, 3 }; var sb = new ScriptBuilder(); sb.CreateArray(expected); - using var engine = ApplicationEngine.Create(TriggerType.Application, null, null); + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(sb.ToArray()); Assert.AreEqual(VMState.HALT, engine.Execute()); @@ -99,7 +109,7 @@ public void TestEmitArray() sb = new ScriptBuilder(); sb.CreateArray(expected); - using var engine2 = ApplicationEngine.Create(TriggerType.Application, null, null); + using var engine2 = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine2.LoadScript(sb.ToArray()); Assert.AreEqual(VMState.HALT, engine2.Execute()); @@ -109,11 +119,12 @@ public void TestEmitArray() [TestMethod] public void TestEmitStruct() { + var snapshot = _snapshotCache.CloneCache(); var expected = new BigInteger[] { 1, 2, 3 }; var sb = new ScriptBuilder(); sb.CreateStruct(expected); - using var engine = ApplicationEngine.Create(TriggerType.Application, null, null); + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(sb.ToArray()); Assert.AreEqual(VMState.HALT, engine.Execute()); @@ -123,7 +134,7 @@ public void TestEmitStruct() sb = new ScriptBuilder(); sb.CreateStruct(expected); - using var engine2 = ApplicationEngine.Create(TriggerType.Application, null, null); + using var engine2 = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine2.LoadScript(sb.ToArray()); Assert.AreEqual(VMState.HALT, engine2.Execute()); @@ -133,11 +144,12 @@ public void TestEmitStruct() [TestMethod] public void TestEmitMap() { + var snapshot = _snapshotCache.CloneCache(); var expected = new Dictionary() { { 1, 2 }, { 3, 4 } }; var sb = new ScriptBuilder(); sb.CreateMap(expected); - using var engine = ApplicationEngine.Create(TriggerType.Application, null, null); + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot); engine.LoadScript(sb.ToArray()); Assert.AreEqual(VMState.HALT, engine.Execute()); From 548bd0573cb2c3fdd497c4c3c429ab5e950f821b Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 27 Dec 2024 12:05:26 +0300 Subject: [PATCH 23/25] NeoToken: add NEP-27 to supported standards list starting from Echidna (#3643) https://github.com/neo-project/neo/pull/3597 introduces `onNEP17Payment` handler to native NeoToke contract starting from Echidna hardfork. We need to update the list of supported standards respectively. Signed-off-by: Anna Shaleva --- src/Neo/SmartContract/Native/FungibleToken.cs | 2 +- src/Neo/SmartContract/Native/NativeContract.cs | 4 ++-- src/Neo/SmartContract/Native/NeoToken.cs | 13 +++++++++++++ .../SmartContract/Native/UT_NativeContract.cs | 2 +- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Neo/SmartContract/Native/FungibleToken.cs b/src/Neo/SmartContract/Native/FungibleToken.cs index 2175f43dfd..ba6c6d4723 100644 --- a/src/Neo/SmartContract/Native/FungibleToken.cs +++ b/src/Neo/SmartContract/Native/FungibleToken.cs @@ -65,7 +65,7 @@ protected FungibleToken() : base() Factor = BigInteger.Pow(10, Decimals); } - protected override void OnManifestCompose(ContractManifest manifest) + protected override void OnManifestCompose(IsHardforkEnabledDelegate hfChecker, uint blockHeight, ContractManifest manifest) { manifest.SupportedStandards = new[] { "NEP-17" }; } diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index 8b355464c9..1ad0ae3a35 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -259,7 +259,7 @@ public ContractState GetContractState(IsHardforkEnabledDelegate hfChecker, uint Extra = null }; - OnManifestCompose(manifest); + OnManifestCompose(hfChecker, blockHeight, manifest); // Return ContractState return new ContractState @@ -271,7 +271,7 @@ public ContractState GetContractState(IsHardforkEnabledDelegate hfChecker, uint }; } - protected virtual void OnManifestCompose(ContractManifest manifest) { } + protected virtual void OnManifestCompose(IsHardforkEnabledDelegate hfChecker, uint blockHeight, ContractManifest manifest) { } /// /// It is the initialize block diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 7e945d8481..706d86cdfe 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -16,6 +16,7 @@ using Neo.IO; using Neo.Persistence; using Neo.SmartContract.Iterators; +using Neo.SmartContract.Manifest; using Neo.VM; using Neo.VM.Types; using System; @@ -107,6 +108,18 @@ private protected override async ContractTask PostTransferAsync(ApplicationEngin await GAS.Mint(engine, distribution.Account, distribution.Amount, callOnPayment); } + protected override void OnManifestCompose(IsHardforkEnabledDelegate hfChecker, uint blockHeight, ContractManifest manifest) + { + if (hfChecker(Hardfork.HF_Echidna, blockHeight)) + { + manifest.SupportedStandards = new[] { "NEP-17", "NEP-27" }; + } + else + { + manifest.SupportedStandards = new[] { "NEP-17" }; + } + } + private GasDistribution DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state) { // PersistingBlock is null when running under the debugger diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index d5d179428c..f742e11471 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -45,7 +45,7 @@ public void TestSetup() {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2681632925},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"String","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"String"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":77,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":84,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":91,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":98,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":112,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":126,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":133,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":140,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":147,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":154,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"CryptoLib", """{"id":-3,"updatecounter":0,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"bls12381Add","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","offset":0,"safe":true},{"name":"bls12381Deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","offset":7,"safe":true},{"name":"bls12381Equal","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","offset":14,"safe":true},{"name":"bls12381Mul","parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"bls12381Pairing","parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","offset":28,"safe":true},{"name":"bls12381Serialize","parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","offset":35,"safe":true},{"name":"keccak256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"murmur32","parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","offset":49,"safe":true},{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":63,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","offset":70,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"LedgerContract", """{"id":-4,"updatecounter":0,"hash":"0xda65b600f7124ce6c79950c1772a36403104f2be","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"LedgerContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"currentHash","parameters":[],"returntype":"Hash256","offset":0,"safe":true},{"name":"currentIndex","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlock","parameters":[{"name":"indexOrHash","type":"ByteArray"}],"returntype":"Array","offset":14,"safe":true},{"name":"getTransaction","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":21,"safe":true},{"name":"getTransactionFromBlock","parameters":[{"name":"blockIndexOrHash","type":"ByteArray"},{"name":"txIndex","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getTransactionHeight","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":35,"safe":true},{"name":"getTransactionSigners","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":42,"safe":true},{"name":"getTransactionVMState","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":49,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, - {"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1991619121},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","offset":77,"safe":false},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":84,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":98,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":105,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":112,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":119,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":126,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":140,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, + {"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1991619121},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17","NEP-27"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","offset":77,"safe":false},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":84,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":98,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":105,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":112,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":119,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":126,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":140,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"GasToken", """{"id":-6,"updatecounter":0,"hash":"0xd2a4cff31913016155e38e474a2c06d08be276cf","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"GasToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"symbol","parameters":[],"returntype":"String","offset":14,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":28,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"PolicyContract", """{"id":-7,"updatecounter":0,"hash":"0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"PolicyContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"blockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":0,"safe":false},{"name":"getAttributeFee","parameters":[{"name":"attributeType","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"getExecFeeFactor","parameters":[],"returntype":"Integer","offset":14,"safe":true},{"name":"getFeePerByte","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"getStoragePrice","parameters":[],"returntype":"Integer","offset":28,"safe":true},{"name":"isBlocked","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":35,"safe":true},{"name":"setAttributeFee","parameters":[{"name":"attributeType","type":"Integer"},{"name":"value","type":"Integer"}],"returntype":"Void","offset":42,"safe":false},{"name":"setExecFeeFactor","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":49,"safe":false},{"name":"setFeePerByte","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":56,"safe":false},{"name":"setStoragePrice","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":63,"safe":false},{"name":"unblockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":70,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"RoleManagement", """{"id":-8,"updatecounter":0,"hash":"0x49cf4e5378ffcd4dec034fd98a174c5491e395e2","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0A=","checksum":983638438},"manifest":{"name":"RoleManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"designateAsRole","parameters":[{"name":"role","type":"Integer"},{"name":"nodes","type":"Array"}],"returntype":"Void","offset":0,"safe":false},{"name":"getDesignatedByRole","parameters":[{"name":"role","type":"Integer"},{"name":"index","type":"Integer"}],"returntype":"Array","offset":7,"safe":true}],"events":[{"name":"Designation","parameters":[{"name":"Role","type":"Integer"},{"name":"BlockIndex","type":"Integer"},{"name":"Old","type":"Array"},{"name":"New","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, From 93fc37b272c86828af6585564b9ccf6a80aec80e Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 30 Dec 2024 19:18:35 -0800 Subject: [PATCH 24/25] ut: fix HF_Echidna unit tests (#3646) * Fix UT * Update src/Neo/ProtocolSettings.cs Co-authored-by: nan01ab * Update src/Neo/ProtocolSettings.cs Co-authored-by: nan01ab * Update src/Neo/ProtocolSettings.cs Co-authored-by: Christopher Schuchardt --------- Co-authored-by: Jimmy Co-authored-by: nan01ab Co-authored-by: Christopher Schuchardt --- src/Neo/ProtocolSettings.cs | 40 ++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/Neo/ProtocolSettings.cs b/src/Neo/ProtocolSettings.cs index cef7ef6de1..da98c3b8c6 100644 --- a/src/Neo/ProtocolSettings.cs +++ b/src/Neo/ProtocolSettings.cs @@ -124,6 +124,42 @@ public record ProtocolSettings public static ProtocolSettings Custom { get; set; } + /// + /// Searches for a file in the given path. If not found, checks in the executable directory. + /// + /// The name of the file to search for. + /// The primary path to search in. + /// Full path of the file if found, null otherwise. + public static string FindFile(string fileName, string path) + { + + // Check if the given path is relative + if (!Path.IsPathRooted(path)) + { + // Combine with the executable directory if relative + var executablePath = AppDomain.CurrentDomain.BaseDirectory; + path = Path.Combine(executablePath, path); + } + + // Check if file exists in the specified (resolved) path + var fullPath = Path.Combine(path, fileName); + if (File.Exists(fullPath)) + { + return fullPath; + } + + // Check if file exists in the executable directory + var executableDir = AppContext.BaseDirectory; + fullPath = Path.Combine(executableDir, fileName); + if (File.Exists(fullPath)) + { + return fullPath; + } + + // File not found in either location + return null; + } + /// /// Loads the from the specified stream. /// @@ -143,7 +179,9 @@ public static ProtocolSettings Load(Stream stream) /// The loaded . public static ProtocolSettings Load(string path) { - if (!File.Exists(path)) + path = FindFile(path, Environment.CurrentDirectory); + + if (path is null) { return Default; } From b1a3ea3d9c67295e42c5830057c2e5dcb96164a7 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 9 Jan 2025 18:05:40 +0800 Subject: [PATCH 25/25] [Core Add] Add support to Ed25519 (#3507) * fix unnecessary change * Clean using --------- Co-authored-by: Fernando Diaz Toledano --- src/Neo/Cryptography/Ed25519.cs | 99 +++++++++++ src/Neo/SmartContract/Native/CryptoLib.cs | 31 ++++ .../Neo.UnitTests/Cryptography/UT_Ed25519.cs | 162 ++++++++++++++++++ .../SmartContract/Native/UT_CryptoLib.cs | 55 ++++++ .../SmartContract/Native/UT_NativeContract.cs | 4 +- 5 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 src/Neo/Cryptography/Ed25519.cs create mode 100644 tests/Neo.UnitTests/Cryptography/UT_Ed25519.cs diff --git a/src/Neo/Cryptography/Ed25519.cs b/src/Neo/Cryptography/Ed25519.cs new file mode 100644 index 0000000000..5919e152b3 --- /dev/null +++ b/src/Neo/Cryptography/Ed25519.cs @@ -0,0 +1,99 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// Ed25519.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Security; +using System; + +namespace Neo.Cryptography +{ + public class Ed25519 + { + internal const int PublicKeySize = 32; + private const int PrivateKeySize = 32; + internal const int SignatureSize = 64; + + /// + /// Generates a new Ed25519 key pair. + /// + /// A byte array containing the private key. + public static byte[] GenerateKeyPair() + { + var keyPairGenerator = new Ed25519KeyPairGenerator(); + keyPairGenerator.Init(new Ed25519KeyGenerationParameters(new SecureRandom())); + var keyPair = keyPairGenerator.GenerateKeyPair(); + return ((Ed25519PrivateKeyParameters)keyPair.Private).GetEncoded(); + } + + /// + /// Derives the public key from a given private key. + /// + /// The private key as a byte array. + /// The corresponding public key as a byte array. + /// Thrown when the private key size is invalid. + public static byte[] GetPublicKey(byte[] privateKey) + { + if (privateKey.Length != PrivateKeySize) + throw new ArgumentException("Invalid private key size", nameof(privateKey)); + + var privateKeyParams = new Ed25519PrivateKeyParameters(privateKey, 0); + return privateKeyParams.GeneratePublicKey().GetEncoded(); + } + + /// + /// Signs a message using the provided private key. + /// Parameters are in the same order as the sample in the Ed25519 specification + /// Ed25519.sign(privkey, pubkey, msg) with pubkey omitted + /// ref. https://datatracker.ietf.org/doc/html/rfc8032. + /// + /// The private key used for signing. + /// The message to be signed. + /// The signature as a byte array. + /// Thrown when the private key size is invalid. + public static byte[] Sign(byte[] privateKey, byte[] message) + { + if (privateKey.Length != PrivateKeySize) + throw new ArgumentException("Invalid private key size", nameof(privateKey)); + + var signer = new Ed25519Signer(); + signer.Init(true, new Ed25519PrivateKeyParameters(privateKey, 0)); + signer.BlockUpdate(message, 0, message.Length); + return signer.GenerateSignature(); + } + + /// + /// Verifies an Ed25519 signature for a given message using the provided public key. + /// Parameters are in the same order as the sample in the Ed25519 specification + /// Ed25519.verify(public, msg, signature) + /// ref. https://datatracker.ietf.org/doc/html/rfc8032. + /// + /// The 32-byte public key used for verification. + /// The message that was signed. + /// The 64-byte signature to verify. + /// True if the signature is valid for the given message and public key; otherwise, false. + /// Thrown when the signature or public key size is invalid. + public static bool Verify(byte[] publicKey, byte[] message, byte[] signature) + { + if (signature.Length != SignatureSize) + throw new ArgumentException("Invalid signature size", nameof(signature)); + + if (publicKey.Length != PublicKeySize) + throw new ArgumentException("Invalid public key size", nameof(publicKey)); + + var verifier = new Ed25519Signer(); + verifier.Init(false, new Ed25519PublicKeyParameters(publicKey, 0)); + verifier.BlockUpdate(message, 0, message.Length); + return verifier.VerifySignature(signature); + } + } +} diff --git a/src/Neo/SmartContract/Native/CryptoLib.cs b/src/Neo/SmartContract/Native/CryptoLib.cs index 9ee46d9490..e7955f1b01 100644 --- a/src/Neo/SmartContract/Native/CryptoLib.cs +++ b/src/Neo/SmartContract/Native/CryptoLib.cs @@ -11,6 +11,8 @@ using Neo.Cryptography; using Neo.Cryptography.ECC; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; using System; using System.Collections.Generic; @@ -115,5 +117,34 @@ public static bool VerifyWithECDsaV0(byte[] message, byte[] pubkey, byte[] signa return false; } } + + /// + /// Verifies that a digital signature is appropriate for the provided key and message using the Ed25519 algorithm. + /// + /// The signed message. + /// The Ed25519 public key to be used. + /// The signature to be verified. + /// if the signature is valid; otherwise, . + [ContractMethod(Hardfork.HF_Echidna, CpuFee = 1 << 15)] + public static bool VerifyWithEd25519(byte[] message, byte[] publicKey, byte[] signature) + { + if (signature.Length != Ed25519.SignatureSize) + return false; + + if (publicKey.Length != Ed25519.PublicKeySize) + return false; + + try + { + var verifier = new Ed25519Signer(); + verifier.Init(false, new Ed25519PublicKeyParameters(publicKey, 0)); + verifier.BlockUpdate(message, 0, message.Length); + return verifier.VerifySignature(signature); + } + catch (Exception) + { + return false; + } + } } } diff --git a/tests/Neo.UnitTests/Cryptography/UT_Ed25519.cs b/tests/Neo.UnitTests/Cryptography/UT_Ed25519.cs new file mode 100644 index 0000000000..5998d957f3 --- /dev/null +++ b/tests/Neo.UnitTests/Cryptography/UT_Ed25519.cs @@ -0,0 +1,162 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// UT_Ed25519.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.Extensions; +using Neo.IO; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.Wallets; +using Neo.Wallets.NEP6; +using System; +using System.Linq; +using System.Text; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_Ed25519 + { + [TestMethod] + public void TestGenerateKeyPair() + { + byte[] keyPair = Ed25519.GenerateKeyPair(); + keyPair.Should().NotBeNull(); + keyPair.Length.Should().Be(32); + } + + [TestMethod] + public void TestGetPublicKey() + { + byte[] privateKey = Ed25519.GenerateKeyPair(); + byte[] publicKey = Ed25519.GetPublicKey(privateKey); + publicKey.Should().NotBeNull(); + publicKey.Length.Should().Be(Ed25519.PublicKeySize); + } + + [TestMethod] + public void TestSignAndVerify() + { + byte[] privateKey = Ed25519.GenerateKeyPair(); + byte[] publicKey = Ed25519.GetPublicKey(privateKey); + byte[] message = Encoding.UTF8.GetBytes("Hello, Neo!"); + + byte[] signature = Ed25519.Sign(privateKey, message); + signature.Should().NotBeNull(); + signature.Length.Should().Be(Ed25519.SignatureSize); + + bool isValid = Ed25519.Verify(publicKey, message, signature); + isValid.Should().BeTrue(); + } + + [TestMethod] + public void TestFailedVerify() + { + byte[] privateKey = Ed25519.GenerateKeyPair(); + byte[] publicKey = Ed25519.GetPublicKey(privateKey); + byte[] message = Encoding.UTF8.GetBytes("Hello, Neo!"); + + byte[] signature = Ed25519.Sign(privateKey, message); + + // Tamper with the message + byte[] tamperedMessage = Encoding.UTF8.GetBytes("Hello, Neo?"); + + bool isValid = Ed25519.Verify(publicKey, tamperedMessage, signature); + isValid.Should().BeFalse(); + + // Tamper with the signature + byte[] tamperedSignature = new byte[signature.Length]; + Array.Copy(signature, tamperedSignature, signature.Length); + tamperedSignature[0] ^= 0x01; // Flip one bit + + isValid = Ed25519.Verify(publicKey, message, tamperedSignature); + isValid.Should().BeFalse(); + + // Use wrong public key + byte[] wrongPrivateKey = Ed25519.GenerateKeyPair(); + byte[] wrongPublicKey = Ed25519.GetPublicKey(wrongPrivateKey); + + isValid = Ed25519.Verify(wrongPublicKey, message, signature); + isValid.Should().BeFalse(); + } + + [TestMethod] + public void TestInvalidPrivateKeySize() + { + byte[] invalidPrivateKey = new byte[31]; // Invalid size + Action act = () => Ed25519.GetPublicKey(invalidPrivateKey); + act.Should().Throw().WithMessage("Invalid private key size*"); + } + + [TestMethod] + public void TestInvalidSignatureSize() + { + byte[] message = Encoding.UTF8.GetBytes("Test message"); + byte[] invalidSignature = new byte[63]; // Invalid size + byte[] publicKey = new byte[Ed25519.PublicKeySize]; + Action act = () => Ed25519.Verify(publicKey, message, invalidSignature); + act.Should().Throw().WithMessage("Invalid signature size*"); + } + + [TestMethod] + public void TestInvalidPublicKeySize() + { + byte[] message = Encoding.UTF8.GetBytes("Test message"); + byte[] signature = new byte[Ed25519.SignatureSize]; + byte[] invalidPublicKey = new byte[31]; // Invalid size + Action act = () => Ed25519.Verify(invalidPublicKey, message, signature); + act.Should().Throw().WithMessage("Invalid public key size*"); + } + + // Test vectors from RFC 8032 (https://datatracker.ietf.org/doc/html/rfc8032) + // Section 7.1. Test Vectors for Ed25519 + + [TestMethod] + public void TestVectorCase1() + { + byte[] privateKey = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".HexToBytes(); + byte[] publicKey = "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".HexToBytes(); + byte[] message = Array.Empty(); + byte[] signature = ("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155" + + "5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b").HexToBytes(); + + Ed25519.GetPublicKey(privateKey).Should().Equal(publicKey); + Ed25519.Sign(privateKey, message).Should().Equal(signature); + } + + [TestMethod] + public void TestVectorCase2() + { + byte[] privateKey = "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb".HexToBytes(); + byte[] publicKey = "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c".HexToBytes(); + byte[] message = Encoding.UTF8.GetBytes("r"); + byte[] signature = ("92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da" + + "085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00").HexToBytes(); + + Ed25519.GetPublicKey(privateKey).Should().Equal(publicKey); + Ed25519.Sign(privateKey, message).Should().Equal(signature); + } + + [TestMethod] + public void TestVectorCase3() + { + byte[] privateKey = "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7".HexToBytes(); + byte[] publicKey = "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025".HexToBytes(); + byte[] signature = ("6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac" + + "18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a").HexToBytes(); + byte[] message = "af82".HexToBytes(); + Ed25519.GetPublicKey(privateKey).Should().Equal(publicKey); + Ed25519.Sign(privateKey, message).Should().Equal(signature); + } + } +} diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs index daf1922644..9852710bdb 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_CryptoLib.cs @@ -26,6 +26,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; namespace Neo.UnitTests.SmartContract.Native { @@ -910,5 +911,59 @@ private bool CallVerifyWithECDsa(byte[] message, ECPoint pub, byte[] signature, return engine.ResultStack.Pop().GetBoolean(); } } + + [TestMethod] + public void TestVerifyWithEd25519() + { + byte[] privateKey = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".HexToBytes(); + byte[] publicKey = "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".HexToBytes(); + byte[] message = Array.Empty(); + byte[] signature = ("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155" + + "5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b").HexToBytes(); + + // Verify using Ed25519 directly + Ed25519.Verify(publicKey, message, signature).Should().BeTrue(); + + // Verify using CryptoLib.VerifyWithEd25519 + CallVerifyWithEd25519(message, publicKey, signature).Should().BeTrue(); + + // Test with a different message + byte[] differentMessage = Encoding.UTF8.GetBytes("Different message"); + CallVerifyWithEd25519(differentMessage, publicKey, signature).Should().BeFalse(); + + // Test with an invalid signature + byte[] invalidSignature = new byte[signature.Length]; + Array.Copy(signature, invalidSignature, signature.Length); + invalidSignature[0] ^= 0x01; // Flip one bit + CallVerifyWithEd25519(message, publicKey, invalidSignature).Should().BeFalse(); + + // Test with an invalid public key + byte[] invalidPublicKey = new byte[publicKey.Length]; + Array.Copy(publicKey, invalidPublicKey, publicKey.Length); + invalidPublicKey[0] ^= 0x01; // Flip one bit + CallVerifyWithEd25519(message, invalidPublicKey, signature).Should().BeFalse(); + } + + private bool CallVerifyWithEd25519(byte[] message, byte[] publicKey, byte[] signature) + { + var snapshot = TestBlockchain.GetTestSnapshotCache(); + using (ScriptBuilder script = new()) + { + script.EmitPush(signature); + script.EmitPush(publicKey); + script.EmitPush(message); + script.EmitPush(3); + script.Emit(OpCode.PACK); + script.EmitPush(CallFlags.All); + script.EmitPush("verifyWithEd25519"); + script.EmitPush(NativeContract.CryptoLib.Hash); + script.EmitSysCall(ApplicationEngine.System_Contract_Call); + + using var engine = ApplicationEngine.Create(TriggerType.Application, null, snapshot, settings: TestBlockchain.TheNeoSystem.Settings); + engine.LoadScript(script.ToArray()); + Assert.AreEqual(VMState.HALT, engine.Execute()); + return engine.ResultStack.Pop().GetBoolean(); + } + } } } diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index f742e11471..812b36fd6c 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -43,7 +43,7 @@ public void TestSetup() { {"ContractManagement", """{"id":-1,"updatecounter":0,"hash":"0xfffdc93764dbaddd97c48f252a53ea4643faa3fd","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"ContractManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Array","offset":0,"safe":false},{"name":"deploy","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Array","offset":7,"safe":false},{"name":"destroy","parameters":[],"returntype":"Void","offset":14,"safe":false},{"name":"getContract","parameters":[{"name":"hash","type":"Hash160"}],"returntype":"Array","offset":21,"safe":true},{"name":"getContractById","parameters":[{"name":"id","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getContractHashes","parameters":[],"returntype":"InteropInterface","offset":35,"safe":true},{"name":"getMinimumDeploymentFee","parameters":[],"returntype":"Integer","offset":42,"safe":true},{"name":"hasMethod","parameters":[{"name":"hash","type":"Hash160"},{"name":"method","type":"String"},{"name":"pcount","type":"Integer"}],"returntype":"Boolean","offset":49,"safe":true},{"name":"setMinimumDeploymentFee","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":56,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"}],"returntype":"Void","offset":63,"safe":false},{"name":"update","parameters":[{"name":"nefFile","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","offset":70,"safe":false}],"events":[{"name":"Deploy","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Update","parameters":[{"name":"Hash","type":"Hash160"}]},{"name":"Destroy","parameters":[{"name":"Hash","type":"Hash160"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}""" }, {"StdLib", """{"id":-2,"updatecounter":0,"hash":"0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2681632925},"manifest":{"name":"StdLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"atoi","parameters":[{"name":"value","type":"String"}],"returntype":"Integer","offset":0,"safe":true},{"name":"atoi","parameters":[{"name":"value","type":"String"},{"name":"base","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"base58CheckDecode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":14,"safe":true},{"name":"base58CheckEncode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":21,"safe":true},{"name":"base58Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":28,"safe":true},{"name":"base58Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":35,"safe":true},{"name":"base64Decode","parameters":[{"name":"s","type":"String"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"base64Encode","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"String","offset":49,"safe":true},{"name":"base64UrlDecode","parameters":[{"name":"s","type":"String"}],"returntype":"String","offset":56,"safe":true},{"name":"base64UrlEncode","parameters":[{"name":"data","type":"String"}],"returntype":"String","offset":63,"safe":true},{"name":"deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"Any","offset":70,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"}],"returntype":"String","offset":77,"safe":true},{"name":"itoa","parameters":[{"name":"value","type":"Integer"},{"name":"base","type":"Integer"}],"returntype":"String","offset":84,"safe":true},{"name":"jsonDeserialize","parameters":[{"name":"json","type":"ByteArray"}],"returntype":"Any","offset":91,"safe":true},{"name":"jsonSerialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":98,"safe":true},{"name":"memoryCompare","parameters":[{"name":"str1","type":"ByteArray"},{"name":"str2","type":"ByteArray"}],"returntype":"Integer","offset":105,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"}],"returntype":"Integer","offset":112,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"}],"returntype":"Integer","offset":119,"safe":true},{"name":"memorySearch","parameters":[{"name":"mem","type":"ByteArray"},{"name":"value","type":"ByteArray"},{"name":"start","type":"Integer"},{"name":"backward","type":"Boolean"}],"returntype":"Integer","offset":126,"safe":true},{"name":"serialize","parameters":[{"name":"item","type":"Any"}],"returntype":"ByteArray","offset":133,"safe":true},{"name":"strLen","parameters":[{"name":"str","type":"String"}],"returntype":"Integer","offset":140,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"}],"returntype":"Array","offset":147,"safe":true},{"name":"stringSplit","parameters":[{"name":"str","type":"String"},{"name":"separator","type":"String"},{"name":"removeEmptyEntries","type":"Boolean"}],"returntype":"Array","offset":154,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, - {"CryptoLib", """{"id":-3,"updatecounter":0,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"bls12381Add","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","offset":0,"safe":true},{"name":"bls12381Deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","offset":7,"safe":true},{"name":"bls12381Equal","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","offset":14,"safe":true},{"name":"bls12381Mul","parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"bls12381Pairing","parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","offset":28,"safe":true},{"name":"bls12381Serialize","parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","offset":35,"safe":true},{"name":"keccak256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"murmur32","parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","offset":49,"safe":true},{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":63,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","offset":70,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, + {"CryptoLib", """{"id":-3,"updatecounter":0,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":3581846399},"manifest":{"name":"CryptoLib","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"bls12381Add","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","offset":0,"safe":true},{"name":"bls12381Deserialize","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","offset":7,"safe":true},{"name":"bls12381Equal","parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","offset":14,"safe":true},{"name":"bls12381Mul","parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"bls12381Pairing","parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","offset":28,"safe":true},{"name":"bls12381Serialize","parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","offset":35,"safe":true},{"name":"keccak256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":42,"safe":true},{"name":"murmur32","parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","offset":49,"safe":true},{"name":"ripemd160","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":56,"safe":true},{"name":"sha256","parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","offset":63,"safe":true},{"name":"verifyWithECDsa","parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","offset":70,"safe":true},{"name":"verifyWithEd25519","parameters":[{"name":"message","type":"ByteArray"},{"name":"publicKey","type":"ByteArray"},{"name":"signature","type":"ByteArray"}],"returntype":"Boolean","offset":77,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"LedgerContract", """{"id":-4,"updatecounter":0,"hash":"0xda65b600f7124ce6c79950c1772a36403104f2be","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"LedgerContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"currentHash","parameters":[],"returntype":"Hash256","offset":0,"safe":true},{"name":"currentIndex","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlock","parameters":[{"name":"indexOrHash","type":"ByteArray"}],"returntype":"Array","offset":14,"safe":true},{"name":"getTransaction","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":21,"safe":true},{"name":"getTransactionFromBlock","parameters":[{"name":"blockIndexOrHash","type":"ByteArray"},{"name":"txIndex","type":"Integer"}],"returntype":"Array","offset":28,"safe":true},{"name":"getTransactionHeight","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":35,"safe":true},{"name":"getTransactionSigners","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Array","offset":42,"safe":true},{"name":"getTransactionVMState","parameters":[{"name":"hash","type":"Hash256"}],"returntype":"Integer","offset":49,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"NeoToken", """{"id":-5,"updatecounter":0,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1991619121},"manifest":{"name":"NeoToken","groups":[],"features":{},"supportedstandards":["NEP-17","NEP-27"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"getAccountState","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","offset":14,"safe":true},{"name":"getAllCandidates","parameters":[],"returntype":"InteropInterface","offset":21,"safe":true},{"name":"getCandidateVote","parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","offset":28,"safe":true},{"name":"getCandidates","parameters":[],"returntype":"Array","offset":35,"safe":true},{"name":"getCommittee","parameters":[],"returntype":"Array","offset":42,"safe":true},{"name":"getCommitteeAddress","parameters":[],"returntype":"Hash160","offset":49,"safe":true},{"name":"getGasPerBlock","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"getNextBlockValidators","parameters":[],"returntype":"Array","offset":63,"safe":true},{"name":"getRegisterPrice","parameters":[],"returntype":"Integer","offset":70,"safe":true},{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","offset":77,"safe":false},{"name":"registerCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":84,"safe":false},{"name":"setGasPerBlock","parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"setRegisterPrice","parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","offset":98,"safe":false},{"name":"symbol","parameters":[],"returntype":"String","offset":105,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":112,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":119,"safe":false},{"name":"unclaimedGas","parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","offset":126,"safe":true},{"name":"unregisterCandidate","parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","offset":133,"safe":false},{"name":"vote","parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","offset":140,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, {"GasToken", """{"id":-6,"updatecounter":0,"hash":"0xd2a4cff31913016155e38e474a2c06d08be276cf","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"GasToken","groups":[],"features":{},"supportedstandards":["NEP-17"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"decimals","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"symbol","parameters":[],"returntype":"String","offset":14,"safe":true},{"name":"totalSupply","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","offset":28,"safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}, @@ -108,7 +108,7 @@ public void TestGetContract() [TestMethod] public void TestIsInitializeBlock() { - string json = UT_ProtocolSettings.CreateHFSettings("\"HF_Cockatrice\": 20"); + string json = UT_ProtocolSettings.CreateHFSettings("\"HF_Cockatrice\": 20,\n\"HF_Domovoi\": 30,\n\"HF_Echidna\": 40"); var file = Path.GetTempFileName(); File.WriteAllText(file, json);