From 8ec8a20599c40e5fe41302954f41bdfe83b6d147 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Wed, 11 Dec 2019 16:19:53 +0800 Subject: [PATCH] More optimizations about Span (#1352) --- src/neo/Cryptography/Crypto.cs | 8 +++--- src/neo/SmartContract/InteropService.NEO.cs | 4 +-- src/neo/SmartContract/InteropService.cs | 25 ++++++++----------- .../SmartContract/Native/PolicyContract.cs | 4 +-- .../SmartContract/Native/Tokens/NeoToken.cs | 4 +-- .../SmartContract/Native/Tokens/Nep5Token.cs | 6 ++--- src/neo/UInt160.cs | 2 +- src/neo/Wallets/Helper.cs | 2 +- 8 files changed, 26 insertions(+), 29 deletions(-) diff --git a/src/neo/Cryptography/Crypto.cs b/src/neo/Cryptography/Crypto.cs index bef425a044..ee7b1418c8 100644 --- a/src/neo/Cryptography/Crypto.cs +++ b/src/neo/Cryptography/Crypto.cs @@ -32,13 +32,13 @@ public static byte[] Sign(byte[] message, byte[] prikey, byte[] pubkey) } } - public static bool VerifySignature(ReadOnlySpan message, ReadOnlySpan signature, byte[] pubkey) + public static bool VerifySignature(ReadOnlySpan message, ReadOnlySpan signature, ReadOnlySpan pubkey) { if (pubkey.Length == 33 && (pubkey[0] == 0x02 || pubkey[0] == 0x03)) { try { - pubkey = ECC.ECPoint.DecodePoint(pubkey, ECC.ECCurve.Secp256r1).EncodePoint(false)[1..]; + pubkey = ECC.ECPoint.DecodePoint(pubkey, ECC.ECCurve.Secp256r1).EncodePoint(false).AsSpan(1); } catch { @@ -58,8 +58,8 @@ public static bool VerifySignature(ReadOnlySpan message, ReadOnlySpan engine.ScriptContainer.GetHashData(), _ => item0.GetSpan() }; - byte[] pubkey = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + ReadOnlySpan pubkey = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); ReadOnlySpan signature = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); try { @@ -162,7 +162,7 @@ private static bool Crypto_ECDsaCheckMultiSig(ApplicationEngine engine) private static bool Account_IsStandard(ApplicationEngine engine) { - UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray()); + UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetSpan()); ContractState contract = engine.Snapshot.Contracts.TryGet(hash); bool isStandard = contract is null || contract.Script.IsStandardContract(); engine.CurrentContext.EvaluationStack.Push(isStandard); diff --git a/src/neo/SmartContract/InteropService.cs b/src/neo/SmartContract/InteropService.cs index cd30deca8f..def6184619 100644 --- a/src/neo/SmartContract/InteropService.cs +++ b/src/neo/SmartContract/InteropService.cs @@ -13,7 +13,6 @@ using System.Numerics; using System.Text; using Array = Neo.VM.Types.Array; -using Boolean = Neo.VM.Types.Boolean; namespace Neo.SmartContract { @@ -77,10 +76,8 @@ private static bool CheckItemForNotification(StackItem state) items_unchecked.Enqueue(item); } break; - case Boolean _: - case ByteArray _: - case Integer _: - size += state.GetByteLength(); + case PrimitiveType primitive: + size += primitive.GetByteLength(); break; case Null _: break; @@ -231,7 +228,7 @@ private static bool Runtime_CheckWitness(ApplicationEngine engine) ReadOnlySpan hashOrPubkey = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); bool result; if (hashOrPubkey.Length == 20) - result = CheckWitness(engine, new UInt160(hashOrPubkey.ToArray())); + result = CheckWitness(engine, new UInt160(hashOrPubkey)); else if (hashOrPubkey.Length == 33) result = CheckWitness(engine, ECPoint.DecodePoint(hashOrPubkey, ECCurve.Secp256r1)); else @@ -250,7 +247,7 @@ private static bool Runtime_Notify(ApplicationEngine engine) private static bool Runtime_Log(ApplicationEngine engine) { - byte[] state = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + ReadOnlySpan state = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); if (state.Length > MaxNotificationSize) return false; string message = Encoding.UTF8.GetString(state); engine.SendLog(engine.CurrentScriptHash, message); @@ -287,7 +284,7 @@ private static bool Runtime_GetNotifications(ApplicationEngine engine) IEnumerable notifications = engine.Notifications; if (!item.IsNull) // must filter by scriptHash { - var hash = new UInt160(item.GetSpan().ToArray()); + var hash = new UInt160(item.GetSpan()); notifications = notifications.Where(p => p.ScriptHash == hash); } @@ -334,7 +331,7 @@ private static bool Blockchain_GetHeight(ApplicationEngine engine) private static bool Blockchain_GetBlock(ApplicationEngine engine) { - byte[] data = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + ReadOnlySpan data = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); UInt256 hash; if (data.Length <= 5) hash = Blockchain.Singleton.GetBlockHash((uint)new BigInteger(data)); @@ -353,7 +350,7 @@ private static bool Blockchain_GetBlock(ApplicationEngine engine) private static bool Blockchain_GetTransaction(ApplicationEngine engine) { - byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + ReadOnlySpan hash = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); Transaction tx = engine.Snapshot.GetTransaction(new UInt256(hash)); if (tx == null) engine.CurrentContext.EvaluationStack.Push(StackItem.Null); @@ -364,7 +361,7 @@ private static bool Blockchain_GetTransaction(ApplicationEngine engine) private static bool Blockchain_GetTransactionHeight(ApplicationEngine engine) { - byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + ReadOnlySpan hash = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); var tx = engine.Snapshot.Transactions.TryGet(new UInt256(hash)); engine.CurrentContext.EvaluationStack.Push(tx != null ? new BigInteger(tx.BlockIndex) : BigInteger.MinusOne); return true; @@ -372,7 +369,7 @@ private static bool Blockchain_GetTransactionHeight(ApplicationEngine engine) private static bool Blockchain_GetTransactionFromBlock(ApplicationEngine engine) { - byte[] data = engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray(); + ReadOnlySpan data = engine.CurrentContext.EvaluationStack.Pop().GetSpan(); UInt256 hash; if (data.Length <= 5) hash = Blockchain.Singleton.GetBlockHash((uint)new BigInteger(data)); @@ -402,7 +399,7 @@ private static bool Blockchain_GetTransactionFromBlock(ApplicationEngine engine) private static bool Blockchain_GetContract(ApplicationEngine engine) { - UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetSpan().ToArray()); + UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetSpan()); ContractState contract = engine.Snapshot.Contracts.TryGet(hash); if (contract == null) engine.CurrentContext.EvaluationStack.Push(StackItem.Null); @@ -470,7 +467,7 @@ private static bool Contract_Call(ApplicationEngine engine) { StackItem contractHash = engine.CurrentContext.EvaluationStack.Pop(); - ContractState contract = engine.Snapshot.Contracts.TryGet(new UInt160(contractHash.GetSpan().ToArray())); + ContractState contract = engine.Snapshot.Contracts.TryGet(new UInt160(contractHash.GetSpan())); if (contract is null) return false; StackItem method = engine.CurrentContext.EvaluationStack.Pop(); diff --git a/src/neo/SmartContract/Native/PolicyContract.cs b/src/neo/SmartContract/Native/PolicyContract.cs index d51e1a75b3..e9b7984bce 100644 --- a/src/neo/SmartContract/Native/PolicyContract.cs +++ b/src/neo/SmartContract/Native/PolicyContract.cs @@ -145,7 +145,7 @@ private StackItem SetFeePerByte(ApplicationEngine engine, Array args) private StackItem BlockAccount(ApplicationEngine engine, Array args) { if (!CheckValidators(engine)) return false; - UInt160 account = new UInt160(args[0].GetSpan().ToArray()); + UInt160 account = new UInt160(args[0].GetSpan()); StorageKey key = CreateStorageKey(Prefix_BlockedAccounts); StorageItem storage = engine.Snapshot.Storages[key]; SortedSet accounts = new SortedSet(storage.Value.AsSerializableArray()); @@ -159,7 +159,7 @@ private StackItem BlockAccount(ApplicationEngine engine, Array args) private StackItem UnblockAccount(ApplicationEngine engine, Array args) { if (!CheckValidators(engine)) return false; - UInt160 account = new UInt160(args[0].GetSpan().ToArray()); + UInt160 account = new UInt160(args[0].GetSpan()); StorageKey key = CreateStorageKey(Prefix_BlockedAccounts); StorageItem storage = engine.Snapshot.Storages[key]; SortedSet accounts = new SortedSet(storage.Value.AsSerializableArray()); diff --git a/src/neo/SmartContract/Native/Tokens/NeoToken.cs b/src/neo/SmartContract/Native/Tokens/NeoToken.cs index 3e8f79ad96..546cb17032 100644 --- a/src/neo/SmartContract/Native/Tokens/NeoToken.cs +++ b/src/neo/SmartContract/Native/Tokens/NeoToken.cs @@ -119,7 +119,7 @@ protected override bool OnPersist(ApplicationEngine engine) [ContractMethod(0_03000000, ContractParameterType.Integer, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Integer }, ParameterNames = new[] { "account", "end" }, SafeMethod = true)] private StackItem UnclaimedGas(ApplicationEngine engine, Array args) { - UInt160 account = new UInt160(args[0].GetSpan().ToArray()); + UInt160 account = new UInt160(args[0].GetSpan()); uint end = (uint)args[1].GetBigInteger(); return UnclaimedGas(engine.Snapshot, account, end); } @@ -153,7 +153,7 @@ private bool RegisterValidator(StoreView snapshot, ECPoint pubkey) [ContractMethod(5_00000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Array }, ParameterNames = new[] { "account", "pubkeys" })] private StackItem Vote(ApplicationEngine engine, Array args) { - UInt160 account = new UInt160(args[0].GetSpan().ToArray()); + UInt160 account = new UInt160(args[0].GetSpan()); ECPoint[] pubkeys = ((Array)args[1]).Select(p => p.GetSpan().AsSerializable()).ToArray(); if (!InteropService.CheckWitness(engine, account)) return false; StorageKey key_account = CreateAccountKey(account); diff --git a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs index 0ee3952350..fa9d779ace 100644 --- a/src/neo/SmartContract/Native/Tokens/Nep5Token.cs +++ b/src/neo/SmartContract/Native/Tokens/Nep5Token.cs @@ -149,7 +149,7 @@ public virtual BigInteger TotalSupply(StoreView snapshot) [ContractMethod(0_01000000, ContractParameterType.Integer, ParameterTypes = new[] { ContractParameterType.Hash160 }, ParameterNames = new[] { "account" }, SafeMethod = true)] protected StackItem BalanceOf(ApplicationEngine engine, Array args) { - return BalanceOf(engine.Snapshot, new UInt160(args[0].GetSpan().ToArray())); + return BalanceOf(engine.Snapshot, new UInt160(args[0].GetSpan())); } public virtual BigInteger BalanceOf(StoreView snapshot, UInt160 account) @@ -163,8 +163,8 @@ public virtual BigInteger BalanceOf(StoreView snapshot, UInt160 account) [ContractMethod(0_08000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Hash160, ContractParameterType.Integer }, ParameterNames = new[] { "from", "to", "amount" })] protected StackItem Transfer(ApplicationEngine engine, Array args) { - UInt160 from = new UInt160(args[0].GetSpan().ToArray()); - UInt160 to = new UInt160(args[1].GetSpan().ToArray()); + UInt160 from = new UInt160(args[0].GetSpan()); + UInt160 to = new UInt160(args[1].GetSpan()); BigInteger amount = args[2].GetBigInteger(); return Transfer(engine, from, to, amount); } diff --git a/src/neo/UInt160.cs b/src/neo/UInt160.cs index e2ce4e5bcf..69c2f85ed1 100644 --- a/src/neo/UInt160.cs +++ b/src/neo/UInt160.cs @@ -22,7 +22,7 @@ public UInt160() { } - public unsafe UInt160(byte[] value) + public unsafe UInt160(ReadOnlySpan value) { fixed (ulong* p = &value1) { diff --git a/src/neo/Wallets/Helper.cs b/src/neo/Wallets/Helper.cs index c5b203df90..712c2585de 100644 --- a/src/neo/Wallets/Helper.cs +++ b/src/neo/Wallets/Helper.cs @@ -28,7 +28,7 @@ public static UInt160 ToScriptHash(this string address) throw new FormatException(); if (data[0] != ProtocolSettings.Default.AddressVersion) throw new FormatException(); - return new UInt160(data[1..]); + return new UInt160(data.AsSpan(1)); } internal static byte[] XOR(byte[] x, byte[] y)