From 6dd0c37a1ab748a9cae0a52608535c4c4cdea188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Thu, 26 Nov 2020 04:02:49 -0600 Subject: [PATCH 01/17] [RpcServer] Querying contracts by ID/name (#378) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixed-bug-1021 * Update src/RpcServer/RpcServer.SmartContract.cs * 😂 * draft * draft * update * fixed bug with decimal of GAS consumed in invokefunction/invokescript * remove modify of invokescript * Querying contracts by ID/name, server side * update * Enable using native.name for search Enable using native.name for search * Using keyword instead of addressOrScriptHash * revert * _initialize * split * update * Update exception message in ApplicationLog * Update src/ApplicationLogs/LogReader.cs Co-authored-by: Luchuan * update * a * More fix * fix * Fixed UT * Simplify Code * Simplify Code 2 * Update RpcServer * update Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan --- src/ApplicationLogs/LogReader.cs | 13 +++---- src/RpcClient/Models/RpcApplicationLog.cs | 6 ++-- src/RpcClient/Models/RpcBlock.cs | 2 +- src/RpcClient/Models/RpcInvokeResult.cs | 4 ++- src/RpcClient/Models/RpcTransaction.cs | 2 +- src/RpcClient/TransactionManagerFactory.cs | 3 +- src/RpcClient/Utility.cs | 19 ++++++++-- src/RpcServer/RpcServer.Blockchain.cs | 17 +++++++-- src/RpcServer/RpcServer.SmartContract.cs | 2 +- src/RpcServer/RpcServer.Wallet.cs | 2 +- src/RpcServer/RpcServer.cs | 2 +- src/RpcServer/Utility.cs | 28 +++++++++++++++ tests/Neo.Network.RPC.Tests/RpcTestCases.json | 36 +++++++++---------- .../UT_TransactionManager.cs | 2 +- 14 files changed, 99 insertions(+), 39 deletions(-) create mode 100644 src/RpcServer/Utility.cs diff --git a/src/ApplicationLogs/LogReader.cs b/src/ApplicationLogs/LogReader.cs index 90c772691..f68ebaede 100644 --- a/src/ApplicationLogs/LogReader.cs +++ b/src/ApplicationLogs/LogReader.cs @@ -4,6 +4,7 @@ using Neo.Ledger; using Neo.Persistence; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.VM; using System; using System.Collections.Generic; @@ -40,7 +41,7 @@ public JObject GetApplicationLog(JArray _params) if (value is null) throw new RpcException(-100, "Unknown transaction/blockhash"); - var raw = JObject.Parse(Utility.StrictUTF8.GetString(value)); + var raw = JObject.Parse(Neo.Utility.StrictUTF8.GetString(value)); //Additional optional "trigger" parameter to getapplicationlog for clients to be able to get just one execution result for a block. if (_params.Count >= 2 && Enum.TryParse(_params[1].AsString(), true, out TriggerType trigger)) { @@ -66,7 +67,7 @@ public static JObject TxLogToJson(Blockchain.ApplicationExecuted appExec) trigger["trigger"] = appExec.Trigger; trigger["vmstate"] = appExec.VMState; trigger["exception"] = GetExceptionMessage(appExec.Exception); - trigger["gasconsumed"] = appExec.GasConsumed.ToString(); + trigger["gasconsumed"] = new BigDecimal(appExec.GasConsumed, NativeContract.GAS.Decimals).ToString(); try { trigger["stack"] = appExec.Stack.Select(q => q.ToJson()).ToArray(); @@ -109,7 +110,7 @@ public static JObject BlockLogToJson(StoreView snapshot, IReadOnlyList q.ToJson()).ToArray(); @@ -150,14 +151,14 @@ public void OnPersist(StoreView snapshot, IReadOnlyList p.Transaction != null)) { var txJson = TxLogToJson(appExec); - writeBatch.Put(appExec.Transaction.Hash.ToArray(), Utility.StrictUTF8.GetBytes(txJson.ToString())); + writeBatch.Put(appExec.Transaction.Hash.ToArray(), Neo.Utility.StrictUTF8.GetBytes(txJson.ToString())); } //processing log for block var blockJson = BlockLogToJson(snapshot, applicationExecutedList); if (blockJson != null) { - writeBatch.Put(snapshot.PersistingBlock.Hash.ToArray(), Utility.StrictUTF8.GetBytes(blockJson.ToString())); + writeBatch.Put(snapshot.PersistingBlock.Hash.ToArray(), Neo.Utility.StrictUTF8.GetBytes(blockJson.ToString())); } db.Write(WriteOptions.Default, writeBatch); } @@ -173,7 +174,7 @@ public bool ShouldThrowExceptionFromCommit(Exception ex) static string GetExceptionMessage(Exception exception) { - if (exception == null) return "Engine faulted."; + if (exception == null) return null; if (exception.InnerException != null) { diff --git a/src/RpcClient/Models/RpcApplicationLog.cs b/src/RpcClient/Models/RpcApplicationLog.cs index cfdfbcc7e..42fa20833 100644 --- a/src/RpcClient/Models/RpcApplicationLog.cs +++ b/src/RpcClient/Models/RpcApplicationLog.cs @@ -1,7 +1,9 @@ using Neo.IO.Json; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.VM; using Neo.VM.Types; +using System; using System.Collections.Generic; using System.Linq; @@ -54,7 +56,7 @@ public JObject ToJson() JObject json = new JObject(); json["trigger"] = Trigger; json["vmstate"] = VMState; - json["gasconsumed"] = GasConsumed.ToString(); + json["gasconsumed"] = new BigDecimal(GasConsumed, NativeContract.GAS.Decimals).ToString(); json["stack"] = Stack.Select(q => q.ToJson()).ToArray(); json["notifications"] = Notifications.Select(q => q.ToJson()).ToArray(); return json; @@ -66,7 +68,7 @@ public static Execution FromJson(JObject json) { Trigger = json["trigger"].TryGetEnum(), VMState = json["vmstate"].TryGetEnum(), - GasConsumed = long.Parse(json["gasconsumed"].AsString()), + GasConsumed = (long)BigDecimal.Parse(json["gasconsumed"].AsString(), NativeContract.GAS.Decimals).Value, Stack = ((JArray)json["stack"]).Select(p => Utility.StackItemFromJson(p)).ToList(), Notifications = ((JArray)json["notifications"]).Select(p => RpcNotifyEventArgs.FromJson(p)).ToList() }; diff --git a/src/RpcClient/Models/RpcBlock.cs b/src/RpcClient/Models/RpcBlock.cs index 24687812f..8d706ca74 100644 --- a/src/RpcClient/Models/RpcBlock.cs +++ b/src/RpcClient/Models/RpcBlock.cs @@ -13,7 +13,7 @@ public class RpcBlock public JObject ToJson() { - JObject json = Block.ToJson(); + JObject json = Utility.BlockToJson(Block); json["confirmations"] = Confirmations; json["nextblockhash"] = NextBlockHash?.ToString(); return json; diff --git a/src/RpcClient/Models/RpcInvokeResult.cs b/src/RpcClient/Models/RpcInvokeResult.cs index e57310894..8ef6e50a6 100644 --- a/src/RpcClient/Models/RpcInvokeResult.cs +++ b/src/RpcClient/Models/RpcInvokeResult.cs @@ -1,8 +1,10 @@ using Neo.IO.Json; +using Neo.SmartContract.Native; using Neo.VM; using Neo.VM.Types; using System; using System.Linq; +using System.Numerics; namespace Neo.Network.RPC.Models { @@ -25,7 +27,7 @@ public JObject ToJson() JObject json = new JObject(); json["script"] = Script; json["state"] = State; - json["gasconsumed"] = GasConsumed; + json["gasconsumed"] = GasConsumed.ToString(); if (!string.IsNullOrEmpty(Exception)) json["exception"] = Exception; try diff --git a/src/RpcClient/Models/RpcTransaction.cs b/src/RpcClient/Models/RpcTransaction.cs index 74aae5566..2ccd2687b 100644 --- a/src/RpcClient/Models/RpcTransaction.cs +++ b/src/RpcClient/Models/RpcTransaction.cs @@ -18,7 +18,7 @@ public class RpcTransaction public JObject ToJson() { - JObject json = Transaction.ToJson(); + JObject json = Utility.TransactionToJson(Transaction); if (Confirmations != null) { json["blockhash"] = BlockHash.ToString(); diff --git a/src/RpcClient/TransactionManagerFactory.cs b/src/RpcClient/TransactionManagerFactory.cs index 0f7277a2c..92e50b310 100644 --- a/src/RpcClient/TransactionManagerFactory.cs +++ b/src/RpcClient/TransactionManagerFactory.cs @@ -1,5 +1,6 @@ using Neo.Network.P2P.Payloads; using Neo.Network.RPC.Models; +using Neo.SmartContract.Native; using System; using System.Threading.Tasks; @@ -47,7 +48,7 @@ public async Task MakeTransactionAsync(byte[] script, Signer Script = script, Signers = signers ?? Array.Empty(), ValidUntilBlock = blockCount - 1 + Transaction.MaxValidUntilBlockIncrement, - SystemFee = long.Parse(invokeResult.GasConsumed), + SystemFee = (long)BigDecimal.Parse(invokeResult.GasConsumed.ToString(), NativeContract.GAS.Decimals).Value, Attributes = attributes ?? Array.Empty(), }; diff --git a/src/RpcClient/Utility.cs b/src/RpcClient/Utility.cs index dae537f2b..2da05a1b4 100644 --- a/src/RpcClient/Utility.cs +++ b/src/RpcClient/Utility.cs @@ -129,6 +129,13 @@ public static Block BlockFromJson(JObject json) return block; } + public static JObject BlockToJson(Block block) + { + JObject json = block.ToJson(); + json["tx"] = block.Transactions.Select(p => TransactionToJson(p)).ToArray(); + return json; + } + public static void FromJson(this BlockBase block, JObject json) { block.Version = (uint)json["version"].AsNumber(); @@ -147,8 +154,8 @@ public static Transaction TransactionFromJson(JObject json) Version = byte.Parse(json["version"].AsString()), Nonce = uint.Parse(json["nonce"].AsString()), Signers = ((JArray)json["signers"]).Select(p => SignerFromJson(p)).ToArray(), - SystemFee = long.Parse(json["sysfee"].AsString()), - NetworkFee = long.Parse(json["netfee"].AsString()), + SystemFee = (long)BigDecimal.Parse(json["sysfee"].AsString(), NativeContract.GAS.Decimals).Value, + NetworkFee = (long)BigDecimal.Parse(json["netfee"].AsString(), NativeContract.GAS.Decimals).Value, ValidUntilBlock = uint.Parse(json["validuntilblock"].AsString()), Attributes = ((JArray)json["attributes"]).Select(p => TransactionAttributeFromJson(p)).ToArray(), Script = Convert.FromBase64String(json["script"].AsString()), @@ -156,6 +163,14 @@ public static Transaction TransactionFromJson(JObject json) }; } + public static JObject TransactionToJson(Transaction tx) + { + JObject json = tx.ToJson(); + json["sysfee"] = new BigDecimal(tx.SystemFee, NativeContract.GAS.Decimals).ToString(); + json["netfee"] = new BigDecimal(tx.NetworkFee, NativeContract.GAS.Decimals).ToString(); + return json; + } + public static Header HeaderFromJson(JObject json) { Header header = new Header(); diff --git a/src/RpcServer/RpcServer.Blockchain.cs b/src/RpcServer/RpcServer.Blockchain.cs index 4ef57fc18..137d484e4 100644 --- a/src/RpcServer/RpcServer.Blockchain.cs +++ b/src/RpcServer/RpcServer.Blockchain.cs @@ -41,7 +41,7 @@ protected virtual JObject GetBlock(JArray _params) throw new RpcException(-100, "Unknown block"); if (verbose) { - JObject json = block.ToJson(); + JObject json = Utility.BlockToJson(block); json["confirmations"] = Blockchain.Singleton.Height - block.Index + 1; UInt256 hash = Blockchain.Singleton.GetNextBlockHash(block.Hash); if (hash != null) @@ -103,11 +103,22 @@ protected virtual JObject GetBlockHeader(JArray _params) [RpcMethod] protected virtual JObject GetContractState(JArray _params) { - UInt160 script_hash = UInt160.Parse(_params[0].AsString()); + UInt160 script_hash = ToScriptHash(_params[0].AsString()); ContractState contract = Blockchain.Singleton.View.Contracts.TryGet(script_hash); return contract?.ToJson() ?? throw new RpcException(-100, "Unknown contract"); } + private static UInt160 ToScriptHash(string keyword) + { + foreach (var native in NativeContract.Contracts) + { + if (keyword.Equals(native.Name, StringComparison.InvariantCultureIgnoreCase) || keyword == native.Id.ToString()) + return native.Hash; + } + + return UInt160.Parse(keyword); + } + [RpcMethod] protected virtual JObject GetRawMemPool(JArray _params) { @@ -135,7 +146,7 @@ protected virtual JObject GetRawTransaction(JArray _params) throw new RpcException(-100, "Unknown transaction"); if (verbose) { - JObject json = tx.ToJson(); + JObject json = Utility.TransactionToJson(tx); TransactionState txState = Blockchain.Singleton.View.Transactions.TryGet(hash); if (txState != null) { diff --git a/src/RpcServer/RpcServer.SmartContract.cs b/src/RpcServer/RpcServer.SmartContract.cs index 4fed465ad..a48ede69a 100644 --- a/src/RpcServer/RpcServer.SmartContract.cs +++ b/src/RpcServer/RpcServer.SmartContract.cs @@ -73,7 +73,7 @@ private JObject GetInvokeResult(byte[] script, Signers signers = null) JObject json = new JObject(); json["script"] = Convert.ToBase64String(script); json["state"] = engine.State; - json["gasconsumed"] = engine.GasConsumed.ToString(); + json["gasconsumed"] = new BigDecimal(engine.GasConsumed, NativeContract.GAS.Decimals).ToString(); json["exception"] = GetExceptionMessage(engine.FaultException); try { diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index 2256c0a6d..214df1bee 100644 --- a/src/RpcServer/RpcServer.Wallet.cs +++ b/src/RpcServer/RpcServer.Wallet.cs @@ -332,7 +332,7 @@ private JObject SignAndRelay(Transaction tx) { tx.Witnesses = context.GetWitnesses(); system.Blockchain.Tell(tx); - return tx.ToJson(); + return Utility.TransactionToJson(tx); } else { diff --git a/src/RpcServer/RpcServer.cs b/src/RpcServer/RpcServer.cs index a17d51d22..b20a22caf 100644 --- a/src/RpcServer/RpcServer.cs +++ b/src/RpcServer/RpcServer.cs @@ -107,7 +107,7 @@ public void StartRpcServer() { if (err != SslPolicyErrors.None) return false; - X509Certificate2 authority = chain.ChainElements[chain.ChainElements.Count - 1].Certificate; + X509Certificate2 authority = chain.ChainElements[^1].Certificate; return settings.TrustedAuthorities.Contains(authority.Thumbprint); }; }); diff --git a/src/RpcServer/Utility.cs b/src/RpcServer/Utility.cs new file mode 100644 index 000000000..0ac336351 --- /dev/null +++ b/src/RpcServer/Utility.cs @@ -0,0 +1,28 @@ +using Neo.IO.Json; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract.Native; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Neo.Plugins +{ + public static class Utility + { + public static JObject BlockToJson(Block block) + { + JObject json = block.ToJson(); + json["tx"] = block.Transactions.Select(p => TransactionToJson(p)).ToArray(); + return json; + } + + public static JObject TransactionToJson(Transaction tx) + { + JObject json = tx.ToJson(); + json["sysfee"] = new BigDecimal(tx.SystemFee, NativeContract.GAS.Decimals).ToString(); + json["netfee"] = new BigDecimal(tx.NetworkFee, NativeContract.GAS.Decimals).ToString(); + return json; + } + } +} diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index 5de1433b6..8833fed6b 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -96,8 +96,8 @@ "version": 0, "nonce": 631973574, "sender": "NikvsLcNP1jWhrFPrfS3n4spEASgdNYTG2", - "sysfee": "9007990", - "netfee": "1248450", + "sysfee": "0.0900799", + "netfee": "0.0124845", "validuntilblock": 2102405, "signers": [ { @@ -157,8 +157,8 @@ "version": 0, "nonce": 631973574, "sender": "NikvsLcNP1jWhrFPrfS3n4spEASgdNYTG2", - "sysfee": "9007990", - "netfee": "1248450", + "sysfee": "0.0900799", + "netfee": "0.0124845", "validuntilblock": 2102405, "signers": [ { @@ -520,8 +520,8 @@ "version": 0, "nonce": 969006668, "sender": "NikvsLcNP1jWhrFPrfS3n4spEASgdNYTG2", - "sysfee": "100000000", - "netfee": "1272390", + "sysfee": "1", + "netfee": "0.0127239", "validuntilblock": 2104625, "signers": [ { @@ -731,7 +731,7 @@ "result": { "script": "0c1426ae7c6c9861ec418468c1f0fdc4a7f2963eb89111c00c0962616c616e63654f660c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b52", "state": "HALT", - "gasconsumed": "2007570", + "gasconsumed": "0.0200757", "stack": [ { "type": "Integer", @@ -756,7 +756,7 @@ "result": { "script": "EMMMBG5hbWUMFDt9NxHG8Mz5sdypA9G/odiW8SOMQWJ9W1IQwwwGc3ltYm9sDBQ7fTcRxvDM+bHcqQPRv6HYlvEjjEFifVtSEMMMCGRlY2ltYWxzDBQ7fTcRxvDM+bHcqQPRv6HYlvEjjEFifVtSEMMMC3RvdGFsU3VwcGx5DBQ7fTcRxvDM+bHcqQPRv6HYlvEjjEFifVtS", "state": "HALT", - "gasconsumed": "5061560", + "gasconsumed": "0.0506156", "stack": [ { "type": "Array", @@ -942,7 +942,7 @@ "result": { "script": "EMMMCGRlY2ltYWxzDBQ7fTcRxvDM+bHcqQPRv6HYlvEjjEFifVtS", "state": "HALT", - "gasconsumed": "5061560", + "gasconsumed": "0.0506156", "stack": [ { "type": "Integer", @@ -1074,8 +1074,8 @@ "version": 0, "nonce": 1553700339, "sender": "NVVwFw6XyhtRCFQ8SpUTMdPyYt4Vd9A1XQ", - "sysfee": "100000000", - "netfee": "1272390", + "sysfee": "1", + "netfee": "0.0127239", "validuntilblock": 2105487, "attributes": [], "cosigners": [ @@ -1125,8 +1125,8 @@ "version": 0, "nonce": 34429660, "sender": "NUMK37TV9yYKbJr1Gufh74nZiM623eBLqX", - "sysfee": "100000000", - "netfee": "2483780", + "sysfee": "1", + "netfee": "0.0248378", "validuntilblock": 2105494, "attributes": [], "cosigners": [ @@ -1170,8 +1170,8 @@ "version": 0, "nonce": 330056065, "sender": "NUMK37TV9yYKbJr1Gufh74nZiM623eBLqX", - "sysfee": "100000000", - "netfee": "2381780", + "sysfee": "1", + "netfee": "0.0238178", "validuntilblock": 2105500, "attributes": [], "cosigners": [ @@ -1213,7 +1213,7 @@ { "trigger": "OnPersist", "vmstate": "HALT", - "gasconsumed": "2031260", + "gasconsumed": "0.0203126", "stack": [], "notifications": [ { @@ -1261,7 +1261,7 @@ { "trigger": "PostPersist", "vmstate": "HALT", - "gasconsumed": "2031260", + "gasconsumed": "0.0203126", "stack": [], "notifications": [ { @@ -1307,7 +1307,7 @@ { "trigger": "OnPersist", "vmstate": "HALT", - "gasconsumed": "2031260", + "gasconsumed": "0.0203126", "stack": [], "notifications": [ { diff --git a/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs b/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs index 32744c2e2..bc740fd1c 100644 --- a/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs +++ b/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs @@ -164,7 +164,7 @@ await txManager Assert.IsTrue(Crypto.VerifySignature(tx.GetHashData(), signature, keyPair1.PublicKey)); // verify network fee and system fee Assert.AreEqual(100000000/*Mock*/, tx.NetworkFee); - Assert.AreEqual(100, tx.SystemFee); + Assert.AreEqual(10000000000, tx.SystemFee); // duplicate sign should not add new witness await txManager.AddSignature(keyPair1).SignAsync(); From c7d19614491ffc0953ddf247fae0514c3dbbee53 Mon Sep 17 00:00:00 2001 From: ZhangTao Date: Fri, 27 Nov 2020 15:26:35 +0800 Subject: [PATCH 02/17] MPT in StateService from core (#410) --- neo-modules.sln | 16 +- src/StateService/MPT/BranchNode.cs | 35 ++ src/StateService/MPT/ExtensionNode.cs | 30 ++ src/StateService/MPT/HashNode.cs | 41 +++ src/StateService/MPT/LeafNode.cs | 36 ++ src/StateService/MPT/MPTNode.cs | 62 ++++ src/StateService/MPT/MPTNodeType.cs | 16 + src/StateService/MPT/MPTTrie.Delete.cs | 120 +++++++ src/StateService/MPT/MPTTrie.Find.cs | 110 ++++++ src/StateService/MPT/MPTTrie.Get.cs | 61 ++++ src/StateService/MPT/MPTTrie.Proof.cs | 73 ++++ src/StateService/MPT/MPTTrie.Put.cs | 158 +++++++++ src/StateService/MPT/MPTTrie.cs | 58 ++++ src/StateService/StateService.csproj | 9 + .../MPT/UT_MPTNode.cs | 30 ++ .../MPT/UT_MPTTrie.cs | 320 ++++++++++++++++++ .../Neo.Plugins.StateService.Tests.csproj | 16 + 17 files changed, 1190 insertions(+), 1 deletion(-) create mode 100644 src/StateService/MPT/BranchNode.cs create mode 100644 src/StateService/MPT/ExtensionNode.cs create mode 100644 src/StateService/MPT/HashNode.cs create mode 100644 src/StateService/MPT/LeafNode.cs create mode 100644 src/StateService/MPT/MPTNode.cs create mode 100644 src/StateService/MPT/MPTNodeType.cs create mode 100644 src/StateService/MPT/MPTTrie.Delete.cs create mode 100644 src/StateService/MPT/MPTTrie.Find.cs create mode 100644 src/StateService/MPT/MPTTrie.Get.cs create mode 100644 src/StateService/MPT/MPTTrie.Proof.cs create mode 100644 src/StateService/MPT/MPTTrie.Put.cs create mode 100644 src/StateService/MPT/MPTTrie.cs create mode 100644 src/StateService/StateService.csproj create mode 100644 tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTNode.cs create mode 100644 tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs create mode 100644 tests/Neo.Plugins.StateService.Tests/Neo.Plugins.StateService.Tests.csproj diff --git a/neo-modules.sln b/neo-modules.sln index 763a89627..24f303eb4 100644 --- a/neo-modules.sln +++ b/neo-modules.sln @@ -1,4 +1,4 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 @@ -24,6 +24,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Network.RPC.Tests", "te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Plugins.Storage.Tests", "tests\Neo.Plugins.Storage.Tests\Neo.Plugins.Storage.Tests.csproj", "{9E7EA895-302A-4C0C-BA9B-54F9A67AD75C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StateService", "src\StateService\StateService.csproj", "{A0F4A66F-6F87-4B99-B8BE-A779BC002F47}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neo.Plugins.StateService.Tests", "tests\Neo.Plugins.StateService.Tests\Neo.Plugins.StateService.Tests.csproj", "{149822EC-4E0C-425F-A032-4196B615BFEB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -66,6 +70,14 @@ Global {9E7EA895-302A-4C0C-BA9B-54F9A67AD75C}.Debug|Any CPU.Build.0 = Debug|Any CPU {9E7EA895-302A-4C0C-BA9B-54F9A67AD75C}.Release|Any CPU.ActiveCfg = Release|Any CPU {9E7EA895-302A-4C0C-BA9B-54F9A67AD75C}.Release|Any CPU.Build.0 = Release|Any CPU + {A0F4A66F-6F87-4B99-B8BE-A779BC002F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0F4A66F-6F87-4B99-B8BE-A779BC002F47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0F4A66F-6F87-4B99-B8BE-A779BC002F47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0F4A66F-6F87-4B99-B8BE-A779BC002F47}.Release|Any CPU.Build.0 = Release|Any CPU + {149822EC-4E0C-425F-A032-4196B615BFEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {149822EC-4E0C-425F-A032-4196B615BFEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {149822EC-4E0C-425F-A032-4196B615BFEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {149822EC-4E0C-425F-A032-4196B615BFEB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -80,6 +92,8 @@ Global {1403FFE9-4265-4269-8E3D-5A79EFD108CA} = {97E81C78-1637-481F-9485-DA1225E94C23} {D52460B3-AB5C-4D07-B400-9E7ADCB01FF5} = {59D802AB-C552-422A-B9C3-64D329FBCDCC} {9E7EA895-302A-4C0C-BA9B-54F9A67AD75C} = {59D802AB-C552-422A-B9C3-64D329FBCDCC} + {A0F4A66F-6F87-4B99-B8BE-A779BC002F47} = {97E81C78-1637-481F-9485-DA1225E94C23} + {149822EC-4E0C-425F-A032-4196B615BFEB} = {59D802AB-C552-422A-B9C3-64D329FBCDCC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {61D3ADE6-BBFC-402D-AB42-1C71C9F9EDE3} diff --git a/src/StateService/MPT/BranchNode.cs b/src/StateService/MPT/BranchNode.cs new file mode 100644 index 000000000..f729412b5 --- /dev/null +++ b/src/StateService/MPT/BranchNode.cs @@ -0,0 +1,35 @@ +using System.IO; + +namespace Neo.Plugins.MPT +{ + public class BranchNode : MPTNode + { + public const int ChildCount = 17; + public readonly MPTNode[] Children = new MPTNode[ChildCount]; + + protected override NodeType Type => NodeType.BranchNode; + + public BranchNode() + { + for (int i = 0; i < ChildCount; i++) + { + Children[i] = HashNode.EmptyNode; + } + } + + internal override void EncodeSpecific(BinaryWriter writer) + { + for (int i = 0; i < ChildCount; i++) + WriteHash(writer, Children[i].Hash); + } + + internal override void DecodeSpecific(BinaryReader reader) + { + for (int i = 0; i < ChildCount; i++) + { + Children[i] = new HashNode(); + Children[i].DecodeSpecific(reader); + } + } + } +} diff --git a/src/StateService/MPT/ExtensionNode.cs b/src/StateService/MPT/ExtensionNode.cs new file mode 100644 index 000000000..00f107240 --- /dev/null +++ b/src/StateService/MPT/ExtensionNode.cs @@ -0,0 +1,30 @@ +using Neo.IO; +using Neo.SmartContract; +using System.IO; + +namespace Neo.Plugins.MPT +{ + public class ExtensionNode : MPTNode + { + //max lenght when store StorageKey + public const int MaxKeyLength = (ApplicationEngine.MaxStorageValueSize + sizeof(int)) * 2; + + public byte[] Key; + public MPTNode Next; + + protected override NodeType Type => NodeType.ExtensionNode; + + internal override void EncodeSpecific(BinaryWriter writer) + { + writer.WriteVarBytes(Key); + WriteHash(writer, Next.Hash); + } + + internal override void DecodeSpecific(BinaryReader reader) + { + Key = reader.ReadVarBytes(MaxKeyLength); + Next = new HashNode(); + Next.DecodeSpecific(reader); + } + } +} diff --git a/src/StateService/MPT/HashNode.cs b/src/StateService/MPT/HashNode.cs new file mode 100644 index 000000000..7053f0a3b --- /dev/null +++ b/src/StateService/MPT/HashNode.cs @@ -0,0 +1,41 @@ +using Neo.IO; +using System; +using System.IO; + +namespace Neo.Plugins.MPT +{ + public class HashNode : MPTNode + { + private UInt256 hash; + + public override UInt256 Hash => hash; + protected override NodeType Type => NodeType.HashNode; + public bool IsEmpty => Hash is null; + public static HashNode EmptyNode { get; } = new HashNode(); + + public HashNode() + { + } + + public HashNode(UInt256 hash) + { + this.hash = hash; + } + + internal override void EncodeSpecific(BinaryWriter writer) + { + WriteHash(writer, hash); + } + + internal override void DecodeSpecific(BinaryReader reader) + { + byte[] buffer = reader.ReadVarBytes(UInt256.Length); + hash = buffer.Length switch + { + 0 => null, + UInt256.Length => new UInt256(buffer), + _ => throw new FormatException() + }; + } + } +} diff --git a/src/StateService/MPT/LeafNode.cs b/src/StateService/MPT/LeafNode.cs new file mode 100644 index 000000000..2a17ef4e2 --- /dev/null +++ b/src/StateService/MPT/LeafNode.cs @@ -0,0 +1,36 @@ +using Neo.IO; +using Neo.SmartContract; +using System; +using System.IO; + +namespace Neo.Plugins.MPT +{ + public class LeafNode : MPTNode + { + //the max size when store StorageItem + public const int MaxValueLength = 3 + ApplicationEngine.MaxStorageValueSize + sizeof(bool); + + public byte[] Value; + + protected override NodeType Type => NodeType.LeafNode; + + public LeafNode() + { + } + + public LeafNode(ReadOnlySpan value) + { + Value = value.ToArray(); + } + + internal override void EncodeSpecific(BinaryWriter writer) + { + writer.WriteVarBytes(Value); + } + + internal override void DecodeSpecific(BinaryReader reader) + { + Value = reader.ReadVarBytes(MaxValueLength); + } + } +} diff --git a/src/StateService/MPT/MPTNode.cs b/src/StateService/MPT/MPTNode.cs new file mode 100644 index 000000000..197031cdf --- /dev/null +++ b/src/StateService/MPT/MPTNode.cs @@ -0,0 +1,62 @@ +using Neo.Cryptography; +using Neo.IO; +using Neo.IO.Caching; +using System; +using System.IO; + +namespace Neo.Plugins.MPT +{ + public abstract class MPTNode + { + private UInt256 hash; + + public virtual UInt256 Hash => hash ??= new UInt256(Crypto.Hash256(Encode())); + protected abstract NodeType Type { get; } + + public void SetDirty() + { + hash = null; + } + + public byte[] Encode() + { + using MemoryStream ms = new MemoryStream(); + using BinaryWriter writer = new BinaryWriter(ms); + + writer.Write((byte)Type); + EncodeSpecific(writer); + writer.Flush(); + + return ms.ToArray(); + } + + internal abstract void EncodeSpecific(BinaryWriter writer); + + public static unsafe MPTNode Decode(ReadOnlySpan data) + { + if (data.IsEmpty) return null; + + fixed (byte* pointer = data) + { + using UnmanagedMemoryStream stream = new UnmanagedMemoryStream(pointer, data.Length); + using BinaryReader reader = new BinaryReader(stream); + + MPTNode n = (MPTNode)ReflectionCache.CreateInstance((NodeType)reader.ReadByte()); + if (n is null) throw new InvalidOperationException(); + + n.DecodeSpecific(reader); + return n; + } + } + + internal abstract void DecodeSpecific(BinaryReader reader); + + protected void WriteHash(BinaryWriter writer, UInt256 hash) + { + if (hash is null) + writer.Write((byte)0); + else + writer.WriteVarBytes(hash.ToArray()); + } + } +} diff --git a/src/StateService/MPT/MPTNodeType.cs b/src/StateService/MPT/MPTNodeType.cs new file mode 100644 index 000000000..05370a645 --- /dev/null +++ b/src/StateService/MPT/MPTNodeType.cs @@ -0,0 +1,16 @@ +using Neo.IO.Caching; + +namespace Neo.Plugins.MPT +{ + public enum NodeType : byte + { + [ReflectionCache(typeof(BranchNode))] + BranchNode = 0x00, + [ReflectionCache(typeof(ExtensionNode))] + ExtensionNode = 0x01, + [ReflectionCache(typeof(HashNode))] + HashNode = 0x02, + [ReflectionCache(typeof(LeafNode))] + LeafNode = 0x03, + } +} diff --git a/src/StateService/MPT/MPTTrie.Delete.cs b/src/StateService/MPT/MPTTrie.Delete.cs new file mode 100644 index 000000000..0470c2393 --- /dev/null +++ b/src/StateService/MPT/MPTTrie.Delete.cs @@ -0,0 +1,120 @@ +using Neo.IO; +using System; +using System.Collections.Generic; +using static Neo.Helper; + +namespace Neo.Plugins.MPT +{ + partial class MPTTrie + { + public bool Delete(TKey key) + { + var path = ToNibbles(key.ToArray()); + if (path.Length == 0) return false; + return TryDelete(ref root, path); + } + + private bool TryDelete(ref MPTNode node, ReadOnlySpan path) + { + switch (node) + { + case LeafNode _: + { + if (path.IsEmpty) + { + node = HashNode.EmptyNode; + return true; + } + return false; + } + case ExtensionNode extensionNode: + { + if (path.StartsWith(extensionNode.Key)) + { + var result = TryDelete(ref extensionNode.Next, path[extensionNode.Key.Length..]); + if (!result) return false; + if (extensionNode.Next is HashNode hashNode && hashNode.IsEmpty) + { + node = extensionNode.Next; + return true; + } + if (extensionNode.Next is ExtensionNode sn) + { + extensionNode.Key = Concat(extensionNode.Key, sn.Key); + extensionNode.Next = sn.Next; + } + extensionNode.SetDirty(); + PutToStore(extensionNode); + return true; + } + return false; + } + case BranchNode branchNode: + { + bool result; + if (path.IsEmpty) + { + result = TryDelete(ref branchNode.Children[BranchNode.ChildCount - 1], path); + } + else + { + result = TryDelete(ref branchNode.Children[path[0]], path[1..]); + } + if (!result) return false; + List childrenIndexes = new List(BranchNode.ChildCount); + for (int i = 0; i < BranchNode.ChildCount; i++) + { + if (branchNode.Children[i] is HashNode hn && hn.IsEmpty) continue; + childrenIndexes.Add((byte)i); + } + if (childrenIndexes.Count > 1) + { + branchNode.SetDirty(); + PutToStore(branchNode); + return true; + } + var lastChildIndex = childrenIndexes[0]; + var lastChild = branchNode.Children[lastChildIndex]; + if (lastChildIndex == BranchNode.ChildCount - 1) + { + node = lastChild; + return true; + } + if (lastChild is HashNode hashNode) + { + lastChild = Resolve(hashNode); + if (lastChild is null) return false; + } + if (lastChild is ExtensionNode exNode) + { + exNode.Key = Concat(childrenIndexes.ToArray(), exNode.Key); + exNode.SetDirty(); + PutToStore(exNode); + node = exNode; + return true; + } + node = new ExtensionNode() + { + Key = childrenIndexes.ToArray(), + Next = lastChild, + }; + PutToStore(node); + return true; + } + case HashNode hashNode: + { + if (hashNode.IsEmpty) + { + return true; + } + var newNode = Resolve(hashNode); + if (newNode is null) return false; + node = newNode; + return TryDelete(ref node, path); + } + default: + return false; + } + } + } +} diff --git a/src/StateService/MPT/MPTTrie.Find.cs b/src/StateService/MPT/MPTTrie.Find.cs new file mode 100644 index 000000000..6d072fd60 --- /dev/null +++ b/src/StateService/MPT/MPTTrie.Find.cs @@ -0,0 +1,110 @@ +using Neo.IO; +using System; +using System.Collections.Generic; +using System.Linq; +using static Neo.Helper; + +namespace Neo.Plugins.MPT +{ + partial class MPTTrie + { + private ReadOnlySpan Seek(ref MPTNode node, ReadOnlySpan path, out MPTNode start) + { + switch (node) + { + case LeafNode leafNode: + { + if (path.IsEmpty) + { + start = leafNode; + return ReadOnlySpan.Empty; + } + break; + } + case HashNode hashNode: + { + if (hashNode.IsEmpty) break; + var newNode = Resolve(hashNode); + if (newNode is null) break; + node = newNode; + return Seek(ref node, path, out start); + } + case BranchNode branchNode: + { + if (path.IsEmpty) + { + start = branchNode; + return ReadOnlySpan.Empty; + } + return Concat(path[..1], Seek(ref branchNode.Children[path[0]], path[1..], out start)); + } + case ExtensionNode extensionNode: + { + if (path.IsEmpty) + { + start = extensionNode.Next; + return extensionNode.Key; + } + if (path.StartsWith(extensionNode.Key)) + { + return Concat(extensionNode.Key, Seek(ref extensionNode.Next, path[extensionNode.Key.Length..], out start)); + } + if (extensionNode.Key.AsSpan().StartsWith(path)) + { + start = extensionNode.Next; + return extensionNode.Key; + } + break; + } + } + start = null; + return ReadOnlySpan.Empty; + } + + public IEnumerable<(TKey Key, TValue Value)> Find(ReadOnlySpan prefix) + { + var path = ToNibbles(prefix); + path = Seek(ref root, path, out MPTNode start).ToArray(); + return Travers(start, path) + .Select(p => (FromNibbles(p.Key).AsSerializable(), p.Value.AsSerializable())); + } + + private IEnumerable<(byte[] Key, byte[] Value)> Travers(MPTNode node, byte[] path) + { + if (node is null) yield break; + switch (node) + { + case LeafNode leafNode: + { + yield return (path, (byte[])leafNode.Value.Clone()); + break; + } + case HashNode hashNode: + { + if (hashNode.IsEmpty) break; + var newNode = Resolve(hashNode); + if (newNode is null) break; + node = newNode; + foreach (var item in Travers(node, path)) + yield return item; + break; + } + case BranchNode branchNode: + { + for (int i = 0; i < BranchNode.ChildCount; i++) + { + foreach (var item in Travers(branchNode.Children[i], i == BranchNode.ChildCount - 1 ? path : Concat(path, new byte[] { (byte)i }))) + yield return item; + } + break; + } + case ExtensionNode extensionNode: + { + foreach (var item in Travers(extensionNode.Next, Concat(path, extensionNode.Key))) + yield return item; + break; + } + } + } + } +} diff --git a/src/StateService/MPT/MPTTrie.Get.cs b/src/StateService/MPT/MPTTrie.Get.cs new file mode 100644 index 000000000..49dc6ed5d --- /dev/null +++ b/src/StateService/MPT/MPTTrie.Get.cs @@ -0,0 +1,61 @@ +using Neo.IO; +using System; + +namespace Neo.Plugins.MPT +{ + partial class MPTTrie + { + public TValue this[TKey key] + { + get + { + var path = ToNibbles(key.ToArray()); + if (path.Length == 0) return null; + var result = TryGet(ref root, path, out var value); + return result ? value.AsSerializable() : null; + } + } + + private bool TryGet(ref MPTNode node, ReadOnlySpan path, out ReadOnlySpan value) + { + switch (node) + { + case LeafNode leafNode: + { + if (path.IsEmpty) + { + value = leafNode.Value; + return true; + } + break; + } + case HashNode hashNode: + { + if (hashNode.IsEmpty) break; + var newNode = Resolve(hashNode); + if (newNode is null) break; + node = newNode; + return TryGet(ref node, path, out value); + } + case BranchNode branchNode: + { + if (path.IsEmpty) + { + return TryGet(ref branchNode.Children[BranchNode.ChildCount - 1], path, out value); + } + return TryGet(ref branchNode.Children[path[0]], path[1..], out value); + } + case ExtensionNode extensionNode: + { + if (path.StartsWith(extensionNode.Key)) + { + return TryGet(ref extensionNode.Next, path[extensionNode.Key.Length..], out value); + } + break; + } + } + value = default; + return false; + } + } +} diff --git a/src/StateService/MPT/MPTTrie.Proof.cs b/src/StateService/MPT/MPTTrie.Proof.cs new file mode 100644 index 000000000..f6e194bf8 --- /dev/null +++ b/src/StateService/MPT/MPTTrie.Proof.cs @@ -0,0 +1,73 @@ +using Neo.Cryptography; +using Neo.IO; +using Neo.Persistence; +using System; +using System.Collections.Generic; + +namespace Neo.Plugins.MPT +{ + partial class MPTTrie + { + public HashSet GetProof(TKey key) + { + var path = ToNibbles(key.ToArray()); + if (path.Length == 0) return null; + HashSet set = new HashSet(ByteArrayEqualityComparer.Default); + if (!GetProof(ref root, path, set)) return null; + return set; + } + + private bool GetProof(ref MPTNode node, ReadOnlySpan path, HashSet set) + { + switch (node) + { + case LeafNode leafNode: + { + if (path.IsEmpty) + { + set.Add(leafNode.Encode()); + return true; + } + break; + } + case HashNode hashNode: + { + if (hashNode.IsEmpty) break; + var newNode = Resolve(hashNode); + if (newNode is null) break; + node = newNode; + return GetProof(ref node, path, set); + } + case BranchNode branchNode: + { + set.Add(branchNode.Encode()); + if (path.IsEmpty) + { + return GetProof(ref branchNode.Children[BranchNode.ChildCount - 1], path, set); + } + return GetProof(ref branchNode.Children[path[0]], path[1..], set); + } + case ExtensionNode extensionNode: + { + if (path.StartsWith(extensionNode.Key)) + { + set.Add(extensionNode.Encode()); + return GetProof(ref extensionNode.Next, path[extensionNode.Key.Length..], set); + } + break; + } + } + return false; + } + + public static TValue VerifyProof(UInt256 root, TKey key, HashSet proof) + { + using var memoryStore = new MemoryStore(); + foreach (byte[] data in proof) + memoryStore.Put(Prefix, Crypto.Hash256(data), data); + using ISnapshot snapshot = memoryStore.GetSnapshot(); + var trie = new MPTTrie(snapshot, root); + return trie[key]; + } + } +} diff --git a/src/StateService/MPT/MPTTrie.Put.cs b/src/StateService/MPT/MPTTrie.Put.cs new file mode 100644 index 000000000..9ddaed16a --- /dev/null +++ b/src/StateService/MPT/MPTTrie.Put.cs @@ -0,0 +1,158 @@ +using Neo.IO; +using System; + +namespace Neo.Plugins.MPT +{ + partial class MPTTrie + { + private static ReadOnlySpan CommonPrefix(ReadOnlySpan a, ReadOnlySpan b) + { + var minLen = a.Length <= b.Length ? a.Length : b.Length; + int i = 0; + if (a.Length != 0 && b.Length != 0) + { + for (i = 0; i < minLen; i++) + { + if (a[i] != b[i]) break; + } + } + return a[..i]; + } + + public bool Put(TKey key, TValue value) + { + var path = ToNibbles(key.ToArray()); + var val = value.ToArray(); + if (path.Length == 0 || path.Length > ExtensionNode.MaxKeyLength) + return false; + if (val.Length > LeafNode.MaxValueLength) + return false; + if (val.Length == 0) + return TryDelete(ref root, path); + var n = new LeafNode(val); + return Put(ref root, path, n); + } + + private bool Put(ref MPTNode node, ReadOnlySpan path, MPTNode val) + { + switch (node) + { + case LeafNode leafNode: + { + if (val is LeafNode v) + { + if (path.IsEmpty) + { + node = v; + PutToStore(node); + return true; + } + var branch = new BranchNode(); + branch.Children[BranchNode.ChildCount - 1] = leafNode; + Put(ref branch.Children[path[0]], path[1..], v); + PutToStore(branch); + node = branch; + return true; + } + return false; + } + case ExtensionNode extensionNode: + { + if (path.StartsWith(extensionNode.Key)) + { + var result = Put(ref extensionNode.Next, path[extensionNode.Key.Length..], val); + if (result) + { + extensionNode.SetDirty(); + PutToStore(extensionNode); + } + return result; + } + var prefix = CommonPrefix(extensionNode.Key, path); + var pathRemain = path[prefix.Length..]; + var keyRemain = extensionNode.Key.AsSpan(prefix.Length); + var son = new BranchNode(); + MPTNode grandSon1 = HashNode.EmptyNode; + MPTNode grandSon2 = HashNode.EmptyNode; + + Put(ref grandSon1, keyRemain[1..], extensionNode.Next); + son.Children[keyRemain[0]] = grandSon1; + + if (pathRemain.IsEmpty) + { + Put(ref grandSon2, pathRemain, val); + son.Children[BranchNode.ChildCount - 1] = grandSon2; + } + else + { + Put(ref grandSon2, pathRemain[1..], val); + son.Children[pathRemain[0]] = grandSon2; + } + PutToStore(son); + if (prefix.Length > 0) + { + var exNode = new ExtensionNode() + { + Key = prefix.ToArray(), + Next = son, + }; + PutToStore(exNode); + node = exNode; + } + else + { + node = son; + } + return true; + } + case BranchNode branchNode: + { + bool result; + if (path.IsEmpty) + { + result = Put(ref branchNode.Children[BranchNode.ChildCount - 1], path, val); + } + else + { + result = Put(ref branchNode.Children[path[0]], path[1..], val); + } + if (result) + { + branchNode.SetDirty(); + PutToStore(branchNode); + } + return result; + } + case HashNode hashNode: + { + MPTNode newNode; + if (hashNode.IsEmpty) + { + if (path.IsEmpty) + { + newNode = val; + } + else + { + newNode = new ExtensionNode() + { + Key = path.ToArray(), + Next = val, + }; + PutToStore(newNode); + } + node = newNode; + if (val is LeafNode) PutToStore(val); + return true; + } + newNode = Resolve(hashNode); + if (newNode is null) return false; + node = newNode; + return Put(ref node, path, val); + } + default: + return false; + } + } + } +} diff --git a/src/StateService/MPT/MPTTrie.cs b/src/StateService/MPT/MPTTrie.cs new file mode 100644 index 000000000..c77bc746e --- /dev/null +++ b/src/StateService/MPT/MPTTrie.cs @@ -0,0 +1,58 @@ +using Neo.IO; +using Neo.Persistence; +using System; + +namespace Neo.Plugins.MPT +{ + public partial class MPTTrie + where TKey : notnull, ISerializable, new() + where TValue : class, ISerializable, new() + { + private const byte Prefix = 0xf0; + + private readonly ISnapshot store; + private MPTNode root; + + public MPTNode Root => root; + + public MPTTrie(ISnapshot store, UInt256 root) + { + this.store = store ?? throw new ArgumentNullException(); + this.root = root is null ? HashNode.EmptyNode : new HashNode(root); + } + + private MPTNode Resolve(HashNode n) + { + var data = store.TryGet(Prefix, n.Hash.ToArray()); + return MPTNode.Decode(data); + } + + private static byte[] ToNibbles(ReadOnlySpan path) + { + var result = new byte[path.Length * 2]; + for (int i = 0; i < path.Length; i++) + { + result[i * 2] = (byte)(path[i] >> 4); + result[i * 2 + 1] = (byte)(path[i] & 0x0F); + } + return result; + } + + private static byte[] FromNibbles(ReadOnlySpan path) + { + if (path.Length % 2 != 0) throw new FormatException($"MPTTrie.FromNibbles invalid path."); + var key = new byte[path.Length / 2]; + for (int i = 0; i < key.Length; i++) + { + key[i] = (byte)(path[i * 2] << 4); + key[i] |= path[i * 2 + 1]; + } + return key; + } + + private void PutToStore(MPTNode node) + { + store.Put(Prefix, node.Hash.ToArray(), node.Encode()); + } + } +} diff --git a/src/StateService/StateService.csproj b/src/StateService/StateService.csproj new file mode 100644 index 000000000..24ea71663 --- /dev/null +++ b/src/StateService/StateService.csproj @@ -0,0 +1,9 @@ + + + + Neo.Plugins.StateService + Neo.Plugins + true + + + diff --git a/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTNode.cs b/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTNode.cs new file mode 100644 index 000000000..a26325470 --- /dev/null +++ b/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTNode.cs @@ -0,0 +1,30 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.MPT; +using System.Text; + +namespace Neo.Plugins.StateService.Tests.MPT +{ + [TestClass] + public class UT_MPTNode + { + [TestMethod] + public void TestDecode() + { + var n = new LeafNode + { + Value = Encoding.ASCII.GetBytes("hello") + }; + var code = n.Encode(); + var m = MPTNode.Decode(code); + Assert.IsInstanceOfType(m, n.GetType()); + } + + [TestMethod] + public void TestHashNode() + { + var hn = new HashNode(null); + var data = hn.Encode(); + Assert.AreEqual("0200", data.ToHexString()); + } + } +} diff --git a/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs b/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs new file mode 100644 index 000000000..31ec30b5d --- /dev/null +++ b/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs @@ -0,0 +1,320 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.MPT; +using Neo.IO; +using Neo.Persistence; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace Neo.Plugins.StateService.Tests.MPT +{ + public class TestKey : ISerializable + { + private byte[] key; + + public int Size => key.Length; + + public TestKey() + { + this.key = Array.Empty(); + } + + public TestKey(byte[] key) + { + this.key = key; + } + public void Serialize(BinaryWriter writer) + { + writer.Write(key); + } + + public void Deserialize(BinaryReader reader) + { + key = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position)); + } + + public override string ToString() + { + return key.ToHexString(); + } + + public static implicit operator TestKey(byte[] key) + { + return new TestKey(key); + } + } + + public class TestValue : ISerializable + { + private byte[] value; + + public int Size => value.Length; + + public TestValue() + { + this.value = Array.Empty(); + } + + public TestValue(byte[] value) + { + this.value = value; + } + + public void Serialize(BinaryWriter writer) + { + writer.Write(value); + } + + public void Deserialize(BinaryReader reader) + { + value = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position)); + } + + public override string ToString() + { + return value.ToHexString(); + } + + public static implicit operator TestValue(byte[] value) + { + return new TestValue(value); + } + } + + [TestClass] + public class UT_MPTTrie + { + private MPTNode root; + private IStore mptdb; + + private void PutToStore(MPTNode node) + { + mptdb.Put(0xf0, node.Hash.ToArray(), node.Encode()); + } + + [TestInitialize] + public void TestInit() + { + var b = new BranchNode(); + var r = new ExtensionNode { Key = "0a0c".HexToBytes(), Next = b }; + var v1 = new LeafNode { Value = "abcd".HexToBytes() }; + var v2 = new LeafNode { Value = "2222".HexToBytes() }; + var v3 = new LeafNode { Value = Encoding.ASCII.GetBytes("hello") }; + var h1 = new HashNode(v3.Hash); + var l1 = new ExtensionNode { Key = new byte[] { 0x01 }, Next = v1 }; + var l2 = new ExtensionNode { Key = new byte[] { 0x09 }, Next = v2 }; + var l3 = new ExtensionNode { Key = "0e".HexToBytes(), Next = h1 }; + b.Children[0] = l1; + b.Children[9] = l2; + b.Children[10] = l3; + this.root = r; + this.mptdb = new MemoryStore(); + PutToStore(r); + PutToStore(b); + PutToStore(l1); + PutToStore(l2); + PutToStore(l3); + PutToStore(v1); + PutToStore(v2); + PutToStore(v3); + } + + [TestMethod] + public void TestTryGet() + { + var mpt = new MPTTrie(mptdb.GetSnapshot(), root.Hash); + Assert.AreEqual("abcd", mpt["ac01".HexToBytes()].ToString()); + Assert.AreEqual("2222", mpt["ac99".HexToBytes()].ToString()); + Assert.IsNull(mpt["ab99".HexToBytes()]); + Assert.IsNull(mpt["ac39".HexToBytes()]); + Assert.IsNull(mpt["ac02".HexToBytes()]); + Assert.IsNull(mpt["ac9910".HexToBytes()]); + } + + [TestMethod] + public void TestTryGetResolve() + { + var mpt = new MPTTrie(mptdb.GetSnapshot(), root.Hash); + Assert.AreEqual(Encoding.ASCII.GetBytes("hello").ToHexString(), mpt["acae".HexToBytes()].ToString()); + } + + [TestMethod] + public void TestTryPut() + { + var store = new MemoryStore(); + var mpt = new MPTTrie(store.GetSnapshot(), null); + var result = mpt.Put("ac01".HexToBytes(), "abcd".HexToBytes()); + Assert.IsTrue(result); + result = mpt.Put("ac99".HexToBytes(), "2222".HexToBytes()); + Assert.IsTrue(result); + result = mpt.Put("acae".HexToBytes(), Encoding.ASCII.GetBytes("hello")); + Assert.IsTrue(result); + Assert.AreEqual(root.Hash.ToString(), mpt.Root.Hash.ToString()); + } + + [TestMethod] + public void TestTryDelete() + { + var b = new BranchNode(); + var r = new ExtensionNode { Key = "0a0c".HexToBytes(), Next = b }; + var v1 = new LeafNode { Value = "abcd".HexToBytes() }; + var v2 = new LeafNode { Value = "2222".HexToBytes() }; + var r1 = new ExtensionNode { Key = "0a0c0001".HexToBytes(), Next = v1 }; + var l1 = new ExtensionNode { Key = new byte[] { 0x01 }, Next = v1 }; + var l2 = new ExtensionNode { Key = new byte[] { 0x09 }, Next = v2 }; + b.Children[0] = l1; + b.Children[9] = l2; + + Assert.AreEqual("0xdea3ab46e9461e885ed7091c1e533e0a8030b248d39cbc638962394eaca0fbb3", r1.Hash.ToString()); + Assert.AreEqual("0x93e8e1ffe2f83dd92fca67330e273bcc811bf64b8f8d9d1b25d5e7366b47d60d", r.Hash.ToString()); + + var mpt = new MPTTrie(mptdb.GetSnapshot(), root.Hash); + Assert.IsNotNull(mpt["ac99".HexToBytes()]); + bool result = mpt.Delete("ac99".HexToBytes()); + Assert.IsTrue(result); + result = mpt.Delete("acae".HexToBytes()); + Assert.IsTrue(result); + Assert.AreEqual("0xdea3ab46e9461e885ed7091c1e533e0a8030b248d39cbc638962394eaca0fbb3", mpt.Root.Hash.ToString()); + } + + [TestMethod] + public void TestDeleteSameValue() + { + var store = new MemoryStore(); + var snapshot = store.GetSnapshot(); + var mpt = new MPTTrie(snapshot, null); + Assert.IsTrue(mpt.Put("ac01".HexToBytes(), "abcd".HexToBytes())); + Assert.IsTrue(mpt.Put("ac02".HexToBytes(), "abcd".HexToBytes())); + Assert.IsNotNull(mpt["ac01".HexToBytes()]); + Assert.IsNotNull(mpt["ac02".HexToBytes()]); + mpt.Delete("ac01".HexToBytes()); + Assert.IsNotNull(mpt["ac02".HexToBytes()]); + snapshot.Commit(); + + var mpt0 = new MPTTrie(store.GetSnapshot(), mpt.Root.Hash); + Assert.IsNotNull(mpt0["ac02".HexToBytes()]); + } + + [TestMethod] + public void TestBranchNodeRemainValue() + { + var store = new MemoryStore(); + var mpt = new MPTTrie(store.GetSnapshot(), null); + Assert.IsTrue(mpt.Put("ac11".HexToBytes(), "ac11".HexToBytes())); + Assert.IsTrue(mpt.Put("ac22".HexToBytes(), "ac22".HexToBytes())); + Assert.IsTrue(mpt.Put("ac".HexToBytes(), "ac".HexToBytes())); + Assert.IsTrue(mpt.Delete("ac11".HexToBytes())); + mpt.Delete("ac22".HexToBytes()); + Assert.IsNotNull(mpt["ac".HexToBytes()]); + } + + [TestMethod] + public void TestGetProof() + { + var b = new BranchNode(); + var r = new ExtensionNode { Key = "0a0c".HexToBytes(), Next = b }; + var v1 = new LeafNode { Value = "abcd".HexToBytes() }; + var v2 = new LeafNode { Value = "2222".HexToBytes() }; + var v3 = new LeafNode { Value = Encoding.ASCII.GetBytes("hello") }; + var h1 = new HashNode(v3.Hash); + var l1 = new ExtensionNode { Key = new byte[] { 0x01 }, Next = v1 }; + var l2 = new ExtensionNode { Key = new byte[] { 0x09 }, Next = v2 }; + var l3 = new ExtensionNode { Key = "0e".HexToBytes(), Next = h1 }; + b.Children[0] = l1; + b.Children[9] = l2; + b.Children[10] = l3; + + var mpt = new MPTTrie(mptdb.GetSnapshot(), root.Hash); + Assert.AreEqual(r.Hash.ToString(), mpt.Root.Hash.ToString()); + HashSet proof = mpt.GetProof("ac01".HexToBytes()); + Assert.AreEqual(4, proof.Count); + Assert.IsTrue(proof.Contains(b.Encode())); + Assert.IsTrue(proof.Contains(r.Encode())); + Assert.IsTrue(proof.Contains(l1.Encode())); + Assert.IsTrue(proof.Contains(v1.Encode())); + + proof = mpt.GetProof(Array.Empty()); + Assert.IsNull(proof); + } + + [TestMethod] + public void TestVerifyProof() + { + var mpt = new MPTTrie(mptdb.GetSnapshot(), root.Hash); + HashSet proof = mpt.GetProof("ac01".HexToBytes()); + TestValue value = MPTTrie.VerifyProof(root.Hash, "ac01".HexToBytes(), proof); + Assert.IsNotNull(value); + Assert.AreEqual(value.ToString(), "abcd"); + } + + [TestMethod] + public void TestAddLongerKey() + { + var store = new MemoryStore(); + var snapshot = store.GetSnapshot(); + var mpt = new MPTTrie(snapshot, null); + var result = mpt.Put(new byte[] { 0xab }, new byte[] { 0x01 }); + Assert.IsTrue(result); + result = mpt.Put(new byte[] { 0xab, 0xcd }, new byte[] { 0x02 }); + Assert.IsTrue(result); + } + + [TestMethod] + public void TestSplitKey() + { + var store = new MemoryStore(); + var snapshot = store.GetSnapshot(); + var mpt1 = new MPTTrie(snapshot, null); + Assert.IsTrue(mpt1.Put(new byte[] { 0xab, 0xcd }, new byte[] { 0x01 })); + Assert.IsTrue(mpt1.Put(new byte[] { 0xab }, new byte[] { 0x02 })); + HashSet set1 = mpt1.GetProof(new byte[] { 0xab, 0xcd }); + Assert.AreEqual(4, set1.Count); + var mpt2 = new MPTTrie(snapshot, null); + Assert.IsTrue(mpt2.Put(new byte[] { 0xab }, new byte[] { 0x02 })); + Assert.IsTrue(mpt2.Put(new byte[] { 0xab, 0xcd }, new byte[] { 0x01 })); + HashSet set2 = mpt2.GetProof(new byte[] { 0xab, 0xcd }); + Assert.AreEqual(4, set2.Count); + Assert.AreEqual(mpt1.Root.Hash, mpt2.Root.Hash); + } + + [TestMethod] + public void TestFind() + { + var store = new MemoryStore(); + var snapshot = store.GetSnapshot(); + var mpt1 = new MPTTrie(snapshot, null); + var results = mpt1.Find(ReadOnlySpan.Empty).ToArray(); + Assert.AreEqual(0, results.Count()); + var mpt2 = new MPTTrie(snapshot, null); + Assert.IsTrue(mpt2.Put(new byte[] { 0xab, 0xcd, 0xef }, new byte[] { 0x01 })); + Assert.IsTrue(mpt2.Put(new byte[] { 0xab, 0xcd, 0xe1 }, new byte[] { 0x02 })); + Assert.IsTrue(mpt2.Put(new byte[] { 0xab }, new byte[] { 0x03 })); + results = mpt2.Find(ReadOnlySpan.Empty).ToArray(); + Assert.AreEqual(3, results.Count()); + results = mpt2.Find(new byte[] { 0xab }).ToArray(); + Assert.AreEqual(3, results.Count()); + results = mpt2.Find(new byte[] { 0xab, 0xcd }).ToArray(); + Assert.AreEqual(2, results.Count()); + results = mpt2.Find(new byte[] { 0xac }).ToArray(); + Assert.AreEqual(0, results.Count()); + } + + [TestMethod] + public void TestFindLeadNode() + { + // r.Key = 0x0a0c + // b.Key = 0x00 + // l1.Key = 0x01 + var mpt = new MPTTrie(mptdb.GetSnapshot(), root.Hash); + var prefix = new byte[] { 0xac, 0x01 }; // = FromNibbles(path = { 0x0a, 0x0c, 0x00, 0x01 }); + var results = mpt.Find(prefix).ToArray(); + Assert.AreEqual(1, results.Count()); + + prefix = new byte[] { 0xac }; // = FromNibbles(path = { 0x0a, 0x0c }); + results = mpt.Find(prefix).ToArray(); + Assert.AreEqual(3, results.Count()); + } + } +} diff --git a/tests/Neo.Plugins.StateService.Tests/Neo.Plugins.StateService.Tests.csproj b/tests/Neo.Plugins.StateService.Tests/Neo.Plugins.StateService.Tests.csproj new file mode 100644 index 000000000..8733ce647 --- /dev/null +++ b/tests/Neo.Plugins.StateService.Tests/Neo.Plugins.StateService.Tests.csproj @@ -0,0 +1,16 @@ + + + + netcoreapp3.0 + Neo.Plugins.StateService.Tests + false + + + + + + + + + + From 0799d85e2433834ad44b11422aa0545a315d1d4e Mon Sep 17 00:00:00 2001 From: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Date: Fri, 27 Nov 2020 17:36:27 +0800 Subject: [PATCH 03/17] Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal (#413) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal * fix --- src/RpcClient/Models/RpcUnclaimedGas.cs | 6 +++--- src/RpcClient/RpcClient.cs | 4 ++-- src/RpcServer/RpcServer.SmartContract.cs | 2 +- src/RpcServer/RpcServer.Wallet.cs | 2 +- tests/Neo.Network.RPC.Tests/RpcTestCases.json | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/RpcClient/Models/RpcUnclaimedGas.cs b/src/RpcClient/Models/RpcUnclaimedGas.cs index 93e2c72fc..4ec14f5d7 100644 --- a/src/RpcClient/Models/RpcUnclaimedGas.cs +++ b/src/RpcClient/Models/RpcUnclaimedGas.cs @@ -1,11 +1,11 @@ using Neo.IO.Json; -using System.Numerics; +using Neo.SmartContract.Native; namespace Neo.Network.RPC.Models { public class RpcUnclaimedGas { - public BigInteger Unclaimed { get; set; } + public BigDecimal Unclaimed { get; set; } public string Address { get; set; } @@ -21,7 +21,7 @@ public static RpcUnclaimedGas FromJson(JObject json) { return new RpcUnclaimedGas { - Unclaimed = BigInteger.Parse(json["unclaimed"].AsString()), + Unclaimed = BigDecimal.Parse(json["unclaimed"].AsString(), NativeContract.GAS.Decimals), Address = json["address"].AsString() }; } diff --git a/src/RpcClient/RpcClient.cs b/src/RpcClient/RpcClient.cs index b5d2cf430..431e08988 100644 --- a/src/RpcClient/RpcClient.cs +++ b/src/RpcClient/RpcClient.cs @@ -460,10 +460,10 @@ public async Task GetWalletBalanceAsync(string assetId) /// /// Gets the amount of unclaimed GAS in the wallet. /// - public async Task GetWalletUnclaimedGasAsync() + public async Task GetWalletUnclaimedGasAsync() { var result = await RpcSendAsync(GetRpcName()).ConfigureAwait(false); - return BigInteger.Parse(result.AsString()); + return BigDecimal.Parse(result.AsString(), SmartContract.Native.NativeContract.GAS.Decimals); } /// diff --git a/src/RpcServer/RpcServer.SmartContract.cs b/src/RpcServer/RpcServer.SmartContract.cs index a48ede69a..99dff93bf 100644 --- a/src/RpcServer/RpcServer.SmartContract.cs +++ b/src/RpcServer/RpcServer.SmartContract.cs @@ -148,7 +148,7 @@ protected virtual JObject GetUnclaimedGas(JArray _params) if (script_hash == null) throw new RpcException(-100, "Invalid address"); SnapshotView snapshot = Blockchain.Singleton.GetSnapshot(); - json["unclaimed"] = NativeContract.NEO.UnclaimedGas(snapshot, script_hash, snapshot.Height + 1).ToString(); + json["unclaimed"] = new BigDecimal(NativeContract.NEO.UnclaimedGas(snapshot, script_hash, snapshot.Height + 1), NativeContract.GAS.Decimals).ToString(); json["address"] = script_hash.ToAddress(); return json; } diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs index 214df1bee..6ec21fb56 100644 --- a/src/RpcServer/RpcServer.Wallet.cs +++ b/src/RpcServer/RpcServer.Wallet.cs @@ -94,7 +94,7 @@ protected virtual JObject GetWalletUnclaimedGas(JArray _params) { gas += NativeContract.NEO.UnclaimedGas(snapshot, account, snapshot.Height + 1); } - return gas.ToString(); + return new BigDecimal(gas, NativeContract.GAS.Decimals).ToString(); } [RpcMethod] diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index 8833fed6b..7b4c1c33d 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -834,7 +834,7 @@ "jsonrpc": "2.0", "id": 1, "result": { - "unclaimed": "735870007400", + "unclaimed": "7358.700074", "address": "NPvKVTGZapmFWABLsyvfreuqn73jCjJtN1" } } @@ -994,7 +994,7 @@ "Response": { "jsonrpc": "2.0", "id": 1, - "result": "735870007400" + "result": "7358.700074" } }, { From b522dce0a9d4f5ee5bdac198c13fb34e07ee9af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Wed, 2 Dec 2020 02:40:09 -0600 Subject: [PATCH 04/17] Fixed UT (Neo CI01089) (#416) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [RpcServer] Querying contracts by ID/name (#378) * fixed-bug-1021 * Update src/RpcServer/RpcServer.SmartContract.cs * 😂 * draft * draft * update * fixed bug with decimal of GAS consumed in invokefunction/invokescript * remove modify of invokescript * Querying contracts by ID/name, server side * update * Enable using native.name for search Enable using native.name for search * Using keyword instead of addressOrScriptHash * revert * _initialize * split * update * Update exception message in ApplicationLog * Update src/ApplicationLogs/LogReader.cs Co-authored-by: Luchuan * update * a * More fix * fix * Fixed UT * Simplify Code * Simplify Code 2 * Update RpcServer * update Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan * MPT in StateService from core (#410) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal (#413) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal * fix * Fixed UT (Neo CI01089) Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan Co-authored-by: ZhangTao --- src/Directory.Build.props | 2 +- src/RpcClient/Models/RpcContractState.cs | 2 + src/RpcClient/RpcClient.cs | 1 + tests/Neo.Network.RPC.Tests/RpcTestCases.json | 117 ++++++++---------- .../UT_ContractClient.cs | 2 - 5 files changed, 54 insertions(+), 70 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 44d252790..ab7337427 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/src/RpcClient/Models/RpcContractState.cs b/src/RpcClient/Models/RpcContractState.cs index 041cd97f8..802710d0d 100644 --- a/src/RpcClient/Models/RpcContractState.cs +++ b/src/RpcClient/Models/RpcContractState.cs @@ -1,3 +1,4 @@ +using Neo; using Neo.IO.Json; using Neo.Ledger; using Neo.SmartContract.Manifest; @@ -19,6 +20,7 @@ public static RpcContractState FromJson(JObject json) ContractState = new ContractState { Id = (int)json["id"].AsNumber(), + Hash = UInt160.Parse(json["hash"].AsString()), Script = Convert.FromBase64String(json["script"].AsString()), Manifest = ContractManifest.FromJson(json["manifest"]) } diff --git a/src/RpcClient/RpcClient.cs b/src/RpcClient/RpcClient.cs index 431e08988..b9c184137 100644 --- a/src/RpcClient/RpcClient.cs +++ b/src/RpcClient/RpcClient.cs @@ -201,6 +201,7 @@ public static ContractState ContractStateFromJson(JObject json) return new ContractState { Id = (int)json["id"].AsNumber(), + Hash = UInt160.Parse(json["hash"].AsString()), Script = Convert.FromBase64String(json["script"].AsString()), Manifest = ContractManifest.FromJson(json["manifest"]) }; diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index 7b4c1c33d..eae9639f9 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -318,109 +318,87 @@ "Request": { "jsonrpc": "2.0", "method": "getcontractstate", - "params": [ "0x806b7fa0db3b46d6c42e1e1b0a7fd50db9d4a9b0" ], + "params": [ "0x36a019d836d964c438c573f78badf79b9e7eebdd" ], "id": 1 }, "Response": { "jsonrpc": "2.0", "id": 1, "result": { - "id": 0, - "hash": "0x806b7fa0db3b46d6c42e1e1b0a7fd50db9d4a9b0", - "script": "VgIMFGklqlVHEkOanGE7oRTvo/rCPdvKYAwDKiwKYVcDAiFB6X04oAwBINshmlCaULQlIwAAACEMFGklqlVHEkOanGE7oRTvo/rCPdvKIUH4J+yMQCFB6X04oAwBQNshmlCaULQlKQEAAHgMCWJhbGFuY2VPZpcnDwAAAHkQziE1WgEAAEB4DAhkZWNpbWFsc5cnDAAAACE1sQEAAEB4DAZkZXBsb3mXJwwAAAAhNbQBAABAeAwEbmFtZZcnDAAAACE1OQIAAEB4DAZzeW1ib2yXJwwAAAAhNTsCAABAeAwSc3VwcG9ydGVkU3RhbmRhcmRzlycMAAAAITUfAgAAQHgMC3RvdGFsU3VwcGx5lycMAAAAITUmAgAAQHgMCHRyYW5zZmVylyclAAAAecoTsyUHAAAAEEB5EM55Ec5weRLOcWhpIVM1EgIAAEB4DAdkZXN0cm95lycMAAAAITUzAAAAQHgMB21pZ3JhdGWXJyAAAAB5yhKzJQcAAAAQQHkQznkRznJqIVA1EAAAAEAQQCFBxp8d8BFAVwACIQwUaSWqVUcSQ5qcYTuhFO+j+sI928ohQfgn7IwlBwAAABBAeMonDAAAAHnKJQcAAAAQQHh5IVBBMcYzHRFAVwEBeMoMARTbIbMlPAAAAAwyVGhlIHBhcmFtZXRlciBhY2NvdW50IFNIT1VMRCBiZSAyMC1ieXRlIGFkZHJlc3Nlcy4hRTohQZv2Z854IVBBkl3oMRBwJQcAAABoQCFBm/ZnznghUEGSXegx2yFAGEBXAQF4IUGpxUtBcGgnCQAAAGgSzkARQCFBm/ZnzgwLdG90YWxTdXBwbHkhUEGSXegxRSFBm/ZnziEMFGklqlVHEkOanGE7oRTvo/rCPdvKIQwDKiwKIVNB5j8YhCFBm/ZnzgwLdG90YWxTdXBwbHkhDAMqLAohU0HmPxiEIQshDBRpJapVRxJDmpxhO6EU76P6wj3byiEMAyosCiFTDAhUcmFuc2ZlchTAQZUBb2ERQAwVTmVwNSBOZW8zIFRlbXBsYXRlIDEgQAwDTk5EQBPDShAMBU5FUC010EoRDAVORVAtN9BKEgwGTkVQLTEw0EAhQZv2Z84MC3RvdGFsU3VwcGx5IVBBkl3oMdshQFcCA3oQticHAAAAEEB4IUH4J+yMJQcAAAAQQHnKDAEU2yGzJQcAAAAQQCFBm/ZnznghUEGSXegx2yFwaHq1JwcAAAAQQHh5mlCaULQlBwAAABFAaHqzJxgAAAAhQZv2Z854IVBBL1jF7SMWAAAAIUGb9mfOeGh6nyFTQeY/GIQhQZv2Z855IVBBkl3oMXFpJ0QAAAAMB2lmIHBhc3MhQc/nR5YhQZv2Z855adshep4hU0HmPxiEDBBTdG9yYWdlLnB1dCBwYXNzIUHP50eWIzsAAAAMCWVsc2UgcGFzcyFBz+dHliFBm/Znznl6IVNB5j8YhAwOYW1vdW50IC0+IHBhc3MhQc/nR5YheHl6IVMMCFRyYW5zZmVyFMBBlQFvYRFA", + "id": -2, + "updatecounter": 0, + "hash": "0x36a019d836d964c438c573f78badf79b9e7eebdd", + "script": "DANHQVNBa2d4Cw==", "manifest": { + "name": "GAS", "groups": [], - "features": { - "storage": true, - "payable": true - }, "supportedstandards": [ - "NEP-5" + "NEP-17" ], "abi": { - "hash": "0x806b7fa0db3b46d6c42e1e1b0a7fd50db9d4a9b0", "methods": [ { - "name": "main", - "parameters": [ - { - "name": "method", - "type": "String" - }, - { - "name": "args", - "type": "Array" - } - ], + "name": "onPersist", + "parameters": [], "offset": 0, - "returntype": "ByteArray" + "returntype": "Void" }, { - "name": "Destroy", + "name": "totalSupply", "parameters": [], - "offset": 400, - "returntype": "Boolean" + "offset": 0, + "returntype": "Integer" }, { - "name": "Migrate", + "name": "balanceOf", "parameters": [ { - "name": "script", + "name": "account", "type": "ByteArray" - }, - { - "name": "manifest", - "type": "String" } ], - "offset": 408, - "returntype": "Boolean" + "offset": 0, + "returntype": "Integer" }, { - "name": "BalanceOf", + "name": "transfer", "parameters": [ { - "name": "account", + "name": "from", "type": "ByteArray" + }, + { + "name": "to", + "type": "ByteArray" + }, + { + "name": "amount", + "type": "Integer" + }, + { + "name": "data", + "type": "Any" } ], - "offset": 474, - "returntype": "Integer" - }, - { - "name": "Decimals", - "parameters": [], - "offset": 585, - "returntype": "Integer" - }, - { - "name": "Deploy", - "parameters": [], - "offset": 610, + "offset": 0, "returntype": "Boolean" }, { - "name": "Name", + "name": "postPersist", "parameters": [], - "offset": 763, - "returntype": "String" + "offset": 0, + "returntype": "Void" }, { - "name": "Symbol", + "name": "symbol", "parameters": [], - "offset": 787, + "offset": 0, "returntype": "String" }, { - "name": "SupportedStandards", + "name": "decimals", "parameters": [], - "offset": 793, - "returntype": "Array" - }, - { - "name": "TotalSupply", - "parameters": [], - "offset": 827, + "offset": 0, "returntype": "Integer" } ], @@ -429,15 +407,15 @@ "name": "Transfer", "parameters": [ { - "name": "arg1", - "type": "ByteArray" + "name": "from", + "type": "Hash160" }, { - "name": "arg2", - "type": "ByteArray" + "name": "to", + "type": "Hash160" }, { - "name": "arg3", + "name": "amount", "type": "Integer" } ] @@ -451,7 +429,12 @@ } ], "trusts": [], - "safemethods": [], + "safemethods": [ + "totalSupply", + "balanceOf", + "symbol", + "decimals" + ], "extra": null } } diff --git a/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs b/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs index 2a120fad4..a442fdd74 100644 --- a/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs +++ b/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs @@ -45,7 +45,6 @@ public async Task TestDeployContract() Permissions = new[] { ContractPermission.DefaultPermission }, Abi = new ContractAbi() { - Hash = new byte[1].ToScriptHash(), Events = new ContractEventDescriptor[0], Methods = new ContractMethodDescriptor[0] }, @@ -55,7 +54,6 @@ public async Task TestDeployContract() SupportedStandards = new string[] { "NEP-10" }, Extra = null, }; - manifest.Features = ContractFeatures.HasStorage | ContractFeatures.Payable; using (ScriptBuilder sb = new ScriptBuilder()) { sb.EmitSysCall(ApplicationEngine.System_Contract_Create, new byte[1], manifest.ToString()); From bd80d9eff87cce9fd41b940b860015fe347761c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Mon, 7 Dec 2020 02:57:14 -0600 Subject: [PATCH 05/17] Nep17 (#412) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [RpcServer] Querying contracts by ID/name (#378) * fixed-bug-1021 * Update src/RpcServer/RpcServer.SmartContract.cs * 😂 * draft * draft * update * fixed bug with decimal of GAS consumed in invokefunction/invokescript * remove modify of invokescript * Querying contracts by ID/name, server side * update * Enable using native.name for search Enable using native.name for search * Using keyword instead of addressOrScriptHash * revert * _initialize * split * update * Update exception message in ApplicationLog * Update src/ApplicationLogs/LogReader.cs Co-authored-by: Luchuan * update * a * More fix * fix * Fixed UT * Simplify Code * Simplify Code 2 * Update RpcServer * update Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan * String Substitution * Modify filename and name methods * update * update * Update src/RpcClient/Models/RpcNep5TokenInfo.cs Co-authored-by: Vitor Nazário Coelho * Update src/RpcClient/Nep17API.cs Co-authored-by: Vitor Nazário Coelho * MPT in StateService from core (#410) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal (#413) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal * fix * Fixed UT (Neo CI01089) * Update Nep17API.cs * Update README.md Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> * update filename * Fix UT * Format * fix * update * update UT * Add Unit Tests * update Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan Co-authored-by: ZhangTao --- README.md | 6 +- neo-modules.sln | 2 +- src/Directory.Build.props | 2 +- ...RpcNep5Balances.cs => RpcNep17Balances.cs} | 18 ++--- ...cNep5TokenInfo.cs => RpcNep17TokenInfo.cs} | 2 +- ...cNep5Transfers.cs => RpcNep17Transfers.cs} | 20 ++--- src/RpcClient/{Nep5API.cs => Nep17API.cs} | 57 ++++++------- src/RpcClient/RpcClient.cs | 20 ++--- src/RpcClient/TransactionManager.cs | 2 +- src/RpcClient/WalletAPI.cs | 34 ++++---- .../DbCache.cs | 0 .../Helper.cs | 0 .../Nep17Balance.cs} | 8 +- .../Nep17BalanceKey.cs} | 12 +-- .../Nep17Transfer.cs} | 8 +- .../Nep17TransferKey.cs} | 12 +-- .../RpcNep17Tracker.cs} | 80 +++++++++---------- .../RpcNep17Tracker.csproj} | 4 +- .../RpcNep17Tracker}/config.json | 4 +- tests/Neo.Network.RPC.Tests/RpcTestCases.json | 14 ++-- .../{UT_Nep5API.cs => UT_Nep17API.cs} | 56 ++++++------- tests/Neo.Network.RPC.Tests/UT_RpcClient.cs | 16 ++-- tests/Neo.Network.RPC.Tests/UT_RpcModels.cs | 12 +-- tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs | 16 ++++ 24 files changed, 208 insertions(+), 197 deletions(-) rename src/RpcClient/Models/{RpcNep5Balances.cs => RpcNep17Balances.cs} (75%) rename src/RpcClient/Models/{RpcNep5TokenInfo.cs => RpcNep17TokenInfo.cs} (87%) rename src/RpcClient/Models/{RpcNep5Transfers.cs => RpcNep17Transfers.cs} (81%) rename src/RpcClient/{Nep5API.cs => Nep17API.cs} (76%) rename src/{RpcNep5Tracker => RpcNep17Tracker}/DbCache.cs (100%) rename src/{RpcNep5Tracker => RpcNep17Tracker}/Helper.cs (100%) rename src/{RpcNep5Tracker/Nep5Balance.cs => RpcNep17Tracker/Nep17Balance.cs} (80%) rename src/{RpcNep5Tracker/Nep5BalanceKey.cs => RpcNep17Tracker/Nep17BalanceKey.cs} (80%) rename src/{RpcNep5Tracker/Nep5Transfer.cs => RpcNep17Tracker/Nep17Transfer.cs} (84%) rename src/{RpcNep5Tracker/Nep5TransferKey.cs => RpcNep17Tracker/Nep17TransferKey.cs} (87%) rename src/{RpcNep5Tracker/RpcNep5Tracker.cs => RpcNep17Tracker/RpcNep17Tracker.cs} (75%) rename src/{RpcNep5Tracker/RpcNep5Tracker.csproj => RpcNep17Tracker/RpcNep17Tracker.csproj} (82%) rename src/{RpcNep5Tracker/RpcNep5Tracker => RpcNep17Tracker/RpcNep17Tracker}/config.json (76%) rename tests/Neo.Network.RPC.Tests/{UT_Nep5API.cs => UT_Nep17API.cs} (67%) diff --git a/README.md b/README.md index 4712b5be2..95f0e3526 100644 --- a/README.md +++ b/README.md @@ -65,12 +65,12 @@ You can also use `RocksDBStore` in the NEO system by modifying the default stora ### RpcServer Plugin for hosting a RpcServer on the neo-node, being able to disable specific calls. -### RpcNep5Tracker -Plugin that enables NEP5 tracking using LevelDB. +### RpcNep17Tracker +Plugin that enables NEP17 tracking using LevelDB. This module works in conjunction with RpcServer, otherwise, just local storage (on leveldb) would be created. ## C# SDK ### RpcClient The RpcClient Project is an individual SDK that is used to interact with NEO blockchain through NEO RPC methods for development using. The main functions include RPC calling, Transaction making, Contract deployment & calling, and Asset transfering. -It needs a NEO node with the `RpcServer` plugin as a provider. And the provider needs more plugins like `RpcNep5Tracker` and `ApplicationLogs` if you want to call RPC methods supplied by the plugins. +It needs a NEO node with the `RpcServer` plugin as a provider. And the provider needs more plugins like `RpcNep17Tracker` and `ApplicationLogs` if you want to call RPC methods supplied by the plugins. diff --git a/neo-modules.sln b/neo-modules.sln index 24f303eb4..18f557324 100644 --- a/neo-modules.sln +++ b/neo-modules.sln @@ -10,7 +10,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplicationLogs", "src\Appl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StatesDumper", "src\StatesDumper\StatesDumper.csproj", "{86531DB1-A231-46C4-823F-BE60972F7523}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RpcNep5Tracker", "src\RpcNep5Tracker\RpcNep5Tracker.csproj", "{BBE8AC15-12DF-4AF0-ABC1-F1557EB5DC8E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RpcNep17Tracker", "src\RpcNep17Tracker\RpcNep17Tracker.csproj", "{BBE8AC15-12DF-4AF0-ABC1-F1557EB5DC8E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LevelDBStore", "src\LevelDBStore\LevelDBStore.csproj", "{C66214CD-0B97-4EA5-B7A2-164F54346F19}" EndProject diff --git a/src/Directory.Build.props b/src/Directory.Build.props index ab7337427..b7a7f73f8 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/src/RpcClient/Models/RpcNep5Balances.cs b/src/RpcClient/Models/RpcNep17Balances.cs similarity index 75% rename from src/RpcClient/Models/RpcNep5Balances.cs rename to src/RpcClient/Models/RpcNep17Balances.cs index 4cdc1ecc7..dfd35b939 100644 --- a/src/RpcClient/Models/RpcNep5Balances.cs +++ b/src/RpcClient/Models/RpcNep17Balances.cs @@ -6,11 +6,11 @@ namespace Neo.Network.RPC.Models { - public class RpcNep5Balances + public class RpcNep17Balances { public UInt160 UserScriptHash { get; set; } - public List Balances { get; set; } + public List Balances { get; set; } public JObject ToJson() { @@ -20,18 +20,18 @@ public JObject ToJson() return json; } - public static RpcNep5Balances FromJson(JObject json) + public static RpcNep17Balances FromJson(JObject json) { - RpcNep5Balances nep5Balance = new RpcNep5Balances + RpcNep17Balances nep17Balance = new RpcNep17Balances { - Balances = ((JArray)json["balance"]).Select(p => RpcNep5Balance.FromJson(p)).ToList(), + Balances = ((JArray)json["balance"]).Select(p => RpcNep17Balance.FromJson(p)).ToList(), UserScriptHash = json["address"].ToScriptHash() }; - return nep5Balance; + return nep17Balance; } } - public class RpcNep5Balance + public class RpcNep17Balance { public UInt160 AssetHash { get; set; } @@ -48,9 +48,9 @@ public JObject ToJson() return json; } - public static RpcNep5Balance FromJson(JObject json) + public static RpcNep17Balance FromJson(JObject json) { - RpcNep5Balance balance = new RpcNep5Balance + RpcNep17Balance balance = new RpcNep17Balance { AssetHash = json["assethash"].ToScriptHash(), Amount = BigInteger.Parse(json["amount"].AsString()), diff --git a/src/RpcClient/Models/RpcNep5TokenInfo.cs b/src/RpcClient/Models/RpcNep17TokenInfo.cs similarity index 87% rename from src/RpcClient/Models/RpcNep5TokenInfo.cs rename to src/RpcClient/Models/RpcNep17TokenInfo.cs index cb609b8a9..d28873943 100644 --- a/src/RpcClient/Models/RpcNep5TokenInfo.cs +++ b/src/RpcClient/Models/RpcNep17TokenInfo.cs @@ -2,7 +2,7 @@ namespace Neo.Network.RPC.Models { - public class RpcNep5TokenInfo + public class RpcNep17TokenInfo { public string Name { get; set; } diff --git a/src/RpcClient/Models/RpcNep5Transfers.cs b/src/RpcClient/Models/RpcNep17Transfers.cs similarity index 81% rename from src/RpcClient/Models/RpcNep5Transfers.cs rename to src/RpcClient/Models/RpcNep17Transfers.cs index d23ca7a41..bc433ede0 100644 --- a/src/RpcClient/Models/RpcNep5Transfers.cs +++ b/src/RpcClient/Models/RpcNep17Transfers.cs @@ -7,13 +7,13 @@ namespace Neo.Network.RPC.Models { - public class RpcNep5Transfers + public class RpcNep17Transfers { public UInt160 UserScriptHash { get; set; } - public List Sent { get; set; } + public List Sent { get; set; } - public List Received { get; set; } + public List Received { get; set; } public JObject ToJson() { @@ -24,19 +24,19 @@ public JObject ToJson() return json; } - public static RpcNep5Transfers FromJson(JObject json) + public static RpcNep17Transfers FromJson(JObject json) { - RpcNep5Transfers transfers = new RpcNep5Transfers + RpcNep17Transfers transfers = new RpcNep17Transfers { - Sent = ((JArray)json["sent"]).Select(p => RpcNep5Transfer.FromJson(p)).ToList(), - Received = ((JArray)json["received"]).Select(p => RpcNep5Transfer.FromJson(p)).ToList(), + Sent = ((JArray)json["sent"]).Select(p => RpcNep17Transfer.FromJson(p)).ToList(), + Received = ((JArray)json["received"]).Select(p => RpcNep17Transfer.FromJson(p)).ToList(), UserScriptHash = json["address"].ToScriptHash() }; return transfers; } } - public class RpcNep5Transfer + public class RpcNep17Transfer { public ulong TimestampMS { get; set; } @@ -65,9 +65,9 @@ public JObject ToJson() return json; } - public static RpcNep5Transfer FromJson(JObject json) + public static RpcNep17Transfer FromJson(JObject json) { - return new RpcNep5Transfer + return new RpcNep17Transfer { TimestampMS = (ulong)json["timestamp"].AsNumber(), AssetHash = json["assethash"].ToScriptHash(), diff --git a/src/RpcClient/Nep5API.cs b/src/RpcClient/Nep17API.cs similarity index 76% rename from src/RpcClient/Nep5API.cs rename to src/RpcClient/Nep17API.cs index 59cadd67e..50650ade6 100644 --- a/src/RpcClient/Nep5API.cs +++ b/src/RpcClient/Nep17API.cs @@ -13,18 +13,18 @@ namespace Neo.Network.RPC { /// - /// Call NEP5 methods with RPC API + /// Call NEP17 methods with RPC API /// - public class Nep5API : ContractClient + public class Nep17API : ContractClient { /// - /// Nep5API Constructor + /// Nep17API Constructor /// /// the RPC client to call NEO RPC methods - public Nep5API(RpcClient rpcClient) : base(rpcClient) { } + public Nep17API(RpcClient rpcClient) : base(rpcClient) { } /// - /// Get balance of NEP5 token + /// Get balance of NEP17 token /// /// contract script hash /// account script hash @@ -37,18 +37,7 @@ public async Task BalanceOfAsync(UInt160 scriptHash, UInt160 account } /// - /// Get name of NEP5 token - /// - /// contract script hash - /// - public async Task NameAsync(UInt160 scriptHash) - { - var result = await TestInvokeAsync(scriptHash, "name").ConfigureAwait(false); - return result.Stack.Single().GetString(); - } - - /// - /// Get symbol of NEP5 token + /// Get symbol of NEP17 token /// /// contract script hash /// @@ -59,7 +48,7 @@ public async Task SymbolAsync(UInt160 scriptHash) } /// - /// Get decimals of NEP5 token + /// Get decimals of NEP17 token /// /// contract script hash /// @@ -70,7 +59,7 @@ public async Task DecimalsAsync(UInt160 scriptHash) } /// - /// Get total supply of NEP5 token + /// Get total supply of NEP17 token /// /// contract script hash /// @@ -85,40 +74,43 @@ public async Task TotalSupplyAsync(UInt160 scriptHash) /// /// contract script hash /// - public async Task GetTokenInfoAsync(UInt160 scriptHash) + public async Task GetTokenInfoAsync(UInt160 scriptHash) { byte[] script = Concat( - scriptHash.MakeScript("name"), scriptHash.MakeScript("symbol"), scriptHash.MakeScript("decimals"), scriptHash.MakeScript("totalSupply")); + var contractState = await rpcClient.GetContractStateAsync(scriptHash.ToString()).ConfigureAwait(false); + var name = contractState.Manifest.Name; + var result = await rpcClient.InvokeScriptAsync(script).ConfigureAwait(false); var stack = result.Stack; - return new RpcNep5TokenInfo + return new RpcNep17TokenInfo { - Name = stack[0].GetString(), - Symbol = stack[1].GetString(), - Decimals = (byte)stack[2].GetInteger(), - TotalSupply = stack[3].GetInteger() + Name = name, + Symbol = stack[0].GetString(), + Decimals = (byte)stack[1].GetInteger(), + TotalSupply = stack[2].GetInteger() }; } /// - /// Create NEP5 token transfer transaction + /// Create NEP17 token transfer transaction /// /// contract script hash /// from KeyPair /// to account script hash /// transfer amount + /// onPayment data /// - public async Task CreateTransferTxAsync(UInt160 scriptHash, KeyPair fromKey, UInt160 to, BigInteger amount) + public async Task CreateTransferTxAsync(UInt160 scriptHash, KeyPair fromKey, UInt160 to, BigInteger amount, object data = null) { var sender = Contract.CreateSignatureRedeemScript(fromKey.PublicKey).ToScriptHash(); Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } }; - byte[] script = scriptHash.MakeScript("transfer", sender, to, amount); + byte[] script = data is null ? scriptHash.MakeScript("transfer", sender, to, amount) : scriptHash.MakeScript("transfer", sender, to, amount, data); TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic); TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false); @@ -128,7 +120,7 @@ public async Task CreateTransferTxAsync(UInt160 scriptHash, KeyPair } /// - /// Create NEP5 token transfer transaction from multi-sig account + /// Create NEP17 token transfer transaction from multi-sig account /// /// contract script hash /// multi-sig min signature count @@ -136,15 +128,16 @@ public async Task CreateTransferTxAsync(UInt160 scriptHash, KeyPair /// sign keys /// to account /// transfer amount + /// onPayment data /// - public async Task CreateTransferTxAsync(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] fromKeys, UInt160 to, BigInteger amount) + public async Task CreateTransferTxAsync(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] fromKeys, UInt160 to, BigInteger amount, object data = null) { if (m > fromKeys.Length) throw new ArgumentException($"Need at least {m} KeyPairs for signing!"); var sender = Contract.CreateMultiSigContract(m, pubKeys).ScriptHash; Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } }; - byte[] script = scriptHash.MakeScript("transfer", sender, to, amount); + byte[] script = data is null ? scriptHash.MakeScript("transfer", sender, to, amount) : scriptHash.MakeScript("transfer", sender, to, amount, data); TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic); TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false); diff --git a/src/RpcClient/RpcClient.cs b/src/RpcClient/RpcClient.cs index b9c184137..8c0ea27c1 100644 --- a/src/RpcClient/RpcClient.cs +++ b/src/RpcClient/RpcClient.cs @@ -447,14 +447,14 @@ public async Task GetNewAddressAsync() /// /// Returns the balance of the corresponding asset in the wallet, based on the specified asset Id. - /// This method applies to assets that conform to NEP-5 standards. + /// This method applies to assets that conform to NEP-17 standards. /// /// new address as string public async Task GetWalletBalanceAsync(string assetId) { var result = await RpcSendAsync(GetRpcName(), assetId).ConfigureAwait(false); BigInteger balance = BigInteger.Parse(result["balance"].AsString()); - byte decimals = await new Nep5API(this).DecimalsAsync(UInt160.Parse(assetId.AsScriptHash())).ConfigureAwait(false); + byte decimals = await new Nep17API(this).DecimalsAsync(UInt160.Parse(assetId.AsScriptHash())).ConfigureAwait(false); return new BigDecimal(balance, decimals); } @@ -556,30 +556,30 @@ public async Task GetApplicationLogAsync(string txHash, Trigg } /// - /// Returns all the NEP-5 transaction information occurred in the specified address. - /// This method is provided by the plugin RpcNep5Tracker. + /// Returns all the NEP-17 transaction information occurred in the specified address. + /// This method is provided by the plugin RpcNep17Tracker. /// /// The address to query the transaction information. /// The start block Timestamp, default to seven days before UtcNow /// The end block Timestamp, default to UtcNow - public async Task GetNep5TransfersAsync(string address, ulong? startTimestamp = default, ulong? endTimestamp = default) + public async Task GetNep17TransfersAsync(string address, ulong? startTimestamp = default, ulong? endTimestamp = default) { startTimestamp ??= 0; endTimestamp ??= DateTime.UtcNow.ToTimestampMS(); var result = await RpcSendAsync(GetRpcName(), address.AsScriptHash(), startTimestamp, endTimestamp) .ConfigureAwait(false); - return RpcNep5Transfers.FromJson(result); + return RpcNep17Transfers.FromJson(result); } /// - /// Returns the balance of all NEP-5 assets in the specified address. - /// This method is provided by the plugin RpcNep5Tracker. + /// Returns the balance of all NEP-17 assets in the specified address. + /// This method is provided by the plugin RpcNep17Tracker. /// - public async Task GetNep5BalancesAsync(string address) + public async Task GetNep17BalancesAsync(string address) { var result = await RpcSendAsync(GetRpcName(), address.AsScriptHash()) .ConfigureAwait(false); - return RpcNep5Balances.FromJson(result); + return RpcNep17Balances.FromJson(result); } #endregion Plugins diff --git a/src/RpcClient/TransactionManager.cs b/src/RpcClient/TransactionManager.cs index 067fc2ff6..c301fea59 100644 --- a/src/RpcClient/TransactionManager.cs +++ b/src/RpcClient/TransactionManager.cs @@ -166,7 +166,7 @@ public async Task SignAsync() Tx.NetworkFee = await rpcClient.CalculateNetworkFeeAsync(Tx).ConfigureAwait(false); Tx.Witnesses = null; - var gasBalance = await new Nep5API(rpcClient).BalanceOfAsync(NativeContract.GAS.Hash, Tx.Sender).ConfigureAwait(false); + var gasBalance = await new Nep17API(rpcClient).BalanceOfAsync(NativeContract.GAS.Hash, Tx.Sender).ConfigureAwait(false); if (gasBalance < Tx.SystemFee + Tx.NetworkFee) throw new InvalidOperationException($"Insufficient GAS in address: {Tx.Sender.ToAddress()}"); diff --git a/src/RpcClient/WalletAPI.cs b/src/RpcClient/WalletAPI.cs index b4cef3c55..aba15cf91 100644 --- a/src/RpcClient/WalletAPI.cs +++ b/src/RpcClient/WalletAPI.cs @@ -19,7 +19,7 @@ namespace Neo.Network.RPC public class WalletAPI { private readonly RpcClient rpcClient; - private readonly Nep5API nep5API; + private readonly Nep17API nep17API; /// /// WalletAPI Constructor @@ -28,7 +28,7 @@ public class WalletAPI public WalletAPI(RpcClient rpc) { rpcClient = rpc; - nep5API = new Nep5API(rpc); + nep17API = new Nep17API(rpc); } /// @@ -52,7 +52,7 @@ public async Task GetUnclaimedGasAsync(UInt160 account) { UInt160 scriptHash = NativeContract.NEO.Hash; var blockCount = await rpcClient.GetBlockCountAsync().ConfigureAwait(false); - var result = await nep5API.TestInvokeAsync(scriptHash, "unclaimedGas", account, blockCount - 1).ConfigureAwait(false); + var result = await nep17API.TestInvokeAsync(scriptHash, "unclaimedGas", account, blockCount - 1).ConfigureAwait(false); BigInteger balance = result.Stack.Single().GetInteger(); return ((decimal)balance) / (long)NativeContract.GAS.Factor; } @@ -92,7 +92,7 @@ public Task GetTokenBalanceAsync(string tokenHash, string account) { UInt160 scriptHash = Utility.GetScriptHash(tokenHash); UInt160 accountHash = Utility.GetScriptHash(account); - return nep5API.BalanceOfAsync(scriptHash, accountHash); + return nep17API.BalanceOfAsync(scriptHash, accountHash); } /// @@ -117,49 +117,49 @@ public Task ClaimGasAsync(string key) public async Task ClaimGasAsync(KeyPair keyPair) { UInt160 toHash = Contract.CreateSignatureRedeemScript(keyPair.PublicKey).ToScriptHash(); - BigInteger balance = await nep5API.BalanceOfAsync(NativeContract.NEO.Hash, toHash).ConfigureAwait(false); - Transaction transaction = await nep5API.CreateTransferTxAsync(NativeContract.NEO.Hash, keyPair, toHash, balance).ConfigureAwait(false); + BigInteger balance = await nep17API.BalanceOfAsync(NativeContract.NEO.Hash, toHash).ConfigureAwait(false); + Transaction transaction = await nep17API.CreateTransferTxAsync(NativeContract.NEO.Hash, keyPair, toHash, balance).ConfigureAwait(false); await rpcClient.SendRawTransactionAsync(transaction).ConfigureAwait(false); return transaction; } /// - /// Transfer NEP5 token balance, with common data types + /// Transfer NEP17 token balance, with common data types /// - /// nep5 token script hash, Example: scripthash ("0xb0a31817c80ad5f87b6ed390ecb3f9d312f7ceb8") + /// nep17 token script hash, Example: scripthash ("0xb0a31817c80ad5f87b6ed390ecb3f9d312f7ceb8") /// wif or private key /// Example: WIF ("KyXwTh1hB76RRMquSvnxZrJzQx7h9nQP2PCRL38v6VDb5ip3nf1p"), PrivateKey ("450d6c2a04b5b470339a745427bae6828400cf048400837d73c415063835e005") /// address or account script hash /// token amount /// - public async Task TransferAsync(string tokenHash, string fromKey, string toAddress, decimal amount) + public async Task TransferAsync(string tokenHash, string fromKey, string toAddress, decimal amount, object data = null) { UInt160 scriptHash = Utility.GetScriptHash(tokenHash); - var decimals = await nep5API.DecimalsAsync(scriptHash).ConfigureAwait(false); + var decimals = await nep17API.DecimalsAsync(scriptHash).ConfigureAwait(false); KeyPair from = Utility.GetKeyPair(fromKey); UInt160 to = Utility.GetScriptHash(toAddress); BigInteger amountInteger = amount.ToBigInteger(decimals); - return await TransferAsync(scriptHash, from, to, amountInteger).ConfigureAwait(false); + return await TransferAsync(scriptHash, from, to, amountInteger, data).ConfigureAwait(false); } /// - /// Transfer NEP5 token from single-sig account + /// Transfer NEP17 token from single-sig account /// /// contract script hash /// from KeyPair /// to account script hash /// transfer amount /// - public async Task TransferAsync(UInt160 scriptHash, KeyPair from, UInt160 to, BigInteger amountInteger) + public async Task TransferAsync(UInt160 scriptHash, KeyPair from, UInt160 to, BigInteger amountInteger, object data = null) { - Transaction transaction = await nep5API.CreateTransferTxAsync(scriptHash, from, to, amountInteger).ConfigureAwait(false); + Transaction transaction = await nep17API.CreateTransferTxAsync(scriptHash, from, to, amountInteger, data).ConfigureAwait(false); await rpcClient.SendRawTransactionAsync(transaction).ConfigureAwait(false); return transaction; } /// - /// Transfer NEP5 token from multi-sig account + /// Transfer NEP17 token from multi-sig account /// /// contract script hash /// multi-sig min signature count @@ -168,9 +168,9 @@ public async Task TransferAsync(UInt160 scriptHash, KeyPair from, U /// to account /// transfer amount /// - public async Task TransferAsync(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] keys, UInt160 to, BigInteger amountInteger) + public async Task TransferAsync(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] keys, UInt160 to, BigInteger amountInteger, object data = null) { - Transaction transaction = await nep5API.CreateTransferTxAsync(scriptHash, m, pubKeys, keys, to, amountInteger).ConfigureAwait(false); + Transaction transaction = await nep17API.CreateTransferTxAsync(scriptHash, m, pubKeys, keys, to, amountInteger, data).ConfigureAwait(false); await rpcClient.SendRawTransactionAsync(transaction).ConfigureAwait(false); return transaction; } diff --git a/src/RpcNep5Tracker/DbCache.cs b/src/RpcNep17Tracker/DbCache.cs similarity index 100% rename from src/RpcNep5Tracker/DbCache.cs rename to src/RpcNep17Tracker/DbCache.cs diff --git a/src/RpcNep5Tracker/Helper.cs b/src/RpcNep17Tracker/Helper.cs similarity index 100% rename from src/RpcNep5Tracker/Helper.cs rename to src/RpcNep17Tracker/Helper.cs diff --git a/src/RpcNep5Tracker/Nep5Balance.cs b/src/RpcNep17Tracker/Nep17Balance.cs similarity index 80% rename from src/RpcNep5Tracker/Nep5Balance.cs rename to src/RpcNep17Tracker/Nep17Balance.cs index c848879f5..9dc5e3d67 100644 --- a/src/RpcNep5Tracker/Nep5Balance.cs +++ b/src/RpcNep17Tracker/Nep17Balance.cs @@ -4,7 +4,7 @@ namespace Neo.Plugins { - public class Nep5Balance : ICloneable, ISerializable + public class Nep17Balance : ICloneable, ISerializable { public BigInteger Balance; public uint LastUpdatedBlock; @@ -23,16 +23,16 @@ void ISerializable.Deserialize(BinaryReader reader) LastUpdatedBlock = reader.ReadUInt32(); } - Nep5Balance ICloneable.Clone() + Nep17Balance ICloneable.Clone() { - return new Nep5Balance + return new Nep17Balance { Balance = Balance, LastUpdatedBlock = LastUpdatedBlock }; } - public void FromReplica(Nep5Balance replica) + public void FromReplica(Nep17Balance replica) { Balance = replica.Balance; LastUpdatedBlock = replica.LastUpdatedBlock; diff --git a/src/RpcNep5Tracker/Nep5BalanceKey.cs b/src/RpcNep17Tracker/Nep17BalanceKey.cs similarity index 80% rename from src/RpcNep5Tracker/Nep5BalanceKey.cs rename to src/RpcNep17Tracker/Nep17BalanceKey.cs index ec1fc218d..0d5e5267a 100644 --- a/src/RpcNep5Tracker/Nep5BalanceKey.cs +++ b/src/RpcNep17Tracker/Nep17BalanceKey.cs @@ -4,18 +4,18 @@ namespace Neo.Plugins { - public class Nep5BalanceKey : IComparable, IEquatable, ISerializable + public class Nep17BalanceKey : IComparable, IEquatable, ISerializable { public readonly UInt160 UserScriptHash; public readonly UInt160 AssetScriptHash; public int Size => 20 + 20; - public Nep5BalanceKey() : this(new UInt160(), new UInt160()) + public Nep17BalanceKey() : this(new UInt160(), new UInt160()) { } - public Nep5BalanceKey(UInt160 userScriptHash, UInt160 assetScriptHash) + public Nep17BalanceKey(UInt160 userScriptHash, UInt160 assetScriptHash) { if (userScriptHash == null || assetScriptHash == null) throw new ArgumentNullException(); @@ -23,7 +23,7 @@ public Nep5BalanceKey(UInt160 userScriptHash, UInt160 assetScriptHash) AssetScriptHash = assetScriptHash; } - public int CompareTo(Nep5BalanceKey other) + public int CompareTo(Nep17BalanceKey other) { if (other is null) return 1; if (ReferenceEquals(this, other)) return 0; @@ -32,7 +32,7 @@ public int CompareTo(Nep5BalanceKey other) return AssetScriptHash.CompareTo(other.AssetScriptHash); } - public bool Equals(Nep5BalanceKey other) + public bool Equals(Nep17BalanceKey other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; @@ -41,7 +41,7 @@ public bool Equals(Nep5BalanceKey other) public override bool Equals(Object other) { - return other is Nep5BalanceKey otherKey && Equals(otherKey); + return other is Nep17BalanceKey otherKey && Equals(otherKey); } public override int GetHashCode() diff --git a/src/RpcNep5Tracker/Nep5Transfer.cs b/src/RpcNep17Tracker/Nep17Transfer.cs similarity index 84% rename from src/RpcNep5Tracker/Nep5Transfer.cs rename to src/RpcNep17Tracker/Nep17Transfer.cs index 84c71f1d7..8a2f33561 100644 --- a/src/RpcNep5Tracker/Nep5Transfer.cs +++ b/src/RpcNep17Tracker/Nep17Transfer.cs @@ -4,7 +4,7 @@ namespace Neo.Plugins { - public class Nep5Transfer : ICloneable, ISerializable + public class Nep17Transfer : ICloneable, ISerializable { public UInt160 UserScriptHash; public uint BlockIndex; @@ -29,9 +29,9 @@ void ISerializable.Deserialize(BinaryReader reader) Amount = new BigInteger(reader.ReadVarBytes(512)); } - Nep5Transfer ICloneable.Clone() + Nep17Transfer ICloneable.Clone() { - return new Nep5Transfer + return new Nep17Transfer { UserScriptHash = UserScriptHash, BlockIndex = BlockIndex, @@ -40,7 +40,7 @@ Nep5Transfer ICloneable.Clone() }; } - void ICloneable.FromReplica(Nep5Transfer replica) + void ICloneable.FromReplica(Nep17Transfer replica) { UserScriptHash = replica.UserScriptHash; BlockIndex = replica.BlockIndex; diff --git a/src/RpcNep5Tracker/Nep5TransferKey.cs b/src/RpcNep17Tracker/Nep17TransferKey.cs similarity index 87% rename from src/RpcNep5Tracker/Nep5TransferKey.cs rename to src/RpcNep17Tracker/Nep17TransferKey.cs index 69e7fc735..128a7bef1 100644 --- a/src/RpcNep5Tracker/Nep5TransferKey.cs +++ b/src/RpcNep17Tracker/Nep17TransferKey.cs @@ -4,7 +4,7 @@ namespace Neo.Plugins { - public class Nep5TransferKey : IComparable, IEquatable, ISerializable + public class Nep17TransferKey : IComparable, IEquatable, ISerializable { public readonly UInt160 UserScriptHash; public ulong TimestampMS { get; private set; } @@ -17,11 +17,11 @@ public class Nep5TransferKey : IComparable, IEquatable _balances; - private DataCache _transfersSent; - private DataCache _transfersReceived; + private DataCache _balances; + private DataCache _transfersSent; + private DataCache _transfersReceived; private WriteBatch _writeBatch; private bool _shouldTrackHistory; private bool _recordNullAddressHistory; private uint _maxResults; private Snapshot _levelDbSnapshot; - public override string Description => "Enquiries NEP-5 balances and transaction history of accounts through RPC"; + public override string Description => "Enquiries NEP-17 balances and transaction history of accounts through RPC"; - public RpcNep5Tracker() + public RpcNep17Tracker() { RpcServerPlugin.RegisterMethods(this); } @@ -44,7 +44,7 @@ protected override void Configure() { if (_db == null) { - var dbPath = GetConfiguration().GetSection("DBPath").Value ?? "Nep5BalanceData"; + var dbPath = GetConfiguration().GetSection("DBPath").Value ?? "Nep17BalanceData"; _db = DB.Open(GetFullPath(dbPath), new Options { CreateIfMissing = true }); } _shouldTrackHistory = (GetConfiguration().GetSection("TrackHistory").Value ?? true.ToString()) != false.ToString(); @@ -58,13 +58,13 @@ private void ResetBatch() _levelDbSnapshot?.Dispose(); _levelDbSnapshot = _db.GetSnapshot(); ReadOptions dbOptions = new ReadOptions { FillCache = false, Snapshot = _levelDbSnapshot }; - _balances = new DbCache(_db, dbOptions, _writeBatch, Nep5BalancePrefix); + _balances = new DbCache(_db, dbOptions, _writeBatch, Nep17BalancePrefix); if (_shouldTrackHistory) { _transfersSent = - new DbCache(_db, dbOptions, _writeBatch, Nep5TransferSentPrefix); + new DbCache(_db, dbOptions, _writeBatch, Nep17TransferSentPrefix); _transfersReceived = - new DbCache(_db, dbOptions, _writeBatch, Nep5TransferReceivedPrefix); + new DbCache(_db, dbOptions, _writeBatch, Nep17TransferReceivedPrefix); } } @@ -76,8 +76,8 @@ private void RecordTransferHistory(StoreView snapshot, UInt160 scriptHash, UInt1 if (_recordNullAddressHistory || from != UInt160.Zero) { - _transfersSent.Add(new Nep5TransferKey(from, header.Timestamp, scriptHash, transferIndex), - new Nep5Transfer + _transfersSent.Add(new Nep17TransferKey(from, header.Timestamp, scriptHash, transferIndex), + new Nep17Transfer { Amount = amount, UserScriptHash = to, @@ -88,8 +88,8 @@ private void RecordTransferHistory(StoreView snapshot, UInt160 scriptHash, UInt1 if (_recordNullAddressHistory || to != UInt160.Zero) { - _transfersReceived.Add(new Nep5TransferKey(to, header.Timestamp, scriptHash, transferIndex), - new Nep5Transfer + _transfersReceived.Add(new Nep17TransferKey(to, header.Timestamp, scriptHash, transferIndex), + new Nep17Transfer { Amount = amount, UserScriptHash = from, @@ -102,7 +102,7 @@ private void RecordTransferHistory(StoreView snapshot, UInt160 scriptHash, UInt1 private void HandleNotification(StoreView snapshot, IVerifiable scriptContainer, UInt160 scriptHash, string eventName, VM.Types.Array stateItems, - Dictionary nep5BalancesChanged, ref ushort transferIndex) + Dictionary nep17BalancesChanged, ref ushort transferIndex) { if (stateItems.Count == 0) return; if (eventName != "Transfer") return; @@ -129,15 +129,15 @@ private void HandleNotification(StoreView snapshot, IVerifiable scriptContainer, if (fromBytes != null) { from = new UInt160(fromBytes); - var fromKey = new Nep5BalanceKey(from, scriptHash); - if (!nep5BalancesChanged.ContainsKey(fromKey)) nep5BalancesChanged.Add(fromKey, new Nep5Balance()); + var fromKey = new Nep17BalanceKey(from, scriptHash); + if (!nep17BalancesChanged.ContainsKey(fromKey)) nep17BalancesChanged.Add(fromKey, new Nep17Balance()); } if (toBytes != null) { to = new UInt160(toBytes); - var toKey = new Nep5BalanceKey(to, scriptHash); - if (!nep5BalancesChanged.ContainsKey(toKey)) nep5BalancesChanged.Add(toKey, new Nep5Balance()); + var toKey = new Nep17BalanceKey(to, scriptHash); + if (!nep17BalancesChanged.ContainsKey(toKey)) nep17BalancesChanged.Add(toKey, new Nep17Balance()); } if (scriptContainer is Transaction transaction) { @@ -149,7 +149,7 @@ public void OnPersist(StoreView snapshot, IReadOnlyList nep5BalancesChanged = new Dictionary(); + Dictionary nep17BalancesChanged = new Dictionary(); ushort transferIndex = 0; foreach (Blockchain.ApplicationExecuted appExecuted in applicationExecutedList) @@ -161,18 +161,18 @@ public void OnPersist(StoreView snapshot, IReadOnlyList nep5BalancePair.Value); - if (itemToChange != nep5BalancePair.Value) - itemToChange.FromReplica(nep5BalancePair.Value); + var itemToChange = _balances.GetAndChange(nep17BalancePair.Key, () => nep17BalancePair.Value); + if (itemToChange != nep17BalancePair.Value) + itemToChange.FromReplica(nep17BalancePair.Value); } } @@ -223,7 +223,7 @@ private void AddTransfers(byte dbPrefix, UInt160 userScriptHash, ulong startTime Array.Reverse(endTimeBytes); } - var transferPairs = _db.FindRange( + var transferPairs = _db.FindRange( prefix.Concat(startTimeBytes).ToArray(), prefix.Concat(endTimeBytes).ToArray()); @@ -250,7 +250,7 @@ private UInt160 GetScriptHashFromParam(string addressOrScriptHash) } [RpcMethod] - public JObject GetNep5Transfers(JArray _params) + public JObject GetNep17Transfers(JArray _params) { if (!_shouldTrackHistory) throw new RpcException(-32601, "Method not found"); UInt160 userScriptHash = GetScriptHashFromParam(_params[0].AsString()); @@ -267,13 +267,13 @@ public JObject GetNep5Transfers(JArray _params) JArray transfersReceived = new JArray(); json["received"] = transfersReceived; json["address"] = userScriptHash.ToAddress(); - AddTransfers(Nep5TransferSentPrefix, userScriptHash, startTime, endTime, transfersSent); - AddTransfers(Nep5TransferReceivedPrefix, userScriptHash, startTime, endTime, transfersReceived); + AddTransfers(Nep17TransferSentPrefix, userScriptHash, startTime, endTime, transfersSent); + AddTransfers(Nep17TransferReceivedPrefix, userScriptHash, startTime, endTime, transfersReceived); return json; } [RpcMethod] - public JObject GetNep5Balances(JArray _params) + public JObject GetNep17Balances(JArray _params) { UInt160 userScriptHash = GetScriptHashFromParam(_params[0].AsString()); @@ -281,7 +281,7 @@ public JObject GetNep5Balances(JArray _params) JArray balances = new JArray(); json["balance"] = balances; json["address"] = userScriptHash.ToAddress(); - var dbCache = new DbCache(_db, null, null, Nep5BalancePrefix); + var dbCache = new DbCache(_db, null, null, Nep17BalancePrefix); byte[] prefix = userScriptHash.ToArray(); foreach (var (key, value) in dbCache.Find(prefix)) { diff --git a/src/RpcNep5Tracker/RpcNep5Tracker.csproj b/src/RpcNep17Tracker/RpcNep17Tracker.csproj similarity index 82% rename from src/RpcNep5Tracker/RpcNep5Tracker.csproj rename to src/RpcNep17Tracker/RpcNep17Tracker.csproj index 403f4a12a..bb3b93e44 100644 --- a/src/RpcNep5Tracker/RpcNep5Tracker.csproj +++ b/src/RpcNep17Tracker/RpcNep17Tracker.csproj @@ -1,10 +1,10 @@ - Neo.Plugins.RpcNep5Tracker + Neo.Plugins.RpcNep17Tracker Neo.Plugins - + PreserveNewest PreserveNewest diff --git a/src/RpcNep5Tracker/RpcNep5Tracker/config.json b/src/RpcNep17Tracker/RpcNep17Tracker/config.json similarity index 76% rename from src/RpcNep5Tracker/RpcNep5Tracker/config.json rename to src/RpcNep17Tracker/RpcNep17Tracker/config.json index 13e79b805..af5e20247 100644 --- a/src/RpcNep5Tracker/RpcNep5Tracker/config.json +++ b/src/RpcNep17Tracker/RpcNep17Tracker/config.json @@ -1,6 +1,6 @@ -{ +{ "PluginConfiguration": { - "DBPath": "Nep5BalanceData", + "DBPath": "Nep17BalanceData", "TrackHistory" : true, "RecordNullAddressHistory": false, "MaxResults" : 1000 diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index eae9639f9..42ac24a45 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -850,7 +850,7 @@ ] }, { - "name": "RpcNep5Tracker", + "name": "RpcNep17Tracker", "version": "3.0.0.0", "interfaces": [ "IPersistencePlugin" @@ -1340,10 +1340,10 @@ } }, { - "Name": "getnep5transfersasync", + "Name": "getnep17transfersasync", "Request": { "jsonrpc": "2.0", - "method": "getnep5transfers", + "method": "getnep17transfers", "params": [ "NVVwFw6XyhtRCFQ8SpUTMdPyYt4Vd9A1XQ", 0, 1868595301000 ], "id": 1 }, @@ -1387,10 +1387,10 @@ } }, { - "Name": "getnep5transfersasync_with_null_transferaddress", + "Name": "getnep17transfersasync_with_null_transferaddress", "Request": { "jsonrpc": "2.0", - "method": "getnep5transfers", + "method": "getnep17transfers", "params": [ "Ncb7jVsYWBt1q5T5k3ZTP8bn5eK4DuanLd", 0, 1868595301000 ], "id": 1 }, @@ -1434,10 +1434,10 @@ } }, { - "Name": "getnep5balancesasync", + "Name": "getnep17balancesasync", "Request": { "jsonrpc": "2.0", - "method": "getnep5balances", + "method": "getnep17balances", "params": [ "NVVwFw6XyhtRCFQ8SpUTMdPyYt4Vd9A1XQ" ], "id": 1 }, diff --git a/tests/Neo.Network.RPC.Tests/UT_Nep5API.cs b/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs similarity index 67% rename from tests/Neo.Network.RPC.Tests/UT_Nep5API.cs rename to tests/Neo.Network.RPC.Tests/UT_Nep17API.cs index 12f0142c9..b35a2bfc9 100644 --- a/tests/Neo.Network.RPC.Tests/UT_Nep5API.cs +++ b/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs @@ -1,5 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; +using Neo.IO.Json; using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.VM; @@ -11,12 +12,12 @@ namespace Neo.Network.RPC.Tests { [TestClass] - public class UT_Nep5API + public class UT_Nep17API { Mock rpcClientMock; KeyPair keyPair1; UInt160 sender; - Nep5API nep5API; + Nep17API nep17API; [TestInitialize] public void TestSetup() @@ -24,7 +25,7 @@ public void TestSetup() keyPair1 = new KeyPair(Wallet.GetPrivateKeyFromWIF("KyXwTh1hB76RRMquSvnxZrJzQx7h9nQP2PCRL38v6VDb5ip3nf1p")); sender = Contract.CreateSignatureRedeemScript(keyPair1.PublicKey).ToScriptHash(); rpcClientMock = UT_TransactionManager.MockRpcClient(sender, new byte[0]); - nep5API = new Nep5API(rpcClientMock.Object); + nep17API = new Nep17API(rpcClientMock.Object); } [TestMethod] @@ -33,27 +34,17 @@ public async Task TestBalanceOf() byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(10000) }); - var balance = await nep5API.BalanceOfAsync(NativeContract.GAS.Hash, UInt160.Zero); + var balance = await nep17API.BalanceOfAsync(NativeContract.GAS.Hash, UInt160.Zero); Assert.AreEqual(10000, (int)balance); } - [TestMethod] - public async Task TestGetName() - { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("name"); - UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.String, Value = NativeContract.GAS.Name }); - - var result = await nep5API.NameAsync(NativeContract.GAS.Hash); - Assert.AreEqual(NativeContract.GAS.Name, result); - } - [TestMethod] public async Task TestGetSymbol() { byte[] testScript = NativeContract.GAS.Hash.MakeScript("symbol"); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.String, Value = NativeContract.GAS.Symbol }); - var result = await nep5API.SymbolAsync(NativeContract.GAS.Hash); + var result = await nep17API.SymbolAsync(NativeContract.GAS.Hash); Assert.AreEqual(NativeContract.GAS.Symbol, result); } @@ -63,7 +54,7 @@ public async Task TestGetDecimals() byte[] testScript = NativeContract.GAS.Hash.MakeScript("decimals"); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(NativeContract.GAS.Decimals) }); - var result = await nep5API.DecimalsAsync(NativeContract.GAS.Hash); + var result = await nep17API.DecimalsAsync(NativeContract.GAS.Hash); Assert.AreEqual(NativeContract.GAS.Decimals, result); } @@ -73,7 +64,7 @@ public async Task TestGetTotalSupply() byte[] testScript = NativeContract.GAS.Hash.MakeScript("totalSupply"); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_00000000) }); - var result = await nep5API.TotalSupplyAsync(NativeContract.GAS.Hash); + var result = await nep17API.TotalSupplyAsync(NativeContract.GAS.Hash); Assert.AreEqual(1_00000000, (int)result); } @@ -81,22 +72,28 @@ public async Task TestGetTotalSupply() public async Task TestGetTokenInfo() { UInt160 scriptHash = NativeContract.GAS.Hash; - byte[] testScript = scriptHash.MakeScript("name") - .Concat(scriptHash.MakeScript("symbol")) + byte[] testScript = scriptHash.MakeScript("symbol") .Concat(scriptHash.MakeScript("decimals")) .Concat(scriptHash.MakeScript("totalSupply")) - .ToArray(); ; + .ToArray(); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, - new ContractParameter { Type = ContractParameterType.String, Value = NativeContract.GAS.Name }, new ContractParameter { Type = ContractParameterType.String, Value = NativeContract.GAS.Symbol }, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(NativeContract.GAS.Decimals) }, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_00000000) }); - var result = await nep5API.GetTokenInfoAsync(NativeContract.GAS.Hash); - Assert.AreEqual(NativeContract.GAS.Name, result.Name); - Assert.AreEqual(NativeContract.GAS.Symbol, result.Symbol); - Assert.AreEqual(8, (int)result.Decimals); - Assert.AreEqual(1_00000000, (int)result.TotalSupply); + var tests = TestUtils.RpcTestCases.Where(p => p.Name == "getcontractstateasync"); + foreach (var test in tests) + { + rpcClientMock.Setup(p => p.RpcSendAsync("getcontractstate", It.Is(u => true))) + .ReturnsAsync(test.Response.Result) + .Verifiable(); + + var result = await nep17API.GetTokenInfoAsync(NativeContract.GAS.Hash); + Assert.AreEqual(NativeContract.GAS.Symbol, result.Symbol); + Assert.AreEqual(8, (int)result.Decimals); + Assert.AreEqual(1_00000000, (int)result.TotalSupply); + Assert.AreEqual("GAS", result.Name); + } } [TestMethod] @@ -105,7 +102,12 @@ public async Task TestTransfer() byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, new BigInteger(1_00000000)); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter()); - var result = await nep5API.CreateTransferTxAsync(NativeContract.GAS.Hash, keyPair1, UInt160.Zero, new BigInteger(1_00000000)); + var result = await nep17API.CreateTransferTxAsync(NativeContract.GAS.Hash, keyPair1, UInt160.Zero, new BigInteger(1_00000000)); + + testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, new BigInteger(1_00000000), string.Empty); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter()); + + result = await nep17API.CreateTransferTxAsync(NativeContract.GAS.Hash, keyPair1, UInt160.Zero, new BigInteger(1_00000000), string.Empty); Assert.IsNotNull(result); } } diff --git a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs index b558ef201..69ba8caaf 100644 --- a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs +++ b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs @@ -431,21 +431,21 @@ public async Task GetApplicationLogTest_TriggerType() } [TestMethod()] - public async Task GetNep5TransfersTest() + public async Task GetNep17TransfersTest() { - var test = TestUtils.RpcTestCases.Find(p => p.Name == nameof(rpc.GetNep5TransfersAsync).ToLower()); - var result = await rpc.GetNep5TransfersAsync(test.Request.Params[0].AsString(), (ulong)test.Request.Params[1].AsNumber(), (ulong)test.Request.Params[2].AsNumber()); + var test = TestUtils.RpcTestCases.Find(p => p.Name == nameof(rpc.GetNep17TransfersAsync).ToLower()); + var result = await rpc.GetNep17TransfersAsync(test.Request.Params[0].AsString(), (ulong)test.Request.Params[1].AsNumber(), (ulong)test.Request.Params[2].AsNumber()); Assert.AreEqual(test.Response.Result.ToString(), result.ToJson().ToString()); - test = TestUtils.RpcTestCases.Find(p => p.Name == (nameof(rpc.GetNep5TransfersAsync).ToLower() + "_with_null_transferaddress")); - result = await rpc.GetNep5TransfersAsync(test.Request.Params[0].AsString(), (ulong)test.Request.Params[1].AsNumber(), (ulong)test.Request.Params[2].AsNumber()); + test = TestUtils.RpcTestCases.Find(p => p.Name == (nameof(rpc.GetNep17TransfersAsync).ToLower() + "_with_null_transferaddress")); + result = await rpc.GetNep17TransfersAsync(test.Request.Params[0].AsString(), (ulong)test.Request.Params[1].AsNumber(), (ulong)test.Request.Params[2].AsNumber()); Assert.AreEqual(test.Response.Result.ToString(), result.ToJson().ToString()); } [TestMethod()] - public async Task GetNep5BalancesTest() + public async Task GetNep17BalancesTest() { - var test = TestUtils.RpcTestCases.Find(p => p.Name == nameof(rpc.GetNep5BalancesAsync).ToLower()); - var result = await rpc.GetNep5BalancesAsync(test.Request.Params[0].AsString()); + var test = TestUtils.RpcTestCases.Find(p => p.Name == nameof(rpc.GetNep17BalancesAsync).ToLower()); + var result = await rpc.GetNep17BalancesAsync(test.Request.Params[0].AsString()); Assert.AreEqual(test.Response.Result.ToString(), result.ToJson().ToString()); } diff --git a/tests/Neo.Network.RPC.Tests/UT_RpcModels.cs b/tests/Neo.Network.RPC.Tests/UT_RpcModels.cs index 04613dbc1..18b55c603 100644 --- a/tests/Neo.Network.RPC.Tests/UT_RpcModels.cs +++ b/tests/Neo.Network.RPC.Tests/UT_RpcModels.cs @@ -57,18 +57,18 @@ public void TestRpcInvokeResult() } [TestMethod()] - public void TestRpcNep5Balances() + public void TestRpcNep17Balances() { - JObject json = TestUtils.RpcTestCases.Find(p => p.Name == nameof(RpcClient.GetNep5BalancesAsync).ToLower()).Response.Result; - var item = RpcNep5Balances.FromJson(json); + JObject json = TestUtils.RpcTestCases.Find(p => p.Name == nameof(RpcClient.GetNep17BalancesAsync).ToLower()).Response.Result; + var item = RpcNep17Balances.FromJson(json); Assert.AreEqual(json.ToString(), item.ToJson().ToString()); } [TestMethod()] - public void TestRpcNep5Transfers() + public void TestRpcNep17Transfers() { - JObject json = TestUtils.RpcTestCases.Find(p => p.Name == nameof(RpcClient.GetNep5TransfersAsync).ToLower()).Response.Result; - var item = RpcNep5Transfers.FromJson(json); + JObject json = TestUtils.RpcTestCases.Find(p => p.Name == nameof(RpcClient.GetNep17TransfersAsync).ToLower()).Response.Result; + var item = RpcNep17Transfers.FromJson(json); Assert.AreEqual(json.ToString(), item.ToJson().ToString()); } diff --git a/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs b/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs index ebfbcb51b..721b53fef 100644 --- a/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs +++ b/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs @@ -127,6 +127,22 @@ public async Task TestTransferfromMultiSigAccount() var tranaction = await walletAPI.TransferAsync(NativeContract.GAS.Hash, 1, new[] { keyPair1.PublicKey }, new[] { keyPair1 }, UInt160.Zero, NativeContract.GAS.Factor * 100); Assert.AreEqual(testScript.ToHexString(), tranaction.Script.ToHexString()); + + try + { + tranaction = await walletAPI.TransferAsync(NativeContract.GAS.Hash, 2, new[] { keyPair1.PublicKey }, new[] { keyPair1 }, UInt160.Zero, NativeContract.GAS.Factor * 100); + Assert.Fail(); + } + catch (System.Exception e) + { + Assert.AreEqual(e.Message, $"Need at least 2 KeyPairs for signing!"); + } + + testScript = NativeContract.GAS.Hash.MakeScript("transfer", multiSender, UInt160.Zero, NativeContract.GAS.Factor * 100, string.Empty); + UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); + + tranaction = await walletAPI.TransferAsync(NativeContract.GAS.Hash, 1, new[] { keyPair1.PublicKey }, new[] { keyPair1 }, UInt160.Zero, NativeContract.GAS.Factor * 100, string.Empty); + Assert.AreEqual(testScript.ToHexString(), tranaction.Script.ToHexString()); } [TestMethod] From 0cb8a830ec12cd9a963479a9dbed5bfe206397e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Thu, 17 Dec 2020 13:47:22 +0800 Subject: [PATCH 06/17] merge --- src/StateService/MPT/MPTNode.cs | 1 - src/StateService/MPT/MPTNodeType.cs | 3 --- src/StateService/MPT/MPTTrie.Put.cs | 2 -- tests/Neo.Network.RPC.Tests/RpcTestCases.json | 2 +- tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs | 1 - 5 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/StateService/MPT/MPTNode.cs b/src/StateService/MPT/MPTNode.cs index b37c9602b..2cd3a29d6 100644 --- a/src/StateService/MPT/MPTNode.cs +++ b/src/StateService/MPT/MPTNode.cs @@ -1,6 +1,5 @@ using Neo.Cryptography; using Neo.IO; -using Neo.IO.Caching; using System; using System.IO; diff --git a/src/StateService/MPT/MPTNodeType.cs b/src/StateService/MPT/MPTNodeType.cs index a17ce1a7e..83c2b558a 100644 --- a/src/StateService/MPT/MPTNodeType.cs +++ b/src/StateService/MPT/MPTNodeType.cs @@ -1,12 +1,9 @@ -using Neo.IO.Caching; namespace Neo.Plugins.MPT { public enum NodeType : byte { - [ReflectionCache(typeof(BranchNode))] BranchNode = 0x00, - [ReflectionCache(typeof(ExtensionNode))] ExtensionNode = 0x01, LeafNode = 0x02, HashNode = 0x03, diff --git a/src/StateService/MPT/MPTTrie.Put.cs b/src/StateService/MPT/MPTTrie.Put.cs index 5fecbc33f..5ff4f9933 100644 --- a/src/StateService/MPT/MPTTrie.Put.cs +++ b/src/StateService/MPT/MPTTrie.Put.cs @@ -133,8 +133,6 @@ private bool Put(ref MPTNode node, ReadOnlySpan path, MPTNode val) case NodeType.Empty: { MPTNode newNode; - if (hashNode.IsEmpty) - { if (path.IsEmpty) { newNode = val; diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index 39e068840..c6c2228b2 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -521,7 +521,7 @@ "name": "vote", "parameters": [ { - "name": "from", + "name": "account", "type": "ByteArray" }, { diff --git a/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs b/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs index 3747a73a9..9affc5f1a 100644 --- a/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs +++ b/tests/Neo.Plugins.StateService.Tests/MPT/UT_MPTTrie.cs @@ -278,7 +278,6 @@ public void TestDeleteSameValue() Assert.IsNotNull(mpt["ac02".HexToBytes()]); mpt.Commit(); snapshot.Commit(); - var mpt0 = new MPTTrie(store.GetSnapshot(), mpt.Root.Hash); Assert.IsNotNull(mpt0["ac02".HexToBytes()]); } From f05644f5887fe7fb9b3513e54594246c25206e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Thu, 17 Dec 2020 13:58:38 +0800 Subject: [PATCH 07/17] clear --- src/StateService/MPT/BranchNode.cs | 35 ----------------------- src/StateService/MPT/ExtensionNode.cs | 30 -------------------- src/StateService/MPT/HashNode.cs | 41 --------------------------- src/StateService/MPT/LeafNode.cs | 36 ----------------------- 4 files changed, 142 deletions(-) delete mode 100644 src/StateService/MPT/BranchNode.cs delete mode 100644 src/StateService/MPT/ExtensionNode.cs delete mode 100644 src/StateService/MPT/HashNode.cs delete mode 100644 src/StateService/MPT/LeafNode.cs diff --git a/src/StateService/MPT/BranchNode.cs b/src/StateService/MPT/BranchNode.cs deleted file mode 100644 index f729412b5..000000000 --- a/src/StateService/MPT/BranchNode.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.IO; - -namespace Neo.Plugins.MPT -{ - public class BranchNode : MPTNode - { - public const int ChildCount = 17; - public readonly MPTNode[] Children = new MPTNode[ChildCount]; - - protected override NodeType Type => NodeType.BranchNode; - - public BranchNode() - { - for (int i = 0; i < ChildCount; i++) - { - Children[i] = HashNode.EmptyNode; - } - } - - internal override void EncodeSpecific(BinaryWriter writer) - { - for (int i = 0; i < ChildCount; i++) - WriteHash(writer, Children[i].Hash); - } - - internal override void DecodeSpecific(BinaryReader reader) - { - for (int i = 0; i < ChildCount; i++) - { - Children[i] = new HashNode(); - Children[i].DecodeSpecific(reader); - } - } - } -} diff --git a/src/StateService/MPT/ExtensionNode.cs b/src/StateService/MPT/ExtensionNode.cs deleted file mode 100644 index 00f107240..000000000 --- a/src/StateService/MPT/ExtensionNode.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Neo.IO; -using Neo.SmartContract; -using System.IO; - -namespace Neo.Plugins.MPT -{ - public class ExtensionNode : MPTNode - { - //max lenght when store StorageKey - public const int MaxKeyLength = (ApplicationEngine.MaxStorageValueSize + sizeof(int)) * 2; - - public byte[] Key; - public MPTNode Next; - - protected override NodeType Type => NodeType.ExtensionNode; - - internal override void EncodeSpecific(BinaryWriter writer) - { - writer.WriteVarBytes(Key); - WriteHash(writer, Next.Hash); - } - - internal override void DecodeSpecific(BinaryReader reader) - { - Key = reader.ReadVarBytes(MaxKeyLength); - Next = new HashNode(); - Next.DecodeSpecific(reader); - } - } -} diff --git a/src/StateService/MPT/HashNode.cs b/src/StateService/MPT/HashNode.cs deleted file mode 100644 index 7053f0a3b..000000000 --- a/src/StateService/MPT/HashNode.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Neo.IO; -using System; -using System.IO; - -namespace Neo.Plugins.MPT -{ - public class HashNode : MPTNode - { - private UInt256 hash; - - public override UInt256 Hash => hash; - protected override NodeType Type => NodeType.HashNode; - public bool IsEmpty => Hash is null; - public static HashNode EmptyNode { get; } = new HashNode(); - - public HashNode() - { - } - - public HashNode(UInt256 hash) - { - this.hash = hash; - } - - internal override void EncodeSpecific(BinaryWriter writer) - { - WriteHash(writer, hash); - } - - internal override void DecodeSpecific(BinaryReader reader) - { - byte[] buffer = reader.ReadVarBytes(UInt256.Length); - hash = buffer.Length switch - { - 0 => null, - UInt256.Length => new UInt256(buffer), - _ => throw new FormatException() - }; - } - } -} diff --git a/src/StateService/MPT/LeafNode.cs b/src/StateService/MPT/LeafNode.cs deleted file mode 100644 index 2a17ef4e2..000000000 --- a/src/StateService/MPT/LeafNode.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Neo.IO; -using Neo.SmartContract; -using System; -using System.IO; - -namespace Neo.Plugins.MPT -{ - public class LeafNode : MPTNode - { - //the max size when store StorageItem - public const int MaxValueLength = 3 + ApplicationEngine.MaxStorageValueSize + sizeof(bool); - - public byte[] Value; - - protected override NodeType Type => NodeType.LeafNode; - - public LeafNode() - { - } - - public LeafNode(ReadOnlySpan value) - { - Value = value.ToArray(); - } - - internal override void EncodeSpecific(BinaryWriter writer) - { - writer.WriteVarBytes(Value); - } - - internal override void DecodeSpecific(BinaryReader reader) - { - Value = reader.ReadVarBytes(MaxValueLength); - } - } -} From 615b9743b19d52330138adada0dc067691054658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Thu, 17 Dec 2020 14:36:18 -0600 Subject: [PATCH 08/17] Transfer bug fix (#429) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [RpcServer] Querying contracts by ID/name (#378) * fixed-bug-1021 * Update src/RpcServer/RpcServer.SmartContract.cs * 😂 * draft * draft * update * fixed bug with decimal of GAS consumed in invokefunction/invokescript * remove modify of invokescript * Querying contracts by ID/name, server side * update * Enable using native.name for search Enable using native.name for search * Using keyword instead of addressOrScriptHash * revert * _initialize * split * update * Update exception message in ApplicationLog * Update src/ApplicationLogs/LogReader.cs Co-authored-by: Luchuan * update * a * More fix * fix * Fixed UT * Simplify Code * Simplify Code 2 * Update RpcServer * update Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan * MPT in StateService from core (#410) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal (#413) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal * fix * Fixed UT (Neo CI01089) (#416) * [RpcServer] Querying contracts by ID/name (#378) * fixed-bug-1021 * Update src/RpcServer/RpcServer.SmartContract.cs * 😂 * draft * draft * update * fixed bug with decimal of GAS consumed in invokefunction/invokescript * remove modify of invokescript * Querying contracts by ID/name, server side * update * Enable using native.name for search Enable using native.name for search * Using keyword instead of addressOrScriptHash * revert * _initialize * split * update * Update exception message in ApplicationLog * Update src/ApplicationLogs/LogReader.cs Co-authored-by: Luchuan * update * a * More fix * fix * Fixed UT * Simplify Code * Simplify Code 2 * Update RpcServer * update Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan * MPT in StateService from core (#410) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal (#413) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal * fix * Fixed UT (Neo CI01089) Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan Co-authored-by: ZhangTao * Nep17 (#412) * [RpcServer] Querying contracts by ID/name (#378) * fixed-bug-1021 * Update src/RpcServer/RpcServer.SmartContract.cs * 😂 * draft * draft * update * fixed bug with decimal of GAS consumed in invokefunction/invokescript * remove modify of invokescript * Querying contracts by ID/name, server side * update * Enable using native.name for search Enable using native.name for search * Using keyword instead of addressOrScriptHash * revert * _initialize * split * update * Update exception message in ApplicationLog * Update src/ApplicationLogs/LogReader.cs Co-authored-by: Luchuan * update * a * More fix * fix * Fixed UT * Simplify Code * Simplify Code 2 * Update RpcServer * update Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan * String Substitution * Modify filename and name methods * update * update * Update src/RpcClient/Models/RpcNep5TokenInfo.cs Co-authored-by: Vitor Nazário Coelho * Update src/RpcClient/Nep17API.cs Co-authored-by: Vitor Nazário Coelho * MPT in StateService from core (#410) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal (#413) * Unify GetUnclaimedGas and GetWalletUnclaimedGas with decimal * fix * Fixed UT (Neo CI01089) * Update Nep17API.cs * Update README.md Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> * update filename * Fix UT * Format * fix * update * update UT * Add Unit Tests * update Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan Co-authored-by: ZhangTao * merge * fixed bug * clear * UT * Add a little code coverage Co-authored-by: Shargon Co-authored-by: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Co-authored-by: superboyiii <573504781@qq.com> Co-authored-by: Vitor Nazário Coelho Co-authored-by: Luchuan Co-authored-by: ZhangTao --- src/Directory.Build.props | 2 +- src/RpcClient/Nep17API.cs | 4 ++-- tests/Neo.Network.RPC.Tests/RpcTestCases.json | 8 ++++---- tests/Neo.Network.RPC.Tests/UT_Nep17API.cs | 10 +++++----- tests/Neo.Network.RPC.Tests/UT_RpcClient.cs | 1 + tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs | 6 +++--- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 7668491fb..ae97d5e4a 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -15,7 +15,7 @@ - + \ No newline at end of file diff --git a/src/RpcClient/Nep17API.cs b/src/RpcClient/Nep17API.cs index 50650ade6..69a3b7d53 100644 --- a/src/RpcClient/Nep17API.cs +++ b/src/RpcClient/Nep17API.cs @@ -110,7 +110,7 @@ public async Task CreateTransferTxAsync(UInt160 scriptHash, KeyPair var sender = Contract.CreateSignatureRedeemScript(fromKey.PublicKey).ToScriptHash(); Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } }; - byte[] script = data is null ? scriptHash.MakeScript("transfer", sender, to, amount) : scriptHash.MakeScript("transfer", sender, to, amount, data); + byte[] script = scriptHash.MakeScript("transfer", sender, to, amount, data); TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic); TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false); @@ -137,7 +137,7 @@ public async Task CreateTransferTxAsync(UInt160 scriptHash, int m, var sender = Contract.CreateMultiSigContract(m, pubKeys).ScriptHash; Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } }; - byte[] script = data is null ? scriptHash.MakeScript("transfer", sender, to, amount) : scriptHash.MakeScript("transfer", sender, to, amount, data); + byte[] script = scriptHash.MakeScript("transfer", sender, to, amount, data); TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic); TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false); diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index c6c2228b2..1e97c3832 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -433,7 +433,7 @@ "jsonrpc": "2.0", "id": 1, "method": "getcontractstate", - "params": [ "0x74c21a1ca66b7a190bf2a65db83ba6fe550cea64" ] + "params": [ "0x0a46e2e37c9987f570b4af253fb77e7eef0f72b6" ] }, "Response": { "jsonrpc": "2.0", @@ -441,10 +441,10 @@ "result": { "id": -1, "updatecounter": 0, - "hash": "0x74c21a1ca66b7a190bf2a65db83ba6fe550cea64", - "script": "DANORU9BGvd7Zw==", + "hash": "0x0a46e2e37c9987f570b4af253fb77e7eef0f72b6", + "script": "DAhOZW9Ub2tlbkEa93tn", "manifest": { - "name": "NEO", + "name": "NeoToken", "groups": [], "supportedstandards": [ "NEP-17" diff --git a/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs b/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs index f48a6eea4..a4f2d93f8 100644 --- a/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs +++ b/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs @@ -98,21 +98,21 @@ public async Task TestGetTokenInfo() .ReturnsAsync(test.Response.Result) .Verifiable(); - if (test.Request.Params[0].AsString() == "0xb399c051778cf37a1e4ef88509b2e054d0420a32") + if (test.Request.Params[0].AsString() == "0xa6a6c15dcdc9b997dac448b6926522d22efeedfb") { var result = await nep17API.GetTokenInfoAsync(NativeContract.GAS.Hash); Assert.AreEqual(NativeContract.GAS.Symbol, result.Symbol); Assert.AreEqual(8, (int)result.Decimals); Assert.AreEqual(1_00000000, (int)result.TotalSupply); - Assert.AreEqual("GAS", result.Name); + Assert.AreEqual("GasToken", result.Name); } - else if (test.Request.Params[0].AsString() == "0x74c21a1ca66b7a190bf2a65db83ba6fe550cea64") + else if (test.Request.Params[0].AsString() == "0x0a46e2e37c9987f570b4af253fb77e7eef0f72b6") { var result = await nep17API.GetTokenInfoAsync(NativeContract.NEO.Hash); Assert.AreEqual(NativeContract.NEO.Symbol, result.Symbol); Assert.AreEqual(0, (int)result.Decimals); Assert.AreEqual(1_00000000, (int)result.TotalSupply); - Assert.AreEqual("NEO", result.Name); + Assert.AreEqual("NeoToken", result.Name); } } } @@ -120,7 +120,7 @@ public async Task TestGetTokenInfo() [TestMethod] public async Task TestTransfer() { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, new BigInteger(1_00000000)); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, new BigInteger(1_00000000), null); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter()); var result = await nep17API.CreateTransferTxAsync(NativeContract.GAS.Hash, keyPair1, UInt160.Zero, new BigInteger(1_00000000)); diff --git a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs index 69ba8caaf..f4f2f5c12 100644 --- a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs +++ b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs @@ -294,6 +294,7 @@ public async Task TestGetUnclaimedGas() { var test = TestUtils.RpcTestCases.Find(p => p.Name == nameof(rpc.GetUnclaimedGasAsync).ToLower()); var result = await rpc.GetUnclaimedGasAsync(test.Request.Params[0].AsString()); + Assert.AreEqual(result.ToJson().AsString(), RpcUnclaimedGas.FromJson(result.ToJson()).ToJson().AsString()); Assert.AreEqual(test.Response.Result["unclaimed"].AsString(), result.Unclaimed.ToString()); } diff --git a/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs b/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs index 721b53fef..7ec348ebe 100644 --- a/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs +++ b/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs @@ -79,7 +79,7 @@ public async Task TestClaimGas() byte[] balanceScript = NativeContract.NEO.Hash.MakeScript("balanceOf", sender); UT_TransactionManager.MockInvokeScript(rpcClientMock, balanceScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_00000000) }); - byte[] testScript = NativeContract.NEO.Hash.MakeScript("transfer", sender, sender, new BigInteger(1_00000000)); + byte[] testScript = NativeContract.NEO.Hash.MakeScript("transfer", sender, sender, new BigInteger(1_00000000), null); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); var json = new JObject(); @@ -96,7 +96,7 @@ public async Task TestTransfer() byte[] decimalsScript = NativeContract.GAS.Hash.MakeScript("decimals"); UT_TransactionManager.MockInvokeScript(rpcClientMock, decimalsScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(8) }); - byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, NativeContract.GAS.Factor * 100); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, NativeContract.GAS.Factor * 100, null); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); var json = new JObject(); @@ -118,7 +118,7 @@ public async Task TestTransferfromMultiSigAccount() byte[] decimalsScript = NativeContract.GAS.Hash.MakeScript("decimals"); UT_TransactionManager.MockInvokeScript(rpcClientMock, decimalsScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(8) }); - byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", multiSender, UInt160.Zero, NativeContract.GAS.Factor * 100); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", multiSender, UInt160.Zero, NativeContract.GAS.Factor * 100, null); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); var json = new JObject(); From 33141c1658e6b4f2e0d2d3a9370f559c175724d3 Mon Sep 17 00:00:00 2001 From: Owen Zhang <38493437+superboyiii@users.noreply.github.com> Date: Fri, 18 Dec 2020 16:37:07 +0800 Subject: [PATCH 09/17] Preview4 (#430) * Preview4 * Remove syslog in README.md --- README.md | 3 --- src/Directory.Build.props | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 95f0e3526..0919ba2fd 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,6 @@ The resulting folder structure is going to be like this: ### ApplicationLogs Add this plugin to your application if need to access the log files. This can be useful to handle notifications, but remember that this also largely increases the space used by the application. `LevelDBStore` and `RpcServer` are also needed for this plugin. You can find more details [here](https://docs.neo.org/docs/en-us/reference/rpc/latest-version/api/getapplicationlog.html). -### SystemLog -Enable neo-cli Logging with timestamps by showing messages with different levels (shown with different colors) \(useful for debugging\). - ### StatesDumper Exports neo-cli status data \(useful for debugging\), such as storage modifications block by block. diff --git a/src/Directory.Build.props b/src/Directory.Build.props index ae97d5e4a..28635c471 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -3,7 +3,7 @@ 3.0.0 - preview3 + preview4 netstandard2.1 Neo.Plugins The Neo Project @@ -15,7 +15,7 @@ - + \ No newline at end of file From 215a8cc23e3d959c983419a60c78dcde8d1e0e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Mon, 21 Dec 2020 22:06:31 -0600 Subject: [PATCH 10/17] dotnet 5.0 (#407) --- .github/workflows/main.yml | 6 ++-- src/Directory.Build.props | 8 +++--- src/RpcClient/ContractClient.cs | 4 +-- src/RpcNep17Tracker/RpcNep17Tracker.cs | 3 +- src/RpcServer/RpcServer.Blockchain.cs | 4 +-- src/RpcServer/RpcServer.SmartContract.cs | 2 +- tests/Directory.Build.props | 15 ++++++++++ .../Neo.Network.RPC.Tests.csproj | 5 ---- tests/Neo.Network.RPC.Tests/RpcTestCases.json | 16 ++++++----- .../UT_ContractClient.cs | 4 +-- .../Neo.Plugins.StateService.Tests.csproj | 28 +++++++------------ .../Neo.Plugins.Storage.Tests.csproj | 8 ------ 12 files changed, 49 insertions(+), 54 deletions(-) create mode 100644 tests/Directory.Build.props diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4a5401c3d..2f9ffe2c5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,7 +6,7 @@ on: pull_request: env: - DOTNET_VERSION: 3.1.100 + DOTNET_VERSION: 5.0.100 jobs: @@ -21,8 +21,8 @@ jobs: dotnet-version: ${{ env.DOTNET_VERSION }} - name: Check format run: | - dotnet tool install --version 3.2.111002 --tool-path ./ dotnet-format --add-source https://dotnet.myget.org/F/format/api/v3/index.json - ./dotnet-format --check --dry-run -v diagnostic + dotnet tool install --version 5.0.142902 --tool-path ./ dotnet-format --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json + ./dotnet-format . --check -v diagnostic - name: Test run: | sudo apt-get --assume-yes install libleveldb-dev libsnappy-dev libc6-dev diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 28635c471..d2c7dfa9c 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,10 +1,10 @@ - + 3.0.0 preview4 - netstandard2.1 + net5.0 Neo.Plugins The Neo Project NEO;Blockchain @@ -15,7 +15,7 @@ - + - \ No newline at end of file + diff --git a/src/RpcClient/ContractClient.cs b/src/RpcClient/ContractClient.cs index bc664c82f..296c2e12b 100644 --- a/src/RpcClient/ContractClient.cs +++ b/src/RpcClient/ContractClient.cs @@ -1,4 +1,3 @@ -using System.Threading.Tasks; using Neo.Network.P2P.Payloads; using Neo.Network.RPC.Models; using Neo.SmartContract; @@ -6,6 +5,7 @@ using Neo.SmartContract.Native; using Neo.VM; using Neo.Wallets; +using System.Threading.Tasks; namespace Neo.Network.RPC { @@ -57,7 +57,7 @@ public async Task CreateDeployContractTxAsync(byte[] nefFile, Contr byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { - sb.EmitAppCall(NativeContract.Management.Hash, "deploy", nefFile, manifest.ToString()); + sb.EmitAppCall(NativeContract.ContractManagement.Hash, "deploy", nefFile, manifest.ToString()); script = sb.ToArray(); } UInt160 sender = Contract.CreateSignatureRedeemScript(key.PublicKey).ToScriptHash(); diff --git a/src/RpcNep17Tracker/RpcNep17Tracker.cs b/src/RpcNep17Tracker/RpcNep17Tracker.cs index 9dcef2318..79fbafa7c 100644 --- a/src/RpcNep17Tracker/RpcNep17Tracker.cs +++ b/src/RpcNep17Tracker/RpcNep17Tracker.cs @@ -1,4 +1,3 @@ -using Microsoft.AspNetCore.Http; using Neo.IO; using Neo.IO.Caching; using Neo.IO.Data.LevelDB; @@ -287,7 +286,7 @@ public JObject GetNep17Balances(JArray _params) foreach (var (key, value) in dbCache.Find(prefix)) { JObject balance = new JObject(); - if (NativeContract.Management.GetContract(snapshot, key.AssetScriptHash) is null) + if (NativeContract.ContractManagement.GetContract(snapshot, key.AssetScriptHash) is null) continue; balance["assethash"] = key.AssetScriptHash.ToString(); balance["amount"] = value.Balance.ToString(); diff --git a/src/RpcServer/RpcServer.Blockchain.cs b/src/RpcServer/RpcServer.Blockchain.cs index adccfbf38..16eb2a990 100644 --- a/src/RpcServer/RpcServer.Blockchain.cs +++ b/src/RpcServer/RpcServer.Blockchain.cs @@ -106,7 +106,7 @@ protected virtual JObject GetContractState(JArray _params) { using SnapshotView snapshot = Blockchain.Singleton.GetSnapshot(); UInt160 script_hash = ToScriptHash(_params[0].AsString()); - ContractState contract = NativeContract.Management.GetContract(snapshot, script_hash); + ContractState contract = NativeContract.ContractManagement.GetContract(snapshot, script_hash); return contract?.ToJson() ?? throw new RpcException(-100, "Unknown contract"); } @@ -170,7 +170,7 @@ protected virtual JObject GetStorage(JArray _params) { using SnapshotView snapshot = Blockchain.Singleton.GetSnapshot(); UInt160 script_hash = UInt160.Parse(_params[0].AsString()); - ContractState contract = NativeContract.Management.GetContract(snapshot, script_hash); + ContractState contract = NativeContract.ContractManagement.GetContract(snapshot, script_hash); if (contract == null) return null; id = contract.Id; } diff --git a/src/RpcServer/RpcServer.SmartContract.cs b/src/RpcServer/RpcServer.SmartContract.cs index ca635f896..475a12bf6 100644 --- a/src/RpcServer/RpcServer.SmartContract.cs +++ b/src/RpcServer/RpcServer.SmartContract.cs @@ -110,7 +110,7 @@ private static Signers SignersFromJson(JArray _params) private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] args, Signers signers = null) { var snapshot = Blockchain.Singleton.GetSnapshot(); - var contract = NativeContract.Management.GetContract(snapshot, scriptHash); + var contract = NativeContract.ContractManagement.GetContract(snapshot, scriptHash); if (contract is null) { throw new RpcException(-100, "Unknown contract"); diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props new file mode 100644 index 000000000..3a7fa1350 --- /dev/null +++ b/tests/Directory.Build.props @@ -0,0 +1,15 @@ + + + + + net5.0 + false + + + + + + + + + diff --git a/tests/Neo.Network.RPC.Tests/Neo.Network.RPC.Tests.csproj b/tests/Neo.Network.RPC.Tests/Neo.Network.RPC.Tests.csproj index af5c7c416..3209d575a 100644 --- a/tests/Neo.Network.RPC.Tests/Neo.Network.RPC.Tests.csproj +++ b/tests/Neo.Network.RPC.Tests/Neo.Network.RPC.Tests.csproj @@ -1,16 +1,11 @@ - netcoreapp3.1 Neo.Network.RPC.Tests - false - - - diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index 1e97c3832..c62c64d5e 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -1112,24 +1112,26 @@ "Name": "invokescriptasync", "Request": { "jsonrpc": "2.0", + "id": 1, "method": "invokescript", - "params": [ "EMMMCGRlY2ltYWxzDBQ7fTcRxvDM+bHcqQPRv6HYlvEjjEFifVtS" ], - "id": 1 + "params": [ + "HxDDDAhkZWNpbWFscwwU\u002B\u002B3\u002BLtIiZZK2SMTal7nJzV3BpqZB7vQM2w==" + ] }, "Response": { "jsonrpc": "2.0", "id": 1, "result": { - "script": "EMMMCGRlY2ltYWxzDBQ7fTcRxvDM+bHcqQPRv6HYlvEjjEFifVtS", + "script": "HxDDDAhkZWNpbWFscwwU++3+LtIiZZK2SMTal7nJzV3BpqZB7vQM2w==", "state": "HALT", - "gasconsumed": "0.0506156", + "gasconsumed": "0.0099918", + "exception": null, "stack": [ { "type": "Integer", "value": "8" } - ], - "tx": "00769d16556925aa554712439a9c613ba114efa3fac23ddbca00e1f505000000009e021400000000005620200000009910c30c046e616d650c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5210c30c0673796d626f6c0c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5210c30c08646563696d616c730c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5210c30c0b746f74616c537570706c790c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5201420c40c848d0fcbf5e6a820508242ea8b7ccbeed3caefeed5db570537279c2154f7cfd8b0d8f477f37f4e6ca912935b732684d57c455dff7aa525ad4ab000931f22208290c2103aa052fbcb8e5b33a4eefd662536f8684641f04109f1d5e69cdda6f084890286a0b410a906ad4" + ] } } }, @@ -1152,7 +1154,7 @@ "Request": { "jsonrpc": "2.0", "method": "getwalletbalance", - "params": [ "0x8c23f196d8a1bfd103a9dcb1f9ccf0c611377d3b" ], + "params": [ "0xa6a6c15dcdc9b997dac448b6926522d22efeedfb" ], "id": 1 }, "Response": { diff --git a/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs b/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs index 0de9a0958..06b331595 100644 --- a/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs +++ b/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs @@ -1,4 +1,3 @@ -using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Neo.SmartContract; @@ -6,6 +5,7 @@ using Neo.SmartContract.Native; using Neo.VM; using Neo.Wallets; +using System.Threading.Tasks; namespace Neo.Network.RPC.Tests { @@ -55,7 +55,7 @@ public async Task TestDeployContract() }; using (ScriptBuilder sb = new ScriptBuilder()) { - sb.EmitAppCall(NativeContract.Management.Hash, "deploy", new byte[1], manifest.ToString()); + sb.EmitAppCall(NativeContract.ContractManagement.Hash, "deploy", new byte[1], manifest.ToString()); script = sb.ToArray(); } diff --git a/tests/Neo.Plugins.StateService.Tests/Neo.Plugins.StateService.Tests.csproj b/tests/Neo.Plugins.StateService.Tests/Neo.Plugins.StateService.Tests.csproj index 4f0dfa232..94b2e2355 100644 --- a/tests/Neo.Plugins.StateService.Tests/Neo.Plugins.StateService.Tests.csproj +++ b/tests/Neo.Plugins.StateService.Tests/Neo.Plugins.StateService.Tests.csproj @@ -1,18 +1,10 @@ - - - - netcoreapp3.0 - Neo.Plugins.StateService.Tests - false - - - - - - - - - - - - + + + + Neo.Plugins.StateService.Tests + + + + + + diff --git a/tests/Neo.Plugins.Storage.Tests/Neo.Plugins.Storage.Tests.csproj b/tests/Neo.Plugins.Storage.Tests/Neo.Plugins.Storage.Tests.csproj index ac7f99449..c6798b71a 100644 --- a/tests/Neo.Plugins.Storage.Tests/Neo.Plugins.Storage.Tests.csproj +++ b/tests/Neo.Plugins.Storage.Tests/Neo.Plugins.Storage.Tests.csproj @@ -1,17 +1,9 @@ - netcoreapp3.0 Neo.Plugins.Storage.Tests - false - - - - - - From 8780e1a4c128cc757e95bc908548825859662425 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Tue, 22 Dec 2020 12:19:32 +0800 Subject: [PATCH 11/17] CI01123 (#435) --- src/Directory.Build.props | 2 +- src/LevelDBStore/LevelDBStore.csproj | 7 ------ src/LevelDBStore/LevelDBStore/config.json | 5 ---- .../Plugins/Storage/LevelDBStore.cs | 10 ++------ .../Plugins/Storage/RocksDBStore.cs | 14 ++++------- src/RocksDBStore/Plugins/Storage/Settings.cs | 21 ----------------- src/RocksDBStore/RocksDBStore.csproj | 7 ------ src/RocksDBStore/RocksDBStore/config.json | 5 ---- tests/Neo.Plugins.Storage.Tests/StoreTest.cs | 23 +++++++++++-------- 9 files changed, 21 insertions(+), 73 deletions(-) delete mode 100644 src/LevelDBStore/LevelDBStore/config.json delete mode 100644 src/RocksDBStore/Plugins/Storage/Settings.cs delete mode 100644 src/RocksDBStore/RocksDBStore/config.json diff --git a/src/Directory.Build.props b/src/Directory.Build.props index d2c7dfa9c..c8dcf12f9 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -15,7 +15,7 @@ - + diff --git a/src/LevelDBStore/LevelDBStore.csproj b/src/LevelDBStore/LevelDBStore.csproj index d49bce97d..42232fbd1 100644 --- a/src/LevelDBStore/LevelDBStore.csproj +++ b/src/LevelDBStore/LevelDBStore.csproj @@ -6,11 +6,4 @@ true - - - PreserveNewest - PreserveNewest - - - diff --git a/src/LevelDBStore/LevelDBStore/config.json b/src/LevelDBStore/LevelDBStore/config.json deleted file mode 100644 index f31d07fd6..000000000 --- a/src/LevelDBStore/LevelDBStore/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "PluginConfiguration": { - "Path": "Data_LevelDB_{0}" - } -} diff --git a/src/LevelDBStore/Plugins/Storage/LevelDBStore.cs b/src/LevelDBStore/Plugins/Storage/LevelDBStore.cs index 61118a57a..246052af3 100644 --- a/src/LevelDBStore/Plugins/Storage/LevelDBStore.cs +++ b/src/LevelDBStore/Plugins/Storage/LevelDBStore.cs @@ -7,17 +7,11 @@ namespace Neo.Plugins.Storage { public class LevelDBStore : Plugin, IStorageProvider { - private string path; - public override string Description => "Uses LevelDB to store the blockchain data"; - protected override void Configure() - { - path = string.Format(GetConfiguration().GetSection("Path").Value ?? "Data_LevelDB_{0}", ProtocolSettings.Default.Magic.ToString("X8")); - } - - public IStore GetStore() + public IStore GetStore(string path) { + path = string.Format(path, ProtocolSettings.Default.Magic.ToString("X8")); if (Environment.CommandLine.Split(' ').Any(p => p == "/repair" || p == "--repair")) DB.Repair(path, Options.Default); return new Store(path); diff --git a/src/RocksDBStore/Plugins/Storage/RocksDBStore.cs b/src/RocksDBStore/Plugins/Storage/RocksDBStore.cs index 6377845e6..e82b5a815 100644 --- a/src/RocksDBStore/Plugins/Storage/RocksDBStore.cs +++ b/src/RocksDBStore/Plugins/Storage/RocksDBStore.cs @@ -6,18 +6,14 @@ public class RocksDBStore : Plugin, IStorageProvider { public override string Description => "Uses RocksDBStore to store the blockchain data"; - /// - /// Configure - /// - protected override void Configure() - { - Settings.Load(GetConfiguration()); - } - /// /// Get store /// /// RocksDbStore - public IStore GetStore() => new Store(Settings.Default.Path); + public IStore GetStore(string path) + { + path = string.Format(path, ProtocolSettings.Default.Magic.ToString("X8")); + return new Store(path); + } } } diff --git a/src/RocksDBStore/Plugins/Storage/Settings.cs b/src/RocksDBStore/Plugins/Storage/Settings.cs deleted file mode 100644 index 253be9751..000000000 --- a/src/RocksDBStore/Plugins/Storage/Settings.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.Extensions.Configuration; - -namespace Neo.Plugins.Storage -{ - internal class Settings - { - public string Path { get; } - - public static Settings Default { get; private set; } - - private Settings(IConfigurationSection section) - { - this.Path = string.Format(section.GetSection("Path").Value ?? "Data_RocksDB_{0}", ProtocolSettings.Default.Magic.ToString("X8")); - } - - public static void Load(IConfigurationSection section) - { - Default = new Settings(section); - } - } -} diff --git a/src/RocksDBStore/RocksDBStore.csproj b/src/RocksDBStore/RocksDBStore.csproj index e1f5bad60..f86fae3c0 100644 --- a/src/RocksDBStore/RocksDBStore.csproj +++ b/src/RocksDBStore/RocksDBStore.csproj @@ -5,13 +5,6 @@ Neo.Plugins.Storage - - - PreserveNewest - PreserveNewest - - - diff --git a/src/RocksDBStore/RocksDBStore/config.json b/src/RocksDBStore/RocksDBStore/config.json deleted file mode 100644 index 5ded6dfe1..000000000 --- a/src/RocksDBStore/RocksDBStore/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "PluginConfiguration": { - "Path": "Data_RocksDB_{0}" - } -} diff --git a/tests/Neo.Plugins.Storage.Tests/StoreTest.cs b/tests/Neo.Plugins.Storage.Tests/StoreTest.cs index a09bedacb..af2e51342 100644 --- a/tests/Neo.Plugins.Storage.Tests/StoreTest.cs +++ b/tests/Neo.Plugins.Storage.Tests/StoreTest.cs @@ -6,6 +6,9 @@ namespace Neo.Plugins.Storage.Tests [TestClass] public class StoreTest { + private const string path_leveldb = "Data_LevelDB_{0}"; + private const string path_rocksdb = "Data_RocksDB_{0}"; + [TestMethod] public void TestLevelDb() { @@ -13,14 +16,14 @@ public void TestLevelDb() { // Test all with the same store - TestStorage(plugin.GetStore()); + TestStorage(plugin.GetStore(path_leveldb)); // Test with different storages - TestPersistenceWrite(plugin.GetStore()); - TestPersistenceRead(plugin.GetStore(), true); - TestPersistenceDelete(plugin.GetStore()); - TestPersistenceRead(plugin.GetStore(), false); + TestPersistenceWrite(plugin.GetStore(path_leveldb)); + TestPersistenceRead(plugin.GetStore(path_leveldb), true); + TestPersistenceDelete(plugin.GetStore(path_leveldb)); + TestPersistenceRead(plugin.GetStore(path_leveldb), false); } } @@ -31,14 +34,14 @@ public void TestRocksDb() { // Test all with the same store - TestStorage(plugin.GetStore()); + TestStorage(plugin.GetStore(path_rocksdb)); // Test with different storages - TestPersistenceWrite(plugin.GetStore()); - TestPersistenceRead(plugin.GetStore(), true); - TestPersistenceDelete(plugin.GetStore()); - TestPersistenceRead(plugin.GetStore(), false); + TestPersistenceWrite(plugin.GetStore(path_rocksdb)); + TestPersistenceRead(plugin.GetStore(path_rocksdb), true); + TestPersistenceDelete(plugin.GetStore(path_rocksdb)); + TestPersistenceRead(plugin.GetStore(path_rocksdb), false); } } From 5774c81cfc2e84a08bcedc03fd3400144174a8cf Mon Sep 17 00:00:00 2001 From: Shine Li Date: Fri, 25 Dec 2020 15:24:31 +0800 Subject: [PATCH 12/17] Fix dotnet5 (#442) --- src/Directory.Build.props | 2 +- src/RpcServer/RpcServer.cs | 2 +- src/RpcServer/RpcServer.csproj | 6 +----- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index c8dcf12f9..f571077d6 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -15,7 +15,7 @@ - + diff --git a/src/RpcServer/RpcServer.cs b/src/RpcServer/RpcServer.cs index b20a22caf..367b34c68 100644 --- a/src/RpcServer/RpcServer.cs +++ b/src/RpcServer/RpcServer.cs @@ -170,7 +170,7 @@ private async Task ProcessAsync(HttpContext context) using StreamReader reader = new StreamReader(context.Request.Body); try { - request = JObject.Parse(reader.ReadToEnd()); + request = JObject.Parse(await reader.ReadToEndAsync()); } catch (FormatException) { } } diff --git a/src/RpcServer/RpcServer.csproj b/src/RpcServer/RpcServer.csproj index f04dbdda5..a3e5b6af8 100644 --- a/src/RpcServer/RpcServer.csproj +++ b/src/RpcServer/RpcServer.csproj @@ -11,9 +11,5 @@ PreserveNewest - - - - - + From bef9e7d8d1c6c43815f26d03f093f77384385320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Tue, 29 Dec 2020 15:54:12 +0800 Subject: [PATCH 13/17] fixed compiler bug --- src/Directory.Build.props | 2 +- src/RpcClient/ContractClient.cs | 5 ++-- src/RpcClient/Nep17API.cs | 10 ++++---- src/RpcServer/RpcServer.SmartContract.cs | 6 ++--- .../UT_ContractClient.cs | 4 ++-- tests/Neo.Network.RPC.Tests/UT_Nep17API.cs | 24 +++++++++---------- tests/Neo.Network.RPC.Tests/UT_PolicyAPI.cs | 8 +++---- .../UT_TransactionManager.cs | 8 +++---- tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs | 24 +++++++++---------- 9 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index c8dcf12f9..4b3679871 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -15,7 +15,7 @@ - + diff --git a/src/RpcClient/ContractClient.cs b/src/RpcClient/ContractClient.cs index 296c2e12b..3aea771a4 100644 --- a/src/RpcClient/ContractClient.cs +++ b/src/RpcClient/ContractClient.cs @@ -41,7 +41,8 @@ public ContractClient(RpcClient rpc, uint? magic = null) /// public Task TestInvokeAsync(UInt160 scriptHash, string operation, params object[] args) { - byte[] script = scriptHash.MakeScript(operation, args); + byte[] script = scriptHash.MakeScript(operation, true, args); + var base64 = System.Convert.ToBase64String(script); return rpcClient.InvokeScriptAsync(script); } @@ -57,7 +58,7 @@ public async Task CreateDeployContractTxAsync(byte[] nefFile, Contr byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { - sb.EmitAppCall(NativeContract.ContractManagement.Hash, "deploy", nefFile, manifest.ToString()); + sb.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", true, nefFile, manifest.ToString()); script = sb.ToArray(); } UInt160 sender = Contract.CreateSignatureRedeemScript(key.PublicKey).ToScriptHash(); diff --git a/src/RpcClient/Nep17API.cs b/src/RpcClient/Nep17API.cs index 69a3b7d53..14312e841 100644 --- a/src/RpcClient/Nep17API.cs +++ b/src/RpcClient/Nep17API.cs @@ -77,9 +77,9 @@ public async Task TotalSupplyAsync(UInt160 scriptHash) public async Task GetTokenInfoAsync(UInt160 scriptHash) { byte[] script = Concat( - scriptHash.MakeScript("symbol"), - scriptHash.MakeScript("decimals"), - scriptHash.MakeScript("totalSupply")); + scriptHash.MakeScript("symbol", true), + scriptHash.MakeScript("decimals", true), + scriptHash.MakeScript("totalSupply", true)); var contractState = await rpcClient.GetContractStateAsync(scriptHash.ToString()).ConfigureAwait(false); var name = contractState.Manifest.Name; @@ -110,7 +110,7 @@ public async Task CreateTransferTxAsync(UInt160 scriptHash, KeyPair var sender = Contract.CreateSignatureRedeemScript(fromKey.PublicKey).ToScriptHash(); Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } }; - byte[] script = scriptHash.MakeScript("transfer", sender, to, amount, data); + byte[] script = scriptHash.MakeScript("transfer", true, sender, to, amount, data); TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic); TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false); @@ -137,7 +137,7 @@ public async Task CreateTransferTxAsync(UInt160 scriptHash, int m, var sender = Contract.CreateMultiSigContract(m, pubKeys).ScriptHash; Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } }; - byte[] script = scriptHash.MakeScript("transfer", sender, to, amount, data); + byte[] script = scriptHash.MakeScript("transfer", true, sender, to, amount, data); TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic); TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false); diff --git a/src/RpcServer/RpcServer.SmartContract.cs b/src/RpcServer/RpcServer.SmartContract.cs index 475a12bf6..5dc4aa831 100644 --- a/src/RpcServer/RpcServer.SmartContract.cs +++ b/src/RpcServer/RpcServer.SmartContract.cs @@ -125,9 +125,9 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar }; using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.Clone()); - engine.LoadContract(contract, methodName, CallFlags.None); + engine.LoadContract(contract, methodName, CallFlags.None, true, 0); - engine.LoadScript(new ScriptBuilder().EmitAppCall(scriptHash, methodName, args).ToArray(), CallFlags.AllowCall); + engine.LoadScript(new ScriptBuilder().EmitDynamicCall(scriptHash, methodName, true, args).ToArray()); JObject json = new JObject(); json["script"] = Convert.ToBase64String(contract.Script); @@ -169,7 +169,7 @@ protected virtual JObject InvokeFunction(JArray _params) byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { - script = sb.EmitAppCall(script_hash, operation, args).ToArray(); + script = sb.EmitDynamicCall(script_hash, operation, true, args).ToArray(); } return GetInvokeResult(script, signers); } diff --git a/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs b/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs index 06b331595..6007d1b27 100644 --- a/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs +++ b/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs @@ -27,7 +27,7 @@ public void TestSetup() [TestMethod] public async Task TestInvoke() { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", true, UInt160.Zero); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.ByteArray, Value = "00e057eb481b".HexToBytes() }); ContractClient contractClient = new ContractClient(rpcClientMock.Object); @@ -55,7 +55,7 @@ public async Task TestDeployContract() }; using (ScriptBuilder sb = new ScriptBuilder()) { - sb.EmitAppCall(NativeContract.ContractManagement.Hash, "deploy", new byte[1], manifest.ToString()); + sb.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", true, new byte[1], manifest.ToString()); script = sb.ToArray(); } diff --git a/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs b/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs index a4f2d93f8..4d4582f11 100644 --- a/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs +++ b/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs @@ -31,7 +31,7 @@ public void TestSetup() [TestMethod] public async Task TestBalanceOf() { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", true, UInt160.Zero); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(10000) }); var balance = await nep17API.BalanceOfAsync(NativeContract.GAS.Hash, UInt160.Zero); @@ -41,7 +41,7 @@ public async Task TestBalanceOf() [TestMethod] public async Task TestGetSymbol() { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("symbol"); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("symbol", true); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.String, Value = NativeContract.GAS.Symbol }); var result = await nep17API.SymbolAsync(NativeContract.GAS.Hash); @@ -51,7 +51,7 @@ public async Task TestGetSymbol() [TestMethod] public async Task TestGetDecimals() { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("decimals"); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("decimals", true); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(NativeContract.GAS.Decimals) }); var result = await nep17API.DecimalsAsync(NativeContract.GAS.Hash); @@ -61,7 +61,7 @@ public async Task TestGetDecimals() [TestMethod] public async Task TestGetTotalSupply() { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("totalSupply"); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("totalSupply", true); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_00000000) }); var result = await nep17API.TotalSupplyAsync(NativeContract.GAS.Hash); @@ -72,9 +72,9 @@ public async Task TestGetTotalSupply() public async Task TestGetTokenInfo() { UInt160 scriptHash = NativeContract.GAS.Hash; - byte[] testScript = scriptHash.MakeScript("symbol") - .Concat(scriptHash.MakeScript("decimals")) - .Concat(scriptHash.MakeScript("totalSupply")) + byte[] testScript = scriptHash.MakeScript("symbol", true) + .Concat(scriptHash.MakeScript("decimals", true)) + .Concat(scriptHash.MakeScript("totalSupply", true)) .ToArray(); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.String, Value = NativeContract.GAS.Symbol }, @@ -82,9 +82,9 @@ public async Task TestGetTokenInfo() new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_00000000) }); scriptHash = NativeContract.NEO.Hash; - testScript = scriptHash.MakeScript("symbol") - .Concat(scriptHash.MakeScript("decimals")) - .Concat(scriptHash.MakeScript("totalSupply")) + testScript = scriptHash.MakeScript("symbol", true) + .Concat(scriptHash.MakeScript("decimals", true)) + .Concat(scriptHash.MakeScript("totalSupply", true)) .ToArray(); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.String, Value = NativeContract.NEO.Symbol }, @@ -120,12 +120,12 @@ public async Task TestGetTokenInfo() [TestMethod] public async Task TestTransfer() { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, new BigInteger(1_00000000), null); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", true, sender, UInt160.Zero, new BigInteger(1_00000000), null); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter()); var result = await nep17API.CreateTransferTxAsync(NativeContract.GAS.Hash, keyPair1, UInt160.Zero, new BigInteger(1_00000000)); - testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, new BigInteger(1_00000000), string.Empty); + testScript = NativeContract.GAS.Hash.MakeScript("transfer", true, sender, UInt160.Zero, new BigInteger(1_00000000), string.Empty); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter()); result = await nep17API.CreateTransferTxAsync(NativeContract.GAS.Hash, keyPair1, UInt160.Zero, new BigInteger(1_00000000), string.Empty); diff --git a/tests/Neo.Network.RPC.Tests/UT_PolicyAPI.cs b/tests/Neo.Network.RPC.Tests/UT_PolicyAPI.cs index 245636e93..9a32320de 100644 --- a/tests/Neo.Network.RPC.Tests/UT_PolicyAPI.cs +++ b/tests/Neo.Network.RPC.Tests/UT_PolicyAPI.cs @@ -29,7 +29,7 @@ public void TestSetup() [TestMethod] public async Task TestGetMaxTransactionsPerBlock() { - byte[] testScript = NativeContract.Policy.Hash.MakeScript("getMaxTransactionsPerBlock"); + byte[] testScript = NativeContract.Policy.Hash.MakeScript("getMaxTransactionsPerBlock", true); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(512) }); var result = await policyAPI.GetMaxTransactionsPerBlockAsync(); @@ -39,7 +39,7 @@ public async Task TestGetMaxTransactionsPerBlock() [TestMethod] public async Task TestGetMaxBlockSize() { - byte[] testScript = NativeContract.Policy.Hash.MakeScript("getMaxBlockSize"); + byte[] testScript = NativeContract.Policy.Hash.MakeScript("getMaxBlockSize", true); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1024u * 256u) }); var result = await policyAPI.GetMaxBlockSizeAsync(); @@ -49,7 +49,7 @@ public async Task TestGetMaxBlockSize() [TestMethod] public async Task TestGetFeePerByte() { - byte[] testScript = NativeContract.Policy.Hash.MakeScript("getFeePerByte"); + byte[] testScript = NativeContract.Policy.Hash.MakeScript("getFeePerByte", true); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1000) }); var result = await policyAPI.GetFeePerByteAsync(); @@ -59,7 +59,7 @@ public async Task TestGetFeePerByte() [TestMethod] public async Task TestIsBlocked() { - byte[] testScript = NativeContract.Policy.Hash.MakeScript("isBlocked", UInt160.Zero); + byte[] testScript = NativeContract.Policy.Hash.MakeScript("isBlocked", true, UInt160.Zero); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Boolean, Value = true }); var result = await policyAPI.IsBlockedAsync(UInt160.Zero); Assert.AreEqual(true, result); diff --git a/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs b/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs index bc740fd1c..06010849a 100644 --- a/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs +++ b/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs @@ -54,13 +54,13 @@ public static Mock MockRpcClient(UInt160 sender, byte[] script) .Verifiable(); // MockGasBalance - byte[] balanceScript = NativeContract.GAS.Hash.MakeScript("balanceOf", sender); + byte[] balanceScript = NativeContract.GAS.Hash.MakeScript("balanceOf", true, sender); var balanceResult = new ContractParameter() { Type = ContractParameterType.Integer, Value = BigInteger.Parse("10000000000000000") }; MockInvokeScript(mockRpc, balanceScript, balanceResult); // MockFeePerByte - byte[] policyScript = NativeContract.Policy.Hash.MakeScript("getFeePerByte"); + byte[] policyScript = NativeContract.Policy.Hash.MakeScript("getFeePerByte", true); var policyResult = new ContractParameter() { Type = ContractParameterType.Integer, Value = BigInteger.Parse("1000") }; MockInvokeScript(mockRpc, policyScript, policyResult); @@ -87,13 +87,13 @@ public static Mock MockMultiSig(UInt160 multiHash, byte[] script) .Verifiable(); // MockGasBalance - byte[] balanceScript = NativeContract.GAS.Hash.MakeScript("balanceOf", multiHash); + byte[] balanceScript = NativeContract.GAS.Hash.MakeScript("balanceOf", true, multiHash); var balanceResult = new ContractParameter() { Type = ContractParameterType.Integer, Value = BigInteger.Parse("10000000000000000") }; MockInvokeScript(mockRpc, balanceScript, balanceResult); // MockFeePerByte - byte[] policyScript = NativeContract.Policy.Hash.MakeScript("getFeePerByte"); + byte[] policyScript = NativeContract.Policy.Hash.MakeScript("getFeePerByte", true); var policyResult = new ContractParameter() { Type = ContractParameterType.Integer, Value = BigInteger.Parse("1000") }; MockInvokeScript(mockRpc, policyScript, policyResult); diff --git a/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs b/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs index 7ec348ebe..594f02654 100644 --- a/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs +++ b/tests/Neo.Network.RPC.Tests/UT_WalletAPI.cs @@ -36,7 +36,7 @@ public void TestSetup() [TestMethod] public async Task TestGetUnclaimedGas() { - byte[] testScript = NativeContract.NEO.Hash.MakeScript("unclaimedGas", sender, 99); + byte[] testScript = NativeContract.NEO.Hash.MakeScript("unclaimedGas", true, sender, 99); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); var balance = await walletAPI.GetUnclaimedGasAsync(address1); @@ -46,7 +46,7 @@ public async Task TestGetUnclaimedGas() [TestMethod] public async Task TestGetNeoBalance() { - byte[] testScript = NativeContract.NEO.Hash.MakeScript("balanceOf", sender); + byte[] testScript = NativeContract.NEO.Hash.MakeScript("balanceOf", true, sender); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_00000000) }); var balance = await walletAPI.GetNeoBalanceAsync(address1); @@ -56,7 +56,7 @@ public async Task TestGetNeoBalance() [TestMethod] public async Task TestGetGasBalance() { - byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", sender); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", true, sender); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); var balance = await walletAPI.GetGasBalanceAsync(address1); @@ -66,7 +66,7 @@ public async Task TestGetGasBalance() [TestMethod] public async Task TestGetTokenBalance() { - byte[] testScript = UInt160.Zero.MakeScript("balanceOf", sender); + byte[] testScript = UInt160.Zero.MakeScript("balanceOf", true, sender); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); var balance = await walletAPI.GetTokenBalanceAsync(UInt160.Zero.ToString(), address1); @@ -76,10 +76,10 @@ public async Task TestGetTokenBalance() [TestMethod] public async Task TestClaimGas() { - byte[] balanceScript = NativeContract.NEO.Hash.MakeScript("balanceOf", sender); + byte[] balanceScript = NativeContract.NEO.Hash.MakeScript("balanceOf", true, sender); UT_TransactionManager.MockInvokeScript(rpcClientMock, balanceScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_00000000) }); - byte[] testScript = NativeContract.NEO.Hash.MakeScript("transfer", sender, sender, new BigInteger(1_00000000), null); + byte[] testScript = NativeContract.NEO.Hash.MakeScript("transfer", true, sender, sender, new BigInteger(1_00000000), null); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); var json = new JObject(); @@ -93,10 +93,10 @@ public async Task TestClaimGas() [TestMethod] public async Task TestTransfer() { - byte[] decimalsScript = NativeContract.GAS.Hash.MakeScript("decimals"); + byte[] decimalsScript = NativeContract.GAS.Hash.MakeScript("decimals", true); UT_TransactionManager.MockInvokeScript(rpcClientMock, decimalsScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(8) }); - byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", sender, UInt160.Zero, NativeContract.GAS.Factor * 100, null); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", true, sender, UInt160.Zero, NativeContract.GAS.Factor * 100, null); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); var json = new JObject(); @@ -110,15 +110,15 @@ public async Task TestTransfer() [TestMethod] public async Task TestTransferfromMultiSigAccount() { - byte[] balanceScript = NativeContract.GAS.Hash.MakeScript("balanceOf", multiSender); + byte[] balanceScript = NativeContract.GAS.Hash.MakeScript("balanceOf", true, multiSender); var balanceResult = new ContractParameter() { Type = ContractParameterType.Integer, Value = BigInteger.Parse("10000000000000000") }; UT_TransactionManager.MockInvokeScript(rpcClientMock, balanceScript, balanceResult); - byte[] decimalsScript = NativeContract.GAS.Hash.MakeScript("decimals"); + byte[] decimalsScript = NativeContract.GAS.Hash.MakeScript("decimals", true); UT_TransactionManager.MockInvokeScript(rpcClientMock, decimalsScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(8) }); - byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", multiSender, UInt160.Zero, NativeContract.GAS.Factor * 100, null); + byte[] testScript = NativeContract.GAS.Hash.MakeScript("transfer", true, multiSender, UInt160.Zero, NativeContract.GAS.Factor * 100, null); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); var json = new JObject(); @@ -138,7 +138,7 @@ public async Task TestTransferfromMultiSigAccount() Assert.AreEqual(e.Message, $"Need at least 2 KeyPairs for signing!"); } - testScript = NativeContract.GAS.Hash.MakeScript("transfer", multiSender, UInt160.Zero, NativeContract.GAS.Factor * 100, string.Empty); + testScript = NativeContract.GAS.Hash.MakeScript("transfer", true, multiSender, UInt160.Zero, NativeContract.GAS.Factor * 100, string.Empty); UT_TransactionManager.MockInvokeScript(rpcClientMock, testScript, new ContractParameter { Type = ContractParameterType.Integer, Value = new BigInteger(1_10000000) }); tranaction = await walletAPI.TransferAsync(NativeContract.GAS.Hash, 1, new[] { keyPair1.PublicKey }, new[] { keyPair1 }, UInt160.Zero, NativeContract.GAS.Factor * 100, string.Empty); From b55fb1b7a327a439a022f473d463a0ac408634cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Tue, 29 Dec 2020 16:28:12 +0800 Subject: [PATCH 14/17] Update RpcTestCases.json --- tests/Neo.Network.RPC.Tests/RpcTestCases.json | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index c62c64d5e..d35f0bf0f 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -1135,6 +1135,28 @@ } } }, + { + "Name": "invokescriptasync", + "Request": { + "jsonrpc": "2.0", + "id": 1, + "method": "invokescript", + "params": [ + "EBEfDAhkZWNpbWFscwwU++3+LtIiZZK2SMTal7nJzV3BpqZBYn1bUg==" + ] + }, + "Response": { + "jsonrpc": "2.0", + "id": 1, + "result": { + "script": "EBEfDAhkZWNpbWFscwwU++3+LtIiZZK2SMTal7nJzV3BpqZBYn1bUg==", + "state": "FAULT", + "gasconsumed": "0.0000057", + "exception": "The given key '1381727586' was not present in the dictionary.", + "stack": [] + } + } + }, { "Name": "getnewaddressasync", "Request": { From 2b71a69d9ea6a487fd63f9a4e18f6c963f5b4c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Tue, 29 Dec 2020 16:36:49 +0800 Subject: [PATCH 15/17] Update RpcTestCases.json --- tests/Neo.Network.RPC.Tests/RpcTestCases.json | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index d35f0bf0f..4ffadec7a 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -1150,10 +1150,15 @@ "id": 1, "result": { "script": "EBEfDAhkZWNpbWFscwwU++3+LtIiZZK2SMTal7nJzV3BpqZBYn1bUg==", - "state": "FAULT", - "gasconsumed": "0.0000057", - "exception": "The given key '1381727586' was not present in the dictionary.", - "stack": [] + "state": "HALT", + "gasconsumed": "0.0099918", + "exception": null, + "stack": [ + { + "type": "Integer", + "value": "8" + } + ] } } }, From f28b1ef84ac1d912c888d1938ae1dcd4873aea06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Tue, 29 Dec 2020 16:39:46 +0800 Subject: [PATCH 16/17] Update ContractClient.cs --- src/RpcClient/ContractClient.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/RpcClient/ContractClient.cs b/src/RpcClient/ContractClient.cs index 3aea771a4..280ea08a1 100644 --- a/src/RpcClient/ContractClient.cs +++ b/src/RpcClient/ContractClient.cs @@ -42,7 +42,6 @@ public ContractClient(RpcClient rpc, uint? magic = null) public Task TestInvokeAsync(UInt160 scriptHash, string operation, params object[] args) { byte[] script = scriptHash.MakeScript(operation, true, args); - var base64 = System.Convert.ToBase64String(script); return rpcClient.InvokeScriptAsync(script); } From ba866ed3356f498c2b4ed0c73c14df158566b516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Wed, 30 Dec 2020 10:17:30 +0800 Subject: [PATCH 17/17] Update RpcNep17Tracker.cs --- src/RpcNep17Tracker/RpcNep17Tracker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RpcNep17Tracker/RpcNep17Tracker.cs b/src/RpcNep17Tracker/RpcNep17Tracker.cs index 79fbafa7c..573e1633c 100644 --- a/src/RpcNep17Tracker/RpcNep17Tracker.cs +++ b/src/RpcNep17Tracker/RpcNep17Tracker.cs @@ -170,7 +170,7 @@ public void OnPersist(StoreView snapshot, IReadOnlyList