From 96437eab2f0a279cfc479df96feb1597df06bea1 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 09:58:27 +0800 Subject: [PATCH 01/36] nullable and use nullable network --- src/Neo/Neo.csproj | 1 + src/Neo/Network/P2P/ChannelsConfig.cs | 2 +- src/Neo/Network/P2P/Connection.cs | 16 +-- src/Neo/Network/P2P/LocalNode.cs | 16 +-- src/Neo/Network/P2P/Message.cs | 6 +- src/Neo/Network/P2P/Payloads/AddrPayload.cs | 2 +- src/Neo/Network/P2P/Payloads/Block.cs | 10 +- .../P2P/Payloads/Conditions/AndCondition.cs | 8 +- .../Payloads/Conditions/BooleanCondition.cs | 4 +- .../Conditions/CalledByContractCondition.cs | 8 +- .../Conditions/CalledByEntryCondition.cs | 2 +- .../Conditions/CalledByGroupCondition.cs | 10 +- .../P2P/Payloads/Conditions/GroupCondition.cs | 10 +- .../P2P/Payloads/Conditions/NotCondition.cs | 6 +- .../P2P/Payloads/Conditions/OrCondition.cs | 8 +- .../Conditions/ScriptHashCondition.cs | 8 +- .../Payloads/Conditions/WitnessCondition.cs | 4 +- src/Neo/Network/P2P/Payloads/Conflicts.cs | 2 +- .../Network/P2P/Payloads/ExtensiblePayload.cs | 8 +- .../Network/P2P/Payloads/GetBlocksPayload.cs | 2 +- src/Neo/Network/P2P/Payloads/Header.cs | 22 ++--- .../Network/P2P/Payloads/HeadersPayload.cs | 2 +- src/Neo/Network/P2P/Payloads/InvPayload.cs | 2 +- .../P2P/Payloads/MerkleBlockPayload.cs | 4 +- .../P2P/Payloads/NetworkAddressWithTime.cs | 4 +- .../Network/P2P/Payloads/OracleResponse.cs | 2 +- src/Neo/Network/P2P/Payloads/Signer.cs | 24 ++--- src/Neo/Network/P2P/Payloads/Transaction.cs | 26 ++--- .../Network/P2P/Payloads/VersionPayload.cs | 4 +- src/Neo/Network/P2P/Payloads/Witness.cs | 2 +- src/Neo/Network/P2P/Payloads/WitnessRule.cs | 10 +- src/Neo/Network/P2P/Peer.cs | 12 +-- .../Network/P2P/RemoteNode.ProtocolHandler.cs | 99 ++++++++++--------- src/Neo/Network/P2P/RemoteNode.cs | 18 ++-- src/Neo/Network/P2P/TaskManager.cs | 24 ++--- src/Neo/Network/UPnP.cs | 22 ++--- 36 files changed, 207 insertions(+), 203 deletions(-) diff --git a/src/Neo/Neo.csproj b/src/Neo/Neo.csproj index 234fbc62c6..4d874a3dfa 100644 --- a/src/Neo/Neo.csproj +++ b/src/Neo/Neo.csproj @@ -3,6 +3,7 @@ netstandard2.1;net7.0 true + enable NEO;AntShares;Blockchain;Smart Contract diff --git a/src/Neo/Network/P2P/ChannelsConfig.cs b/src/Neo/Network/P2P/ChannelsConfig.cs index cc64242066..ed16569264 100644 --- a/src/Neo/Network/P2P/ChannelsConfig.cs +++ b/src/Neo/Network/P2P/ChannelsConfig.cs @@ -21,7 +21,7 @@ public class ChannelsConfig /// /// Tcp configuration. /// - public IPEndPoint Tcp { get; set; } + public IPEndPoint Tcp { get; set; } = null!; /// /// Minimum desired connections. diff --git a/src/Neo/Network/P2P/Connection.cs b/src/Neo/Network/P2P/Connection.cs index 53e30a2bde..2a4d0228a7 100644 --- a/src/Neo/Network/P2P/Connection.cs +++ b/src/Neo/Network/P2P/Connection.cs @@ -45,8 +45,8 @@ internal class Close { public bool Abort; } public IPEndPoint Local { get; } private ICancelable timer; - private readonly IActorRef tcp; - private bool disconnected = false; + private readonly IActorRef? _tcp; + private bool disconnected; /// /// Initializes a new instance of the class. @@ -62,7 +62,7 @@ protected Connection(object connection, IPEndPoint remote, IPEndPoint local) switch (connection) { case IActorRef tcp: - this.tcp = tcp; + this._tcp = tcp; break; } } @@ -74,9 +74,9 @@ protected Connection(object connection, IPEndPoint remote, IPEndPoint local) public void Disconnect(bool abort = false) { disconnected = true; - if (tcp != null) + if (_tcp != null) { - tcp.Tell(abort ? Tcp.Abort.Instance : Tcp.Close.Instance); + _tcp.Tell(abort ? Tcp.Abort.Instance : Tcp.Close.Instance); } Context.Stop(Self); } @@ -130,7 +130,7 @@ private void OnReceived(ByteString data) protected override void PostStop() { if (!disconnected) - tcp?.Tell(Tcp.Close.Instance); + _tcp?.Tell(Tcp.Close.Instance); timer.CancelIfNotNull(); base.PostStop(); } @@ -141,9 +141,9 @@ protected override void PostStop() /// protected void SendData(ByteString data) { - if (tcp != null) + if (_tcp != null) { - tcp.Tell(Tcp.Write.Create(data, Ack.Instance)); + _tcp.Tell(Tcp.Write.Create(data, Ack.Instance)); } } } diff --git a/src/Neo/Network/P2P/LocalNode.cs b/src/Neo/Network/P2P/LocalNode.cs index f0bce492d5..ae6b4e664d 100644 --- a/src/Neo/Network/P2P/LocalNode.cs +++ b/src/Neo/Network/P2P/LocalNode.cs @@ -31,12 +31,12 @@ public class LocalNode : Peer /// /// Sent to to relay an . /// - public class RelayDirectly { public IInventory Inventory; } + public class RelayDirectly { public IInventory Inventory = null!; } /// /// Sent to to send an . /// - public class SendDirectly { public IInventory Inventory; } + public class SendDirectly { public IInventory Inventory = null!; } /// /// Sent to to request for an instance of . @@ -49,7 +49,7 @@ public class GetInstance { } public const uint ProtocolVersion = 0; private const int MaxCountFromSeedList = 5; - private readonly IPEndPoint[] SeedList; + private readonly IPEndPoint?[] SeedList; private readonly NeoSystem system; internal readonly ConcurrentDictionary RemoteNodes = new(); @@ -105,7 +105,7 @@ public LocalNode(NeoSystem system) /// /// The message command to be packed. /// Optional payload to be Serialized along the message. - private void BroadcastMessage(MessageCommand command, ISerializable payload = null) + private void BroadcastMessage(MessageCommand command, ISerializable? payload = null) { BroadcastMessage(Message.Create(command, payload)); } @@ -127,9 +127,9 @@ private void SendToRemoteNodes(object message) } } - private static IPEndPoint GetIPEndpointFromHostPort(string hostNameOrAddress, int port) + private static IPEndPoint? GetIPEndpointFromHostPort(string hostNameOrAddress, int port) { - if (IPAddress.TryParse(hostNameOrAddress, out IPAddress ipAddress)) + if (IPAddress.TryParse(hostNameOrAddress, out IPAddress? ipAddress)) return new IPEndPoint(ipAddress, port); IPHostEntry entry; try @@ -145,7 +145,7 @@ private static IPEndPoint GetIPEndpointFromHostPort(string hostNameOrAddress, in return new IPEndPoint(ipAddress, port); } - internal static IPEndPoint GetIpEndPoint(string hostAndPort) + internal static IPEndPoint? GetIpEndPoint(string hostAndPort) { if (string.IsNullOrEmpty(hostAndPort)) return null; @@ -221,7 +221,7 @@ protected override void NeedMorePeers(int count) // It will try to add those, sequentially, to the list of currently unconnected ones. Random rand = new(); - AddPeers(SeedList.Where(u => u != null).OrderBy(p => rand.Next()).Take(count)); + AddPeers(SeedList.Where(u => u != null).OrderBy(p => rand.Next()).Take(count)!); } } diff --git a/src/Neo/Network/P2P/Message.cs b/src/Neo/Network/P2P/Message.cs index 9d3c63a85b..5baba051aa 100644 --- a/src/Neo/Network/P2P/Message.cs +++ b/src/Neo/Network/P2P/Message.cs @@ -44,7 +44,7 @@ public class Message : ISerializable /// /// The payload of the message. /// - public ISerializable Payload; + public ISerializable? Payload; private ReadOnlyMemory _payload_compressed; @@ -56,7 +56,7 @@ public class Message : ISerializable /// The command of the message. /// The payload of the message. For the messages that don't require a payload, it should be . /// - public static Message Create(MessageCommand command, ISerializable payload = null) + public static Message Create(MessageCommand command, ISerializable? payload = null) { Message message = new() { @@ -114,7 +114,7 @@ void ISerializable.Serialize(BinaryWriter writer) writer.WriteVarBytes(_payload_compressed.Span); } - internal static int TryDeserialize(ByteString data, out Message msg) + internal static int TryDeserialize(ByteString data, out Message? msg) { msg = null; if (data.Count < 3) return 0; diff --git a/src/Neo/Network/P2P/Payloads/AddrPayload.cs b/src/Neo/Network/P2P/Payloads/AddrPayload.cs index ebdceb65ec..b1ddc158c3 100644 --- a/src/Neo/Network/P2P/Payloads/AddrPayload.cs +++ b/src/Neo/Network/P2P/Payloads/AddrPayload.cs @@ -28,7 +28,7 @@ public class AddrPayload : ISerializable /// /// The list of nodes. /// - public NetworkAddressWithTime[] AddressList; + public NetworkAddressWithTime[] AddressList = null!; public int Size => AddressList.GetVarSize(); diff --git a/src/Neo/Network/P2P/Payloads/Block.cs b/src/Neo/Network/P2P/Payloads/Block.cs index 3c727b9886..71627aab3c 100644 --- a/src/Neo/Network/P2P/Payloads/Block.cs +++ b/src/Neo/Network/P2P/Payloads/Block.cs @@ -28,12 +28,12 @@ public sealed class Block : IEquatable, IInventory /// /// The header of the block. /// - public Header Header; + public Header Header = null!; /// /// The transaction list of the block. /// - public Transaction[] Transactions; + public Transaction[] Transactions = Array.Empty(); public UInt256 Hash => Header.Hash; @@ -92,20 +92,20 @@ public void Deserialize(ref MemoryReader reader) Transactions = reader.ReadSerializableArray(ushort.MaxValue); if (Transactions.Distinct().Count() != Transactions.Length) throw new FormatException(); - if (MerkleTree.ComputeRoot(Transactions.Select(p => p.Hash).ToArray()) != Header.MerkleRoot) + if (MerkleTree.ComputeRoot(Transactions.Select(p => p!.Hash).ToArray()) != Header.MerkleRoot) throw new FormatException(); } void IVerifiable.DeserializeUnsigned(ref MemoryReader reader) => throw new NotSupportedException(); - public bool Equals(Block other) + public bool Equals(Block? other) { if (ReferenceEquals(this, other)) return true; if (other is null) return false; return Hash.Equals(other.Hash); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as Block); } diff --git a/src/Neo/Network/P2P/Payloads/Conditions/AndCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/AndCondition.cs index e395b10d5d..2a966779d4 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/AndCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/AndCondition.cs @@ -28,7 +28,7 @@ public class AndCondition : WitnessCondition /// /// The expressions of the condition. /// - public WitnessCondition[] Expressions; + public WitnessCondition[] Expressions = null!; public override int Size => base.Size + Expressions.GetVarSize(); public override WitnessConditionType Type => WitnessConditionType.And; @@ -53,9 +53,9 @@ protected override void SerializeWithoutType(BinaryWriter writer) private protected override void ParseJson(JObject json, int maxNestDepth) { if (maxNestDepth <= 0) throw new FormatException(); - JArray expressions = (JArray)json["expressions"]; + JArray expressions = (JArray)json["expressions"]!; if (expressions.Count > MaxSubitems) throw new FormatException(); - Expressions = expressions.Select(p => FromJson((JObject)p, maxNestDepth - 1)).ToArray(); + Expressions = expressions.Select(p => FromJson((JObject)p!, maxNestDepth - 1)).ToArray(); if (Expressions.Length == 0) throw new FormatException(); } @@ -66,7 +66,7 @@ public override JObject ToJson() return json; } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { var result = (VM.Types.Array)base.ToStackItem(referenceCounter); result.Add(new VM.Types.Array(referenceCounter, Expressions.Select(p => p.ToStackItem(referenceCounter)))); diff --git a/src/Neo/Network/P2P/Payloads/Conditions/BooleanCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/BooleanCondition.cs index e7609fcbaf..78d3fea230 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/BooleanCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/BooleanCondition.cs @@ -45,7 +45,7 @@ protected override void SerializeWithoutType(BinaryWriter writer) private protected override void ParseJson(JObject json, int maxNestDepth) { - Expression = json["expression"].GetBoolean(); + Expression = json["expression"]!.GetBoolean(); } public override JObject ToJson() @@ -55,7 +55,7 @@ public override JObject ToJson() return json; } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { var result = (VM.Types.Array)base.ToStackItem(referenceCounter); result.Add(Expression); diff --git a/src/Neo/Network/P2P/Payloads/Conditions/CalledByContractCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/CalledByContractCondition.cs index f853743b72..8643b9a1e7 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/CalledByContractCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/CalledByContractCondition.cs @@ -23,7 +23,7 @@ public class CalledByContractCondition : WitnessCondition /// /// The script hash to be checked. /// - public UInt160 Hash; + public UInt160 Hash = null!; public override int Size => base.Size + UInt160.Length; public override WitnessConditionType Type => WitnessConditionType.CalledByContract; @@ -45,7 +45,7 @@ protected override void SerializeWithoutType(BinaryWriter writer) private protected override void ParseJson(JObject json, int maxNestDepth) { - Hash = UInt160.Parse(json["hash"].GetString()); + Hash = UInt160.Parse(json["hash"]!.GetString()); } public override JObject ToJson() @@ -55,9 +55,9 @@ public override JObject ToJson() return json; } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { - var result = (VM.Types.Array)base.ToStackItem(referenceCounter); + var result = (Array)base.ToStackItem(referenceCounter); result.Add(Hash.ToArray()); return result; } diff --git a/src/Neo/Network/P2P/Payloads/Conditions/CalledByEntryCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/CalledByEntryCondition.cs index 8f8e21f80a..5a7a457a5f 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/CalledByEntryCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/CalledByEntryCondition.cs @@ -22,7 +22,7 @@ public class CalledByEntryCondition : WitnessCondition public override bool Match(ApplicationEngine engine) { - var state = engine.CurrentContext.GetState(); + var state = engine.CurrentContext!.GetState(); if (state.CallingContext is null) return true; state = state.CallingContext.GetState(); return state.CallingContext is null; diff --git a/src/Neo/Network/P2P/Payloads/Conditions/CalledByGroupCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/CalledByGroupCondition.cs index 82dab60fcf..98cca9b859 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/CalledByGroupCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/CalledByGroupCondition.cs @@ -26,7 +26,7 @@ public class CalledByGroupCondition : WitnessCondition /// /// The group to be checked. /// - public ECPoint Group; + public ECPoint Group = null!; public override int Size => base.Size + Group.Size; public override WitnessConditionType Type => WitnessConditionType.CalledByGroup; @@ -39,7 +39,7 @@ protected override void DeserializeWithoutType(ref MemoryReader reader, int maxN public override bool Match(ApplicationEngine engine) { engine.ValidateCallFlags(CallFlags.ReadStates); - ContractState contract = NativeContract.ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash); + ContractState? contract = NativeContract.ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash.NotNull()); return contract is not null && contract.Manifest.Groups.Any(p => p.PubKey.Equals(Group)); } @@ -50,7 +50,7 @@ protected override void SerializeWithoutType(BinaryWriter writer) private protected override void ParseJson(JObject json, int maxNestDepth) { - Group = ECPoint.Parse(json["group"].GetString(), ECCurve.Secp256r1); + Group = ECPoint.Parse(json["group"]!.GetString(), ECCurve.Secp256r1); } public override JObject ToJson() @@ -60,9 +60,9 @@ public override JObject ToJson() return json; } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { - var result = (VM.Types.Array)base.ToStackItem(referenceCounter); + var result = (Array)base.ToStackItem(referenceCounter); result.Add(Group.ToArray()); return result; } diff --git a/src/Neo/Network/P2P/Payloads/Conditions/GroupCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/GroupCondition.cs index ee937aff8b..889e37003c 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/GroupCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/GroupCondition.cs @@ -26,7 +26,7 @@ public class GroupCondition : WitnessCondition /// /// The group to be checked. /// - public ECPoint Group; + public ECPoint Group = null!; public override int Size => base.Size + Group.Size; public override WitnessConditionType Type => WitnessConditionType.Group; @@ -39,7 +39,7 @@ protected override void DeserializeWithoutType(ref MemoryReader reader, int maxN public override bool Match(ApplicationEngine engine) { engine.ValidateCallFlags(CallFlags.ReadStates); - ContractState contract = NativeContract.ContractManagement.GetContract(engine.Snapshot, engine.CurrentScriptHash); + ContractState? contract = NativeContract.ContractManagement.GetContract(engine.Snapshot, engine.CurrentScriptHash!); return contract is not null && contract.Manifest.Groups.Any(p => p.PubKey.Equals(Group)); } @@ -50,7 +50,7 @@ protected override void SerializeWithoutType(BinaryWriter writer) private protected override void ParseJson(JObject json, int maxNestDepth) { - Group = ECPoint.Parse(json["group"].GetString(), ECCurve.Secp256r1); + Group = ECPoint.Parse(json["group"]!.GetString(), ECCurve.Secp256r1); } public override JObject ToJson() @@ -60,9 +60,9 @@ public override JObject ToJson() return json; } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { - var result = (VM.Types.Array)base.ToStackItem(referenceCounter); + var result = (Array)base.ToStackItem(referenceCounter); result.Add(Group.ToArray()); return result; } diff --git a/src/Neo/Network/P2P/Payloads/Conditions/NotCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/NotCondition.cs index 83ecd4d973..680e7edac9 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/NotCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/NotCondition.cs @@ -27,7 +27,7 @@ public class NotCondition : WitnessCondition /// /// The expression of the condition to be reversed. /// - public WitnessCondition Expression; + public WitnessCondition Expression = null!; public override int Size => base.Size + Expression.Size; public override WitnessConditionType Type => WitnessConditionType.Not; @@ -51,7 +51,7 @@ protected override void SerializeWithoutType(BinaryWriter writer) private protected override void ParseJson(JObject json, int maxNestDepth) { if (maxNestDepth <= 0) throw new FormatException(); - Expression = FromJson((JObject)json["expression"], maxNestDepth - 1); + Expression = FromJson((JObject)json["expression"]!, maxNestDepth - 1); } public override JObject ToJson() @@ -61,7 +61,7 @@ public override JObject ToJson() return json; } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { var result = (VM.Types.Array)base.ToStackItem(referenceCounter); result.Add(Expression.ToStackItem(referenceCounter)); diff --git a/src/Neo/Network/P2P/Payloads/Conditions/OrCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/OrCondition.cs index b06fc922a8..ce71d7cf93 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/OrCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/OrCondition.cs @@ -28,7 +28,7 @@ public class OrCondition : WitnessCondition /// /// The expressions of the condition. /// - public WitnessCondition[] Expressions; + public WitnessCondition[] Expressions = null!; public override int Size => base.Size + Expressions.GetVarSize(); public override WitnessConditionType Type => WitnessConditionType.Or; @@ -53,9 +53,9 @@ protected override void SerializeWithoutType(BinaryWriter writer) private protected override void ParseJson(JObject json, int maxNestDepth) { if (maxNestDepth <= 0) throw new FormatException(); - JArray expressions = (JArray)json["expressions"]; + JArray expressions = json["expressions"].NullExceptionOr(); if (expressions.Count > MaxSubitems) throw new FormatException(); - Expressions = expressions.Select(p => FromJson((JObject)p, maxNestDepth - 1)).ToArray(); + Expressions = expressions.Select(p => FromJson(p.NullExceptionOr(), maxNestDepth - 1)).ToArray(); if (Expressions.Length == 0) throw new FormatException(); } @@ -66,7 +66,7 @@ public override JObject ToJson() return json; } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { var result = (VM.Types.Array)base.ToStackItem(referenceCounter); result.Add(new VM.Types.Array(referenceCounter, Expressions.Select(p => p.ToStackItem(referenceCounter)))); diff --git a/src/Neo/Network/P2P/Payloads/Conditions/ScriptHashCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/ScriptHashCondition.cs index 9199e1a9a2..50c69d16b5 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/ScriptHashCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/ScriptHashCondition.cs @@ -23,7 +23,7 @@ public class ScriptHashCondition : WitnessCondition /// /// The script hash to be checked. /// - public UInt160 Hash; + public UInt160 Hash = null!; public override int Size => base.Size + UInt160.Length; public override WitnessConditionType Type => WitnessConditionType.ScriptHash; @@ -45,7 +45,7 @@ protected override void SerializeWithoutType(BinaryWriter writer) private protected override void ParseJson(JObject json, int maxNestDepth) { - Hash = UInt160.Parse(json["hash"].GetString()); + Hash = UInt160.Parse(json["hash"]!.GetString()); } public override JObject ToJson() @@ -55,9 +55,9 @@ public override JObject ToJson() return json; } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { - var result = (VM.Types.Array)base.ToStackItem(referenceCounter); + var result = (Array)base.ToStackItem(referenceCounter); result.Add(Hash.ToArray()); return result; } diff --git a/src/Neo/Network/P2P/Payloads/Conditions/WitnessCondition.cs b/src/Neo/Network/P2P/Payloads/Conditions/WitnessCondition.cs index 7738a6d4a8..3cd9dfbd33 100644 --- a/src/Neo/Network/P2P/Payloads/Conditions/WitnessCondition.cs +++ b/src/Neo/Network/P2P/Payloads/Conditions/WitnessCondition.cs @@ -103,7 +103,7 @@ void ISerializable.Serialize(BinaryWriter writer) /// The converted . public static WitnessCondition FromJson(JObject json, int maxNestDepth) { - WitnessConditionType type = Enum.Parse(json["type"].GetString()); + WitnessConditionType type = Enum.Parse(json["type"]!.GetString()); if (ReflectionCache.CreateInstance(type) is not WitnessCondition condition) throw new FormatException("Invalid WitnessConditionType."); condition.ParseJson(json, maxNestDepth); @@ -127,7 +127,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) throw new NotSupportedException(); } - public virtual StackItem ToStackItem(ReferenceCounter referenceCounter) + public virtual StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new VM.Types.Array(referenceCounter, new StackItem[] { (byte)Type }); } diff --git a/src/Neo/Network/P2P/Payloads/Conflicts.cs b/src/Neo/Network/P2P/Payloads/Conflicts.cs index 082de2014d..3dafba30dc 100644 --- a/src/Neo/Network/P2P/Payloads/Conflicts.cs +++ b/src/Neo/Network/P2P/Payloads/Conflicts.cs @@ -22,7 +22,7 @@ public class Conflicts : TransactionAttribute /// /// Indicates the conflict transaction hash. /// - public UInt256 Hash; + public UInt256 Hash = null!; public override TransactionAttributeType Type => TransactionAttributeType.Conflicts; diff --git a/src/Neo/Network/P2P/Payloads/ExtensiblePayload.cs b/src/Neo/Network/P2P/Payloads/ExtensiblePayload.cs index 306f6327ab..9df2645bd2 100644 --- a/src/Neo/Network/P2P/Payloads/ExtensiblePayload.cs +++ b/src/Neo/Network/P2P/Payloads/ExtensiblePayload.cs @@ -27,7 +27,7 @@ public class ExtensiblePayload : IInventory /// /// The category of the extension. /// - public string Category; + public string Category = null!; /// /// Indicates that the payload is only valid when the block height is greater than or equal to this value. @@ -42,7 +42,7 @@ public class ExtensiblePayload : IInventory /// /// The sender of the payload. /// - public UInt160 Sender; + public UInt160 Sender = null!; /// /// The data of the payload. @@ -52,9 +52,9 @@ public class ExtensiblePayload : IInventory /// /// The witness of the payload. It must match the . /// - public Witness Witness; + public Witness Witness = null!; - private UInt256 _hash = null; + private UInt256? _hash; public UInt256 Hash { get diff --git a/src/Neo/Network/P2P/Payloads/GetBlocksPayload.cs b/src/Neo/Network/P2P/Payloads/GetBlocksPayload.cs index d12c8ae2cd..a8920e24a4 100644 --- a/src/Neo/Network/P2P/Payloads/GetBlocksPayload.cs +++ b/src/Neo/Network/P2P/Payloads/GetBlocksPayload.cs @@ -23,7 +23,7 @@ public class GetBlocksPayload : ISerializable /// /// The starting hash of the blocks to request. /// - public UInt256 HashStart; + public UInt256 HashStart = null!; /// /// The number of blocks to request. diff --git a/src/Neo/Network/P2P/Payloads/Header.cs b/src/Neo/Network/P2P/Payloads/Header.cs index 9e1d77fb8a..d94edfe54a 100644 --- a/src/Neo/Network/P2P/Payloads/Header.cs +++ b/src/Neo/Network/P2P/Payloads/Header.cs @@ -27,18 +27,18 @@ namespace Neo.Network.P2P.Payloads public sealed class Header : IEquatable
, IVerifiable { private uint version; - private UInt256 prevHash; - private UInt256 merkleRoot; + private UInt256 prevHash = null!; + private UInt256 merkleRoot = null!; private ulong timestamp; private ulong nonce; private uint index; private byte primaryIndex; - private UInt160 nextConsensus; + private UInt160 nextConsensus = null!; /// /// The witness of the block. /// - public Witness Witness; + public Witness Witness = null!; /// /// The version of the block. @@ -112,7 +112,7 @@ public UInt160 NextConsensus set { nextConsensus = value; _hash = null; } } - private UInt256 _hash = null; + private UInt256? _hash; public UInt256 Hash { get @@ -171,14 +171,14 @@ void IVerifiable.DeserializeUnsigned(ref MemoryReader reader) nextConsensus = reader.ReadSerializable(); } - public bool Equals(Header other) + public bool Equals(Header? other) { if (other is null) return false; if (ReferenceEquals(other, this)) return true; return Hash.Equals(other.Hash); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as Header); } @@ -191,7 +191,7 @@ public override int GetHashCode() UInt160[] IVerifiable.GetScriptHashesForVerifying(DataCache snapshot) { if (prevHash == UInt256.Zero) return new[] { Witness.ScriptHash }; - TrimmedBlock prev = NativeContract.Ledger.GetTrimmedBlock(snapshot, prevHash); + TrimmedBlock? prev = NativeContract.Ledger.GetTrimmedBlock(snapshot, prevHash); if (prev is null) throw new InvalidOperationException(); return new[] { prev.Header.nextConsensus }; } @@ -199,7 +199,7 @@ UInt160[] IVerifiable.GetScriptHashesForVerifying(DataCache snapshot) public void Serialize(BinaryWriter writer) { ((IVerifiable)this).SerializeUnsigned(writer); - writer.Write(new Witness[] { Witness }); + writer.Write(new[] { Witness }); } void IVerifiable.SerializeUnsigned(BinaryWriter writer) @@ -240,7 +240,7 @@ internal bool Verify(ProtocolSettings settings, DataCache snapshot) { if (primaryIndex >= settings.ValidatorsCount) return false; - TrimmedBlock prev = NativeContract.Ledger.GetTrimmedBlock(snapshot, prevHash); + TrimmedBlock? prev = NativeContract.Ledger.GetTrimmedBlock(snapshot, prevHash); if (prev is null) return false; if (prev.Index + 1 != index) return false; if (prev.Hash != prevHash) return false; @@ -251,7 +251,7 @@ internal bool Verify(ProtocolSettings settings, DataCache snapshot) internal bool Verify(ProtocolSettings settings, DataCache snapshot, HeaderCache headerCache) { - Header prev = headerCache.Last; + Header? prev = headerCache.Last; if (prev is null) return Verify(settings, snapshot); if (primaryIndex >= settings.ValidatorsCount) return false; diff --git a/src/Neo/Network/P2P/Payloads/HeadersPayload.cs b/src/Neo/Network/P2P/Payloads/HeadersPayload.cs index 152ba32857..657b48f003 100644 --- a/src/Neo/Network/P2P/Payloads/HeadersPayload.cs +++ b/src/Neo/Network/P2P/Payloads/HeadersPayload.cs @@ -28,7 +28,7 @@ public class HeadersPayload : ISerializable /// /// The list of headers. /// - public Header[] Headers; + public Header[] Headers = null!; public int Size => Headers.GetVarSize(); diff --git a/src/Neo/Network/P2P/Payloads/InvPayload.cs b/src/Neo/Network/P2P/Payloads/InvPayload.cs index aa4d340d99..f55630abec 100644 --- a/src/Neo/Network/P2P/Payloads/InvPayload.cs +++ b/src/Neo/Network/P2P/Payloads/InvPayload.cs @@ -34,7 +34,7 @@ public class InvPayload : ISerializable /// /// The hashes of the inventories. /// - public UInt256[] Hashes; + public UInt256[] Hashes = null!; public int Size => sizeof(InventoryType) + Hashes.GetVarSize(); diff --git a/src/Neo/Network/P2P/Payloads/MerkleBlockPayload.cs b/src/Neo/Network/P2P/Payloads/MerkleBlockPayload.cs index aebb17d5d9..d7ec1a7a49 100644 --- a/src/Neo/Network/P2P/Payloads/MerkleBlockPayload.cs +++ b/src/Neo/Network/P2P/Payloads/MerkleBlockPayload.cs @@ -26,7 +26,7 @@ public class MerkleBlockPayload : ISerializable /// /// The header of the block. /// - public Header Header; + public Header Header = null!; /// /// The number of the transactions in the block. @@ -36,7 +36,7 @@ public class MerkleBlockPayload : ISerializable /// /// The nodes of the transactions hash tree. /// - public UInt256[] Hashes; + public UInt256[] Hashes = null!; /// /// The data in the that filtered the block. diff --git a/src/Neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/src/Neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index d3cfd15f66..d38d24e784 100644 --- a/src/Neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/src/Neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -31,12 +31,12 @@ public class NetworkAddressWithTime : ISerializable /// /// The address of the node. /// - public IPAddress Address; + public IPAddress Address = null!; /// /// The capabilities of the node. /// - public NodeCapability[] Capabilities; + public NodeCapability[] Capabilities = null!; /// /// The of the Tcp server. diff --git a/src/Neo/Network/P2P/Payloads/OracleResponse.cs b/src/Neo/Network/P2P/Payloads/OracleResponse.cs index 2770f556a8..0f2ff6ccd5 100644 --- a/src/Neo/Network/P2P/Payloads/OracleResponse.cs +++ b/src/Neo/Network/P2P/Payloads/OracleResponse.cs @@ -97,7 +97,7 @@ public override bool Verify(DataCache snapshot, Transaction tx) { if (tx.Signers.Any(p => p.Scopes != WitnessScope.None)) return false; if (!tx.Script.Span.SequenceEqual(FixedScript)) return false; - OracleRequest request = NativeContract.Oracle.GetRequest(snapshot, Id); + OracleRequest? request = NativeContract.Oracle.GetRequest(snapshot, Id); if (request is null) return false; if (tx.NetworkFee + tx.SystemFee != request.GasForResponse) return false; UInt160 oracleAccount = Contract.GetBFTAddress(NativeContract.RoleManagement.GetDesignatedByRole(snapshot, Role.Oracle, NativeContract.Ledger.CurrentIndex(snapshot) + 1)); diff --git a/src/Neo/Network/P2P/Payloads/Signer.cs b/src/Neo/Network/P2P/Payloads/Signer.cs index 2f96047323..e906470ea2 100644 --- a/src/Neo/Network/P2P/Payloads/Signer.cs +++ b/src/Neo/Network/P2P/Payloads/Signer.cs @@ -33,7 +33,7 @@ public class Signer : IInteroperable, ISerializable /// /// The account of the signer. /// - public UInt160 Account; + public UInt160 Account = null!; /// /// The scopes of the witness. @@ -44,19 +44,19 @@ public class Signer : IInteroperable, ISerializable /// The contracts that allowed by the witness. /// Only available when the flag is set. /// - public UInt160[] AllowedContracts; + public UInt160[] AllowedContracts = null!; /// /// The groups that allowed by the witness. /// Only available when the flag is set. /// - public ECPoint[] AllowedGroups; + public ECPoint[] AllowedGroups = null!; /// /// The rules that the witness must meet. /// Only available when the flag is set. /// - public WitnessRule[] Rules; + public WitnessRule[] Rules = null!; public int Size => /*Account*/ UInt160.Length + @@ -154,14 +154,14 @@ public void Serialize(BinaryWriter writer) public static Signer FromJson(JObject json) { Signer signer = new(); - signer.Account = UInt160.Parse(json["account"].GetString()); - signer.Scopes = Enum.Parse(json["scopes"].GetString()); + signer.Account = UInt160.Parse(json["account"]!.GetString()); + signer.Scopes = Enum.Parse(json["scopes"]!.GetString()); if (signer.Scopes.HasFlag(WitnessScope.CustomContracts)) - signer.AllowedContracts = ((JArray)json["allowedcontracts"]).Select(p => UInt160.Parse(p.GetString())).ToArray(); + signer.AllowedContracts = json["allowedcontracts"].NullExceptionOr().Select(p => UInt160.Parse(p!.GetString())).ToArray(); if (signer.Scopes.HasFlag(WitnessScope.CustomGroups)) - signer.AllowedGroups = ((JArray)json["allowedgroups"]).Select(p => ECPoint.Parse(p.GetString(), ECCurve.Secp256r1)).ToArray(); + signer.AllowedGroups = json["allowedgroups"].NullExceptionOr().Select(p => ECPoint.Parse(p!.GetString(), ECCurve.Secp256r1)).ToArray(); if (signer.Scopes.HasFlag(WitnessScope.WitnessRules)) - signer.Rules = ((JArray)json["rules"]).Select(p => WitnessRule.FromJson((JObject)p)).ToArray(); + signer.Rules = json["rules"].NullExceptionOr().Select(p => WitnessRule.FromJson(p.NullExceptionOr())).ToArray(); return signer; } @@ -175,9 +175,9 @@ public JObject ToJson() json["account"] = Account.ToString(); json["scopes"] = Scopes; if (Scopes.HasFlag(WitnessScope.CustomContracts)) - json["allowedcontracts"] = AllowedContracts.Select(p => (JToken)p.ToString()).ToArray(); + json["allowedcontracts"] = AllowedContracts.Select(p => (JToken)p.ToString()!).ToArray(); if (Scopes.HasFlag(WitnessScope.CustomGroups)) - json["allowedgroups"] = AllowedGroups.Select(p => (JToken)p.ToString()).ToArray(); + json["allowedgroups"] = AllowedGroups.Select(p => (JToken)p.ToString()!).ToArray(); if (Scopes.HasFlag(WitnessScope.WitnessRules)) json["rules"] = Rules.Select(p => p.ToJson()).ToArray(); return json; @@ -188,7 +188,7 @@ void IInteroperable.FromStackItem(VM.Types.StackItem stackItem) throw new NotSupportedException(); } - VM.Types.StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + VM.Types.StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) { return new VM.Types.Array(referenceCounter, new VM.Types.StackItem[] { diff --git a/src/Neo/Network/P2P/Payloads/Transaction.cs b/src/Neo/Network/P2P/Payloads/Transaction.cs index 16417beb43..427d1a950a 100644 --- a/src/Neo/Network/P2P/Payloads/Transaction.cs +++ b/src/Neo/Network/P2P/Payloads/Transaction.cs @@ -49,10 +49,10 @@ public class Transaction : IEquatable, IInventory, IInteroperable private long sysfee; private long netfee; private uint validUntilBlock; - private Signer[] _signers; - private TransactionAttribute[] attributes; + private Signer[] _signers = null!; + private TransactionAttribute[] attributes = null!; private ReadOnlyMemory script; - private Witness[] witnesses; + private Witness[] witnesses = null!; /// /// The size of a transaction header. @@ -64,7 +64,7 @@ public class Transaction : IEquatable, IInventory, IInteroperable sizeof(long) + //NetworkFee sizeof(uint); //ValidUntilBlock - private Dictionary _attributesCache; + private Dictionary? _attributesCache; /// /// The attributes of the transaction. /// @@ -79,7 +79,7 @@ public TransactionAttribute[] Attributes /// public long FeePerByte => NetworkFee / Size; - private UInt256 _hash = null; + private UInt256? _hash; public UInt256 Hash { get @@ -242,14 +242,14 @@ public void DeserializeUnsigned(ref MemoryReader reader) if (Script.Length == 0) throw new FormatException(); } - public bool Equals(Transaction other) + public bool Equals(Transaction? other) { if (other is null) return false; if (ReferenceEquals(this, other)) return true; return Hash.Equals(other.Hash); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as Transaction); } @@ -264,7 +264,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) /// /// The type of the attribute. /// The first attribute of this type. Or if there is no attribute of this type. - public T GetAttribute() where T : TransactionAttribute + public T? GetAttribute() where T : TransactionAttribute { return GetAttributes().FirstOrDefault(); } @@ -287,7 +287,7 @@ public override int GetHashCode() return Hash.GetHashCode(); } - public UInt160[] GetScriptHashesForVerifying(DataCache snapshot) + public UInt160[] GetScriptHashesForVerifying(DataCache? snapshot) { return Signers.Select(p => p.Account).ToArray(); } @@ -429,11 +429,11 @@ public virtual VerifyResult VerifyStateIndependent(ProtocolSettings settings) return VerifyResult.Invalid; } } - else if (IsMultiSigContract(witnesses[i].VerificationScript.Span, out var m, out ECPoint[] points)) + else if (IsMultiSigContract(witnesses[i].VerificationScript.Span, out var m, out ECPoint[]? points)) { if (hashes[i] != witnesses[i].ScriptHash) return VerifyResult.Invalid; var signatures = GetMultiSignatures(witnesses[i].InvocationScript); - if (signatures.Length != m) return VerifyResult.Invalid; + if (signatures?.Length != m) return VerifyResult.Invalid; var n = points.Length; var message = this.GetSignData(settings.Network); try @@ -456,7 +456,7 @@ public virtual VerifyResult VerifyStateIndependent(ProtocolSettings settings) return VerifyResult.Succeed; } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { if (_signers == null || _signers.Length == 0) throw new ArgumentException("Sender is not specified in the transaction."); return new Array(referenceCounter, new StackItem[] @@ -475,7 +475,7 @@ public StackItem ToStackItem(ReferenceCounter referenceCounter) }); } - private static ReadOnlyMemory[] GetMultiSignatures(ReadOnlyMemory script) + private static ReadOnlyMemory[]? GetMultiSignatures(ReadOnlyMemory script) { ReadOnlySpan span = script.Span; int i = 0; diff --git a/src/Neo/Network/P2P/Payloads/VersionPayload.cs b/src/Neo/Network/P2P/Payloads/VersionPayload.cs index 8cec6278e7..639e89cf4e 100644 --- a/src/Neo/Network/P2P/Payloads/VersionPayload.cs +++ b/src/Neo/Network/P2P/Payloads/VersionPayload.cs @@ -50,12 +50,12 @@ public class VersionPayload : ISerializable /// /// A used to identify the client software of the node. /// - public string UserAgent; + public string UserAgent = null!; /// /// The capabilities of the node. /// - public NodeCapability[] Capabilities; + public NodeCapability[] Capabilities = null!; public int Size => sizeof(uint) + // Network diff --git a/src/Neo/Network/P2P/Payloads/Witness.cs b/src/Neo/Network/P2P/Payloads/Witness.cs index 34932cc7fb..c83e3d4b14 100644 --- a/src/Neo/Network/P2P/Payloads/Witness.cs +++ b/src/Neo/Network/P2P/Payloads/Witness.cs @@ -39,7 +39,7 @@ public class Witness : ISerializable /// public ReadOnlyMemory VerificationScript; - private UInt160 _scriptHash; + private UInt160? _scriptHash; /// /// The hash of the . /// diff --git a/src/Neo/Network/P2P/Payloads/WitnessRule.cs b/src/Neo/Network/P2P/Payloads/WitnessRule.cs index 3bac09e7f5..0fe1055f5c 100644 --- a/src/Neo/Network/P2P/Payloads/WitnessRule.cs +++ b/src/Neo/Network/P2P/Payloads/WitnessRule.cs @@ -33,7 +33,7 @@ public class WitnessRule : IInteroperable, ISerializable /// /// The condition of the rule. /// - public WitnessCondition Condition; + public WitnessCondition Condition = null!; int ISerializable.Size => sizeof(WitnessRuleAction) + Condition.Size; @@ -58,7 +58,7 @@ void ISerializable.Serialize(BinaryWriter writer) /// The converted . public static WitnessRule FromJson(JObject json) { - WitnessRuleAction action = Enum.Parse(json["action"].GetString()); + WitnessRuleAction action = Enum.Parse(json["action"]!.GetString()); if (action != WitnessRuleAction.Allow && action != WitnessRuleAction.Deny) throw new FormatException(); @@ -66,7 +66,7 @@ public static WitnessRule FromJson(JObject json) return new() { Action = action, - Condition = WitnessCondition.FromJson((JObject)json["condition"], WitnessCondition.MaxNestingDepth) + Condition = WitnessCondition.FromJson(json["condition"].NullExceptionOr(), WitnessCondition.MaxNestingDepth) }; } @@ -88,9 +88,9 @@ void IInteroperable.FromStackItem(StackItem stackItem) throw new NotSupportedException(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { - return new VM.Types.Array(referenceCounter, new StackItem[] + return new VM.Types.Array(referenceCounter, new[] { (byte)Action, Condition.ToStackItem(referenceCounter) diff --git a/src/Neo/Network/P2P/Peer.cs b/src/Neo/Network/P2P/Peer.cs index 767d747b1d..e197b9024f 100644 --- a/src/Neo/Network/P2P/Peer.cs +++ b/src/Neo/Network/P2P/Peer.cs @@ -37,7 +37,7 @@ public class Peers /// /// The unconnected peers to be added. /// - public IEnumerable EndPoints { get; init; } + public IEnumerable EndPoints { get; init; } = null!; } /// @@ -48,7 +48,7 @@ public class Connect /// /// The address of the remote node. /// - public IPEndPoint EndPoint { get; init; } + public IPEndPoint EndPoint { get; init; } = null!; /// /// Indicates whether the remote node is trusted. A trusted node will always be connected. @@ -69,8 +69,8 @@ private class Timer { } public const int DefaultMaxConnections = DefaultMinDesiredConnections * 4; private static readonly IActorRef tcp_manager = Context.System.Tcp(); - private IActorRef tcp_listener; - private ICancelable timer; + private IActorRef tcp_listener = null!; + private ICancelable timer = null!; private static readonly HashSet localAddresses = new(); private readonly Dictionary ConnectedAddresses = new(); @@ -309,7 +309,7 @@ private void OnTcpCommandFailed(Tcp.Command cmd) private void OnTerminated(IActorRef actorRef) { - if (ConnectedPeers.TryRemove(actorRef, out IPEndPoint endPoint)) + if (ConnectedPeers.TryRemove(actorRef, out IPEndPoint? endPoint)) { ConnectedAddresses.TryGetValue(endPoint.Address, out int count); if (count > 0) count--; @@ -325,7 +325,7 @@ private void OnTimer() // Check if the number of desired connections is already enough if (ConnectedPeers.Count >= MinDesiredConnections) return; - // If there aren't available UnconnectedPeers, it triggers an abstract implementation of NeedMorePeers + // If there aren't available UnconnectedPeers, it triggers an abstract implementation of NeedMorePeers if (UnconnectedPeers.Count == 0) NeedMorePeers(MinDesiredConnections - ConnectedPeers.Count); diff --git a/src/Neo/Network/P2P/RemoteNode.ProtocolHandler.cs b/src/Neo/Network/P2P/RemoteNode.ProtocolHandler.cs index 4606723cd0..ac484b0cba 100644 --- a/src/Neo/Network/P2P/RemoteNode.ProtocolHandler.cs +++ b/src/Neo/Network/P2P/RemoteNode.ProtocolHandler.cs @@ -49,7 +49,7 @@ public static event MessageReceivedHandler MessageReceived private readonly HashSetCache knownHashes; private readonly HashSetCache sentHashes; private bool verack = false; - private BloomFilter bloom_filter; + private BloomFilter? bloom_filter; private static readonly TimeSpan TimerInterval = TimeSpan.FromSeconds(30); private readonly ICancelable timer = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(TimerInterval, TimerInterval, Context.Self, new Timer(), ActorRefs.NoSender); @@ -61,7 +61,7 @@ private void OnMessage(Message msg) return; if (Version == null) { - if (msg.Command != MessageCommand.Version) + if (msg.Command != MessageCommand.Version || msg.Payload is null) throw new ProtocolViolationException(); OnVersionMessageReceived((VersionPayload)msg.Payload); return; @@ -73,71 +73,73 @@ private void OnMessage(Message msg) OnVerackMessageReceived(); return; } - switch (msg.Command) + switch (msg.Command, msg.Payload) { - case MessageCommand.Addr: - OnAddrMessageReceived((AddrPayload)msg.Payload); + case (MessageCommand.Addr, AddrPayload payload): + OnAddrMessageReceived(payload); break; - case MessageCommand.Block: - case MessageCommand.Extensible: + case (MessageCommand.Block, IInventory): + case (MessageCommand.Extensible, IInventory): OnInventoryReceived((IInventory)msg.Payload); break; - case MessageCommand.FilterAdd: - OnFilterAddMessageReceived((FilterAddPayload)msg.Payload); + case (MessageCommand.FilterAdd, FilterAddPayload payload): + OnFilterAddMessageReceived(payload); break; - case MessageCommand.FilterClear: + case (MessageCommand.FilterClear, _): OnFilterClearMessageReceived(); break; - case MessageCommand.FilterLoad: - OnFilterLoadMessageReceived((FilterLoadPayload)msg.Payload); + case (MessageCommand.FilterLoad, FilterLoadPayload payload): + OnFilterLoadMessageReceived(payload); break; - case MessageCommand.GetAddr: + case (MessageCommand.GetAddr, _): OnGetAddrMessageReceived(); break; - case MessageCommand.GetBlocks: - OnGetBlocksMessageReceived((GetBlocksPayload)msg.Payload); + case (MessageCommand.GetBlocks, GetBlocksPayload payload): + OnGetBlocksMessageReceived(payload); break; - case MessageCommand.GetBlockByIndex: - OnGetBlockByIndexMessageReceived((GetBlockByIndexPayload)msg.Payload); + case (MessageCommand.GetBlockByIndex, GetBlockByIndexPayload payload): + OnGetBlockByIndexMessageReceived(payload); break; - case MessageCommand.GetData: - OnGetDataMessageReceived((InvPayload)msg.Payload); + case (MessageCommand.GetData, InvPayload payload): + OnGetDataMessageReceived(payload); break; - case MessageCommand.GetHeaders: - OnGetHeadersMessageReceived((GetBlockByIndexPayload)msg.Payload); + case (MessageCommand.GetHeaders, GetBlockByIndexPayload payload): + OnGetHeadersMessageReceived(payload); break; - case MessageCommand.Headers: - OnHeadersMessageReceived((HeadersPayload)msg.Payload); + case (MessageCommand.Headers, HeadersPayload payload): + OnHeadersMessageReceived(payload); break; - case MessageCommand.Inv: - OnInvMessageReceived((InvPayload)msg.Payload); + case (MessageCommand.Inv, InvPayload payload): + OnInvMessageReceived(payload); break; - case MessageCommand.Mempool: + case (MessageCommand.Mempool, _): OnMemPoolMessageReceived(); break; - case MessageCommand.Ping: - OnPingMessageReceived((PingPayload)msg.Payload); + case (MessageCommand.Ping, PingPayload payload): + OnPingMessageReceived(payload); break; - case MessageCommand.Pong: - OnPongMessageReceived((PingPayload)msg.Payload); + case (MessageCommand.Pong, PingPayload payload): + OnPongMessageReceived(payload); break; - case MessageCommand.Transaction: - if (msg.Payload.Size <= Transaction.MaxTransactionSize) - OnInventoryReceived((Transaction)msg.Payload); + case (MessageCommand.Transaction, Transaction payload): + if (payload.Size <= Transaction.MaxTransactionSize) + OnInventoryReceived(payload); break; - case MessageCommand.Verack: - case MessageCommand.Version: + case (MessageCommand.Verack, _): + case (MessageCommand.Version, _): throw new ProtocolViolationException(); - case MessageCommand.Alert: - case MessageCommand.MerkleBlock: - case MessageCommand.NotFound: - case MessageCommand.Reject: - default: break; + // break; + // case (MessageCommand.Alert, _): + // case (MessageCommand.MerkleBlock, _): + // case (MessageCommand.NotFound, _): + // case (MessageCommand.Reject, _): + // default: break; } } - private void OnAddrMessageReceived(AddrPayload payload) + private void OnAddrMessageReceived(AddrPayload? payload) { + if (payload == null) throw new NullReferenceException($"AddrPayload {nameof(payload)} is null."); ref bool sent = ref sentCommands[(byte)MessageCommand.GetAddr]; if (!sent) return; sent = false; @@ -191,8 +193,8 @@ private void OnGetBlocksMessageReceived(GetBlocksPayload payload) // The default value of payload.Count is -1 int count = payload.Count < 0 || payload.Count > InvPayload.MaxHashesCount ? InvPayload.MaxHashesCount : payload.Count; DataCache snapshot = system.StoreView; - UInt256 hash = payload.HashStart; - TrimmedBlock state = NativeContract.Ledger.GetTrimmedBlock(snapshot, hash); + UInt256? hash = payload.HashStart; + TrimmedBlock? state = NativeContract.Ledger.GetTrimmedBlock(snapshot, hash); if (state == null) return; uint currentHeight = NativeContract.Ledger.CurrentIndex(snapshot); List hashes = new(); @@ -214,7 +216,7 @@ private void OnGetBlockByIndexMessageReceived(GetBlockByIndexPayload payload) uint count = payload.Count == -1 ? InvPayload.MaxHashesCount : Math.Min((uint)payload.Count, InvPayload.MaxHashesCount); for (uint i = payload.IndexStart, max = payload.IndexStart + count; i < max; i++) { - Block block = NativeContract.Ledger.GetBlock(system.StoreView, i); + Block? block = NativeContract.Ledger.GetBlock(system.StoreView, i); if (block == null) break; @@ -245,13 +247,13 @@ private void OnGetDataMessageReceived(InvPayload payload) switch (payload.Type) { case InventoryType.TX: - if (system.MemPool.TryGetValue(hash, out Transaction tx)) + if (system.MemPool.TryGetValue(hash, out Transaction? tx)) EnqueueMessage(Message.Create(MessageCommand.Transaction, tx)); else notFound.Add(hash); break; case InventoryType.Block: - Block block = NativeContract.Ledger.GetBlock(system.StoreView, hash); + Block? block = NativeContract.Ledger.GetBlock(system.StoreView, hash); if (block != null) { if (bloom_filter == null) @@ -382,9 +384,10 @@ private void OnVerackMessageReceived() CheckMessageQueue(); } - private void OnVersionMessageReceived(VersionPayload payload) + private void OnVersionMessageReceived(VersionPayload? payload) { - Version = payload; + Version = payload ?? throw new NullReferenceException($"AddrPayload {nameof(payload)} is null."); + foreach (NodeCapability capability in payload.Capabilities) { switch (capability) diff --git a/src/Neo/Network/P2P/RemoteNode.cs b/src/Neo/Network/P2P/RemoteNode.cs index 6aa2c742a8..e76a00cfbd 100644 --- a/src/Neo/Network/P2P/RemoteNode.cs +++ b/src/Neo/Network/P2P/RemoteNode.cs @@ -33,7 +33,7 @@ namespace Neo.Network.P2P public partial class RemoteNode : Connection { internal class StartProtocol { } - internal class Relay { public IInventory Inventory; } + internal class Relay { public IInventory Inventory = null!; } private readonly NeoSystem system; private readonly LocalNode localNode; @@ -43,7 +43,7 @@ internal class Relay { public IInventory Inventory; } private readonly bool[] sentCommands = new bool[1 << (sizeof(MessageCommand) * 8)]; private ByteString msg_buffer = ByteString.Empty; private bool ack = true; - private uint lastHeightSent = 0; + private uint lastHeightSent; /// /// The address of the remote Tcp server. @@ -53,22 +53,22 @@ internal class Relay { public IInventory Inventory; } /// /// The port listened by the remote Tcp server. If the remote node is not a server, this field is 0. /// - public int ListenerTcpPort { get; private set; } = 0; + public int ListenerTcpPort { get; private set; } /// /// The sent by the remote node. /// - public VersionPayload Version { get; private set; } + public VersionPayload Version { get; private set; } = null!; /// /// The index of the last block sent by the remote node. /// - public uint LastBlockIndex { get; private set; } = 0; + public uint LastBlockIndex { get; private set; } /// /// Indicates whether the remote node is a full node. /// - public bool IsFullNode { get; private set; } = false; + public bool IsFullNode { get; private set; } /// /// Initializes a new instance of the class. @@ -106,7 +106,7 @@ private void CheckMessageQueue() SendMessage(queue.Dequeue()); } - private void EnqueueMessage(MessageCommand command, ISerializable payload = null) + private void EnqueueMessage(MessageCommand command, ISerializable? payload = null) { EnqueueMessage(Message.Create(command, payload)); } @@ -145,7 +145,7 @@ protected override void OnData(ByteString data) { msg_buffer = msg_buffer.Concat(data); - for (Message message = TryParseMessage(); message != null; message = TryParseMessage()) + for (Message? message = TryParseMessage(); message != null; message = TryParseMessage()) OnMessage(message); } @@ -232,7 +232,7 @@ private void SendMessage(Message message) sentCommands[(byte)message.Command] = true; } - private Message TryParseMessage() + private Message? TryParseMessage() { var length = Message.TryDeserialize(msg_buffer, out var msg); if (length <= 0) return null; diff --git a/src/Neo/Network/P2P/TaskManager.cs b/src/Neo/Network/P2P/TaskManager.cs index 1d24597154..2a3ed0dab3 100644 --- a/src/Neo/Network/P2P/TaskManager.cs +++ b/src/Neo/Network/P2P/TaskManager.cs @@ -31,9 +31,9 @@ namespace Neo.Network.P2P /// public class TaskManager : UntypedActor { - internal class Register { public VersionPayload Version; } + internal class Register { public VersionPayload Version = null!; } internal class Update { public uint LastBlockIndex; } - internal class NewTasks { public InvPayload Payload; } + internal class NewTasks { public InvPayload Payload = null!; } /// /// Sent to to restart tasks for inventories. @@ -43,7 +43,7 @@ public class RestartTasks /// /// The inventories that need to restart. /// - public InvPayload Payload { get; init; } + public InvPayload Payload { get; init; } = null!; } private class Timer { } @@ -81,7 +81,7 @@ public TaskManager(NeoSystem system) private void OnHeaders(Header[] _) { - if (!sessions.TryGetValue(Sender, out TaskSession session)) + if (!sessions.TryGetValue(Sender, out TaskSession? session)) return; if (session.InvTasks.Remove(HeaderTaskHash)) DecrementGlobalTask(HeaderTaskHash); @@ -91,14 +91,14 @@ private void OnHeaders(Header[] _) private void OnInvalidBlock(Block invalidBlock) { foreach (var (actor, session) in sessions) - if (session.ReceivedBlock.TryGetValue(invalidBlock.Index, out Block block)) + if (session.ReceivedBlock.TryGetValue(invalidBlock.Index, out Block? block)) if (block.Hash == invalidBlock.Hash) actor.Tell(Tcp.Abort.Instance); } private void OnNewTasks(InvPayload payload) { - if (!sessions.TryGetValue(Sender, out TaskSession session)) + if (!sessions.TryGetValue(Sender, out TaskSession? session)) return; // Do not accept payload of type InventoryType.TX if not synced on HeaderHeight @@ -141,7 +141,7 @@ private void OnPersistCompleted(Block block) lastSeenPersistedIndex = block.Index; foreach (var (actor, session) in sessions) - if (session.ReceivedBlock.Remove(block.Index, out Block receivedBlock)) + if (session.ReceivedBlock.Remove(block.Index, out Block? receivedBlock)) { if (block.Hash == receivedBlock.Hash) RequestTasks(actor, session); @@ -198,7 +198,7 @@ private void OnRegister(VersionPayload version) private void OnUpdate(Update update) { - if (!sessions.TryGetValue(Sender, out TaskSession session)) + if (!sessions.TryGetValue(Sender, out TaskSession? session)) return; session.LastBlockIndex = update.LastBlockIndex; } @@ -214,14 +214,14 @@ private void OnRestartTasks(InvPayload payload) private void OnTaskCompleted(IInventory inventory) { - Block block = inventory as Block; + var block = inventory as Block; knownHashes.Add(inventory.Hash); globalInvTasks.Remove(inventory.Hash); if (block is not null) globalIndexTasks.Remove(block.Index); foreach (TaskSession ms in sessions.Values) ms.AvailableTasks.Remove(inventory.Hash); - if (sessions.TryGetValue(Sender, out TaskSession session)) + if (sessions.TryGetValue(Sender, out TaskSession? session)) { session.InvTasks.Remove(inventory.Hash); if (block is not null) @@ -303,7 +303,7 @@ private bool IncrementGlobalTask(uint index) private void OnTerminated(IActorRef actor) { - if (!sessions.TryGetValue(actor, out TaskSession session)) + if (!sessions.TryGetValue(actor, out TaskSession? session)) return; foreach (UInt256 hash in session.InvTasks.Keys) DecrementGlobalTask(hash); @@ -419,7 +419,7 @@ public TaskManagerMailbox(Akka.Actor.Settings settings, Config config) { } - internal protected override bool IsHighPriority(object message) + protected internal override bool IsHighPriority(object message) { switch (message) { diff --git a/src/Neo/Network/UPnP.cs b/src/Neo/Network/UPnP.cs index a0cd0ce78a..f7ebfe9471 100644 --- a/src/Neo/Network/UPnP.cs +++ b/src/Neo/Network/UPnP.cs @@ -25,7 +25,7 @@ namespace Neo.Network /// public static class UPnP { - private static string _serviceUrl; + private static string? _serviceUrl; /// /// Gets or sets the timeout for discovering the UPnP device. @@ -74,8 +74,8 @@ public static bool Discover() string resp = Encoding.ASCII.GetString(buffer[..length]).ToLowerInvariant(); if (resp.Contains("upnp:rootdevice")) { - resp = resp[(resp.IndexOf("location:") + 9)..]; - resp = resp.Substring(0, resp.IndexOf("\r")).Trim(); + resp = resp[(resp.IndexOf("location:", StringComparison.Ordinal) + 9)..]; + resp = resp.Substring(0, resp.IndexOf("\r", StringComparison.Ordinal)).Trim(); if (!string.IsNullOrEmpty(_serviceUrl = GetServiceUrl(resp))) { return true; @@ -92,7 +92,7 @@ public static bool Discover() return false; } - private static string GetServiceUrl(string resp) + private static string? GetServiceUrl(string resp) { try { @@ -100,21 +100,21 @@ private static string GetServiceUrl(string resp) desc.Load(resp); XmlNamespaceManager nsMgr = new(desc.NameTable); nsMgr.AddNamespace("tns", "urn:schemas-upnp-org:device-1-0"); - XmlNode typen = desc.SelectSingleNode("//tns:device/tns:deviceType/text()", nsMgr); - if (!typen.Value.Contains("InternetGatewayDevice")) + XmlNode typen = desc.SelectSingleNode("//tns:device/tns:deviceType/text()", nsMgr)!; + if (!typen.Value!.Contains("InternetGatewayDevice")) return null; - XmlNode node = desc.SelectSingleNode("//tns:service[contains(tns:serviceType,\"WANIPConnection\")]/tns:controlURL/text()", nsMgr); + XmlNode? node = desc.SelectSingleNode("//tns:service[contains(tns:serviceType,\"WANIPConnection\")]/tns:controlURL/text()", nsMgr); if (node == null) return null; - XmlNode eventnode = desc.SelectSingleNode("//tns:service[contains(tns:serviceType,\"WANIPConnection\")]/tns:eventSubURL/text()", nsMgr); - return CombineUrls(resp, node.Value); + XmlNode? eventnode = desc.SelectSingleNode("//tns:service[contains(tns:serviceType,\"WANIPConnection\")]/tns:eventSubURL/text()", nsMgr); + return CombineUrls(resp, node.Value!); } catch { return null; } } private static string CombineUrls(string resp, string p) { - int n = resp.IndexOf("://"); + int n = resp.IndexOf("://", StringComparison.Ordinal); n = resp.IndexOf('/', n + 3); return resp.Substring(0, n) + p; } @@ -166,7 +166,7 @@ public static IPAddress GetExternalIP() "", "GetExternalIPAddress"); XmlNamespaceManager nsMgr = new(xdoc.NameTable); nsMgr.AddNamespace("tns", "urn:schemas-upnp-org:device-1-0"); - string IP = xdoc.SelectSingleNode("//NewExternalIPAddress/text()", nsMgr).Value; + string IP = xdoc.SelectSingleNode("//NewExternalIPAddress/text()", nsMgr)!.Value!; return IPAddress.Parse(IP); } From 57383c9303891e80f71b5aa0491d7fd58d6b9897 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 10:00:15 +0800 Subject: [PATCH 02/36] add helper methods --- src/Neo/Helper.cs | 24 +++++++++++++++++++----- src/Neo/Utility.cs | 2 +- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/Neo/Helper.cs b/src/Neo/Helper.cs index 00099bc148..5dbc89c213 100644 --- a/src/Neo/Helper.cs +++ b/src/Neo/Helper.cs @@ -135,9 +135,9 @@ internal static void Remove(this HashSet set, IReadOnlyDictionary internal static string GetVersion(this Assembly assembly) { - CustomAttributeData attribute = assembly.CustomAttributes.FirstOrDefault(p => p.AttributeType == typeof(AssemblyInformationalVersionAttribute)); - if (attribute == null) return assembly.GetName().Version.ToString(3); - return (string)attribute.ConstructorArguments[0].Value; + CustomAttributeData? attribute = assembly.CustomAttributes.FirstOrDefault(p => p.AttributeType == typeof(AssemblyInformationalVersionAttribute)); + if (attribute == null) return assembly.GetName().Version!.ToString(3); + return (string)attribute.ConstructorArguments[0].Value!; } /// @@ -145,9 +145,9 @@ internal static string GetVersion(this Assembly assembly) /// /// The hex to convert. /// The converted byte array. - public static byte[] HexToBytes(this string value) + public static byte[] HexToBytes(this string? value) { - if (value == null || value.Length == 0) + if (string.IsNullOrEmpty(value)) return Array.Empty(); if (value.Length % 2 == 1) throw new FormatException(); @@ -309,5 +309,19 @@ internal static IPEndPoint Unmap(this IPEndPoint endPoint) return endPoint; return new IPEndPoint(endPoint.Address.Unmap(), endPoint.Port); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static T NullExceptionOr(this object? obj) where T : class + { + if (obj == null) throw new NullReferenceException($"Object {nameof(obj)} is null."); + return (T)obj; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static T NotNull(this T? obj) where T : class + { + if (obj == null) throw new NullReferenceException($"Object {nameof(obj)} is null."); + return obj; + } } } diff --git a/src/Neo/Utility.cs b/src/Neo/Utility.cs index 6883c69a26..807b2979e0 100644 --- a/src/Neo/Utility.cs +++ b/src/Neo/Utility.cs @@ -31,7 +31,7 @@ public Logger() } } - public static event LogEventHandler Logging; + public static event LogEventHandler Logging = null!; /// /// A strict UTF8 encoding used in NEO system. From 9f1613836f44099e74cffa8ea902ecc140e930d6 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 10:02:20 +0800 Subject: [PATCH 03/36] fix UT --- tests/Neo.UnitTests/Network/P2P/Payloads/UT_Block.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Block.cs b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Block.cs index 2021e5a187..3cbcb883de 100644 --- a/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Block.cs +++ b/tests/Neo.UnitTests/Network/P2P/Payloads/UT_Block.cs @@ -31,7 +31,7 @@ public void TestSetup() [TestMethod] public void Transactions_Get() { - uut.Transactions.Should().BeNull(); + uut.Transactions.Should().BeEmpty(); } [TestMethod] From 8145c4dae7e344ad4c50abf3d391f4333cdd974d Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 10:03:34 +0800 Subject: [PATCH 04/36] use nullable crypto --- src/Neo/Cryptography/Crypto.cs | 4 +- src/Neo/Cryptography/ECC/ECFieldElement.cs | 12 ++--- src/Neo/Cryptography/ECC/ECPoint.cs | 58 +++++++++++----------- src/Neo/Cryptography/Helper.cs | 4 +- src/Neo/Cryptography/MerkleTree.cs | 14 +++--- src/Neo/Cryptography/MerkleTreeNode.cs | 8 +-- 6 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/Neo/Cryptography/Crypto.cs b/src/Neo/Cryptography/Crypto.cs index e09b556d82..723fabc8f1 100644 --- a/src/Neo/Cryptography/Crypto.cs +++ b/src/Neo/Cryptography/Crypto.cs @@ -80,8 +80,8 @@ public static bool VerifySignature(ReadOnlySpan message, ReadOnlySpan public class ECPoint : IComparable, IEquatable, ISerializable { - internal ECFieldElement X, Y; + internal ECFieldElement? X, Y; internal readonly ECCurve Curve; - private byte[] _compressedPoint, _uncompressedPoint; + private byte[]? _compressedPoint, _uncompressedPoint; /// /// Indicates whether it is a point at infinity. @@ -37,15 +37,15 @@ public bool IsInfinity public int Size => IsInfinity ? 1 : 33; - private static IO.Caching.ECPointCache pointCacheK1 { get; } = new(1000); - private static IO.Caching.ECPointCache pointCacheR1 { get; } = new(1000); + private static ECPointCache pointCacheK1 { get; } = new(1000); + private static ECPointCache pointCacheR1 { get; } = new(1000); /// /// Initializes a new instance of the class with the secp256r1 curve. /// public ECPoint() : this(null, null, ECCurve.Secp256r1) { } - internal ECPoint(ECFieldElement x, ECFieldElement y, ECCurve curve) + internal ECPoint(ECFieldElement? x, ECFieldElement? y, ECCurve curve) { if ((x is null ^ y is null) || (curve is null)) throw new ArgumentException("Exactly one of the field elements is null"); @@ -54,13 +54,13 @@ internal ECPoint(ECFieldElement x, ECFieldElement y, ECCurve curve) this.Curve = curve; } - public int CompareTo(ECPoint other) + public int CompareTo(ECPoint? other) { - if (!Curve.Equals(other.Curve)) throw new InvalidOperationException("Invalid comparision for points with different curves"); + if (!Curve.Equals(other?.Curve)) throw new InvalidOperationException("Invalid comparision for points with different curves"); if (ReferenceEquals(this, other)) return 0; - int result = X.CompareTo(other.X); + int result = X!.CompareTo(other.X); if (result != 0) return result; - return Y.CompareTo(other.Y); + return Y!.CompareTo(other.Y); } /// @@ -71,7 +71,7 @@ public int CompareTo(ECPoint other) /// The decoded point. public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve) { - ECPoint p = null; + ECPoint? p = null; switch (encoded[0]) { case 0x02: // compressed @@ -102,7 +102,7 @@ public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve) private static ECPoint DecompressPoint(ReadOnlySpan encoded, ECCurve curve) { - ECPointCache pointCache = null; + ECPointCache? pointCache; if (curve == ECCurve.Secp256k1) pointCache = pointCacheK1; else if (curve == ECCurve.Secp256r1) pointCache = pointCacheR1; else throw new FormatException("Invalid curve " + curve); @@ -123,7 +123,7 @@ private static ECPoint DecompressPoint(int yTilde, BigInteger X1, ECCurve curve) { ECFieldElement x = new(X1, curve); ECFieldElement alpha = x * (x.Square() + curve.A) + curve.B; - ECFieldElement beta = alpha.Sqrt(); + ECFieldElement? beta = alpha.Sqrt(); // // if we can't find a sqrt we haven't got a point on the @@ -187,27 +187,27 @@ public byte[] EncodePoint(bool commpressed) { if (_uncompressedPoint != null) return _uncompressedPoint; data = new byte[65]; - byte[] yBytes = Y.Value.ToByteArray(isUnsigned: true, isBigEndian: true); + byte[] yBytes = Y!.Value.ToByteArray(isUnsigned: true, isBigEndian: true); Buffer.BlockCopy(yBytes, 0, data, 65 - yBytes.Length, yBytes.Length); } - byte[] xBytes = X.Value.ToByteArray(isUnsigned: true, isBigEndian: true); + byte[] xBytes = X!.Value.ToByteArray(isUnsigned: true, isBigEndian: true); Buffer.BlockCopy(xBytes, 0, data, 33 - xBytes.Length, xBytes.Length); - data[0] = commpressed ? Y.Value.IsEven ? (byte)0x02 : (byte)0x03 : (byte)0x04; + data[0] = commpressed ? Y!.Value.IsEven ? (byte)0x02 : (byte)0x03 : (byte)0x04; if (commpressed) _compressedPoint = data; else _uncompressedPoint = data; return data; } - public bool Equals(ECPoint other) + public bool Equals(ECPoint? other) { if (ReferenceEquals(this, other)) return true; if (other is null) return false; if (IsInfinity && other.IsInfinity) return true; if (IsInfinity || other.IsInfinity) return false; - return X.Equals(other.X) && Y.Equals(other.Y); + return X!.Equals(other.X) && Y!.Equals(other.Y); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as ECPoint); } @@ -231,7 +231,7 @@ public static ECPoint FromBytes(byte[] bytes, ECCurve curve) public override int GetHashCode() { - return X.GetHashCode() + Y.GetHashCode(); + return X!.GetHashCode() + Y!.GetHashCode(); } internal static ECPoint Multiply(ECPoint p, BigInteger k) @@ -361,7 +361,7 @@ public override string ToString() /// The object used to construct the . /// The parsed point. /// if was converted successfully; otherwise, . - public static bool TryParse(string value, ECCurve curve, out ECPoint point) + public static bool TryParse(string value, ECCurve curve, out ECPoint? point) { try { @@ -379,13 +379,13 @@ internal ECPoint Twice() { if (this.IsInfinity) return this; - if (this.Y.Value.Sign == 0) + if (this.Y?.Value.Sign == 0) return Curve.Infinity; ECFieldElement TWO = new(2, Curve); ECFieldElement THREE = new(3, Curve); - ECFieldElement gamma = (this.X.Square() * THREE + Curve.A) / (Y * TWO); + ECFieldElement gamma = (this.X!.Square() * THREE + Curve.A) / (Y! * TWO); ECFieldElement x3 = gamma.Square() - this.X * TWO; - ECFieldElement y3 = gamma * (this.X - x3) - this.Y; + ECFieldElement y3 = gamma * (this.X - x3) - this.Y!; return new ECPoint(x3, y3, Curve); } @@ -426,7 +426,7 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k) public static ECPoint operator -(ECPoint x) { - return new ECPoint(x.X, -x.Y, x.Curve); + return new ECPoint(x.X, -x.Y!, x.Curve); } public static ECPoint operator *(ECPoint p, byte[] n) @@ -449,15 +449,15 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k) return y; if (y.IsInfinity) return x; - if (x.X.Equals(y.X)) + if (x.X!.Equals(y.X)) { - if (x.Y.Equals(y.Y)) + if (x.Y!.Equals(y.Y)) return x.Twice(); return x.Curve.Infinity; } - ECFieldElement gamma = (y.Y - x.Y) / (y.X - x.X); - ECFieldElement x3 = gamma.Square() - x.X - y.X; - ECFieldElement y3 = gamma * (x.X - x3) - x.Y; + ECFieldElement gamma = (y.Y! - x.Y!) / (y.X! - x.X); + ECFieldElement x3 = gamma.Square() - x.X - y.X!; + ECFieldElement y3 = gamma * (x.X - x3) - x.Y!; return new ECPoint(x3, y3, x.Curve); } diff --git a/src/Neo/Cryptography/Helper.cs b/src/Neo/Cryptography/Helper.cs index 840b6ebb7b..c74aff27c9 100644 --- a/src/Neo/Cryptography/Helper.cs +++ b/src/Neo/Cryptography/Helper.cs @@ -153,7 +153,7 @@ public static byte[] Sha256(this Span value) return Sha256((ReadOnlySpan)value); } - public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] nonce, byte[] associatedData = null) + public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] nonce, byte[]? associatedData = null) { if (nonce.Length != 12) throw new ArgumentOutOfRangeException(nameof(nonce)); var tag = new byte[16]; @@ -179,7 +179,7 @@ public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] non return Concat(nonce, cipherBytes, tag); } - public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[] associatedData = null) + public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[]? associatedData = null) { ReadOnlySpan encrypted = encryptedData; var nonce = encrypted[..12]; diff --git a/src/Neo/Cryptography/MerkleTree.cs b/src/Neo/Cryptography/MerkleTree.cs index 58d3856b2c..e2ce925d0e 100644 --- a/src/Neo/Cryptography/MerkleTree.cs +++ b/src/Neo/Cryptography/MerkleTree.cs @@ -23,7 +23,7 @@ namespace Neo.Cryptography /// public class MerkleTree { - private readonly MerkleTreeNode root; + private readonly MerkleTreeNode? root; /// /// The depth of the tree. @@ -40,7 +40,7 @@ internal MerkleTree(UInt256[] hashes) this.Depth = depth; } - private static MerkleTreeNode Build(MerkleTreeNode[] leaves) + private static MerkleTreeNode? Build(MerkleTreeNode[] leaves) { if (leaves.Length == 0) return null; if (leaves.Length == 1) return leaves[0]; @@ -63,7 +63,7 @@ private static MerkleTreeNode Build(MerkleTreeNode[] leaves) parents[i].RightChild = leaves[i * 2 + 1]; leaves[i * 2 + 1].Parent = parents[i]; } - parents[i].Hash = Concat(buffer, parents[i].LeftChild.Hash, parents[i].RightChild.Hash); + parents[i].Hash = Concat(buffer, parents[i].LeftChild!.Hash, parents[i].RightChild!.Hash); } return Build(parents); //TailCall } @@ -87,7 +87,7 @@ public static UInt256 ComputeRoot(UInt256[] hashes) if (hashes.Length == 0) return UInt256.Zero; if (hashes.Length == 1) return hashes[0]; MerkleTree tree = new(hashes); - return tree.root.Hash; + return tree.root!.Hash; } private static void DepthFirstSearch(MerkleTreeNode node, IList hashes) @@ -100,7 +100,7 @@ private static void DepthFirstSearch(MerkleTreeNode node, IList hashes) else { DepthFirstSearch(node.LeftChild, hashes); - DepthFirstSearch(node.RightChild, hashes); + DepthFirstSearch(node.RightChild!, hashes); } } @@ -145,8 +145,8 @@ private static void Trim(MerkleTreeNode node, int index, int depth, BitArray fla else { Trim(node.LeftChild, index * 2, depth - 1, flags); - Trim(node.RightChild, index * 2 + 1, depth - 1, flags); - if (node.LeftChild.LeftChild == null && node.RightChild.RightChild == null) + Trim(node.RightChild!, index * 2 + 1, depth - 1, flags); + if (node.LeftChild.LeftChild == null && node.RightChild!.RightChild == null) { node.LeftChild = null; node.RightChild = null; diff --git a/src/Neo/Cryptography/MerkleTreeNode.cs b/src/Neo/Cryptography/MerkleTreeNode.cs index 8fcc2dd5ce..3eb3b84cd4 100644 --- a/src/Neo/Cryptography/MerkleTreeNode.cs +++ b/src/Neo/Cryptography/MerkleTreeNode.cs @@ -13,10 +13,10 @@ namespace Neo.Cryptography { internal class MerkleTreeNode { - public UInt256 Hash; - public MerkleTreeNode Parent; - public MerkleTreeNode LeftChild; - public MerkleTreeNode RightChild; + public UInt256 Hash = null!; + public MerkleTreeNode? Parent; + public MerkleTreeNode? LeftChild; + public MerkleTreeNode? RightChild; public bool IsLeaf => LeftChild == null && RightChild == null; From f6879088498e0f8a29d5ddcd7f15586609fb4cc4 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 10:05:08 +0800 Subject: [PATCH 05/36] use nullable smartcontract --- .../ApplicationEngine.Contract.cs | 14 +-- .../SmartContract/ApplicationEngine.Crypto.cs | 4 +- .../ApplicationEngine.Runtime.cs | 64 +++++----- .../ApplicationEngine.Storage.cs | 7 +- src/Neo/SmartContract/ApplicationEngine.cs | 103 ++++++++-------- src/Neo/SmartContract/BinarySerializer.cs | 8 +- src/Neo/SmartContract/Contract.cs | 10 +- src/Neo/SmartContract/ContractParameter.cs | 32 ++--- .../ContractParametersContext.cs | 77 ++++++------ src/Neo/SmartContract/ContractState.cs | 10 +- src/Neo/SmartContract/ContractTask.cs | 4 +- src/Neo/SmartContract/ContractTaskAwaiter.cs | 20 ++-- .../ContractTaskMethodBuilder.cs | 4 +- src/Neo/SmartContract/DeployedContract.cs | 2 +- .../SmartContract/ExecutionContextState.cs | 10 +- src/Neo/SmartContract/Helper.cs | 13 +- .../IApplicationEngineProvider.cs | 2 +- src/Neo/SmartContract/IInteroperable.cs | 2 +- src/Neo/SmartContract/InteropDescriptor.cs | 6 +- .../InteropParameterDescriptor.cs | 16 +-- src/Neo/SmartContract/JsonSerializer.cs | 17 +-- src/Neo/SmartContract/Manifest/ContractAbi.cs | 14 +-- .../Manifest/ContractEventDescriptor.cs | 13 +- .../SmartContract/Manifest/ContractGroup.cs | 10 +- .../Manifest/ContractManifest.cs | 38 +++--- .../Manifest/ContractMethodDescriptor.cs | 13 +- .../Manifest/ContractParameterDefinition.cs | 10 +- .../Manifest/ContractPermission.cs | 20 ++-- .../Manifest/ContractPermissionDescriptor.cs | 24 ++-- .../Manifest/WildCardContainer.cs | 12 +- src/Neo/SmartContract/MethodToken.cs | 4 +- src/Neo/SmartContract/Native/AccountState.cs | 2 +- .../Native/ContractManagement.cs | 34 +++--- .../Native/ContractMethodAttribute.cs | 2 +- .../Native/ContractMethodMetadata.cs | 2 +- src/Neo/SmartContract/Native/FungibleToken.cs | 18 +-- src/Neo/SmartContract/Native/GasToken.cs | 9 +- .../SmartContract/Native/HashIndexState.cs | 4 +- .../SmartContract/Native/InteroperableList.cs | 6 +- .../SmartContract/Native/LedgerContract.cs | 90 +++++++------- .../SmartContract/Native/NativeContract.cs | 10 +- src/Neo/SmartContract/Native/NeoToken.cs | 111 +++++++++--------- .../SmartContract/Native/OracleContract.cs | 75 ++++++------ src/Neo/SmartContract/Native/OracleRequest.cs | 18 +-- .../SmartContract/Native/PolicyContract.cs | 16 +-- .../SmartContract/Native/RoleManagement.cs | 2 +- src/Neo/SmartContract/Native/StdLib.cs | 2 +- .../SmartContract/Native/TransactionState.cs | 4 +- src/Neo/SmartContract/Native/TrimmedBlock.cs | 7 +- src/Neo/SmartContract/NefFile.cs | 6 +- src/Neo/SmartContract/NotifyEventArgs.cs | 2 +- src/Neo/SmartContract/StorageItem.cs | 2 +- src/Neo/SmartContract/StorageKey.cs | 4 +- 53 files changed, 520 insertions(+), 489 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.Contract.cs b/src/Neo/SmartContract/ApplicationEngine.Contract.cs index 5e45ba4645..dc6c17d036 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Contract.cs @@ -76,9 +76,9 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl if ((callFlags & ~CallFlags.All) != 0) throw new ArgumentOutOfRangeException(nameof(callFlags)); - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Count); + ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Count); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Count} parameter(s) doesn't exist in the contract {contractHash}."); bool hasReturnValue = md.ReturnType != ContractParameterType.Void; @@ -93,10 +93,10 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl /// The version of the native contract to be called. protected internal void CallNativeContract(byte version) { - NativeContract contract = NativeContract.GetContract(CurrentScriptHash); + NativeContract? contract = NativeContract.GetContract(CurrentScriptHash!); if (contract is null) throw new InvalidOperationException("It is not allowed to use \"System.Contract.CallNative\" directly."); - if (!contract.IsActive(ProtocolSettings, NativeContract.Ledger.CurrentIndex(Snapshot))) + if (!contract.IsActive(ProtocolSettings!, NativeContract.Ledger.CurrentIndex(Snapshot))) throw new InvalidOperationException($"The native contract {contract.Name} is not active."); contract.Invoke(this, version); } @@ -108,7 +108,7 @@ protected internal void CallNativeContract(byte version) /// The of the current context. protected internal CallFlags GetCallFlags() { - var state = CurrentContext.GetState(); + var state = CurrentContext!.GetState(); return state.CallFlags; } @@ -155,7 +155,7 @@ protected internal async void NativeOnPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) + if (contract.IsActive(ProtocolSettings!, PersistingBlock!.Index)) await contract.OnPersist(this); } } @@ -177,7 +177,7 @@ protected internal async void NativePostPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) + if (contract.IsActive(ProtocolSettings!, PersistingBlock!.Index)) await contract.PostPersist(this); } } diff --git a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs index 1a8b2c7d6d..7c151e6f2e 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs @@ -46,7 +46,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) { try { - return Crypto.VerifySignature(ScriptContainer.GetSignData(ProtocolSettings.Network), signature, pubkey, ECCurve.Secp256r1); + return Crypto.VerifySignature(ScriptContainer!.GetSignData(ProtocolSettings!.Network), signature, pubkey, ECCurve.Secp256r1); } catch (ArgumentException) { @@ -63,7 +63,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) /// if the signatures are valid; otherwise, . protected internal bool CheckMultisig(byte[][] pubkeys, byte[][] signatures) { - byte[] message = ScriptContainer.GetSignData(ProtocolSettings.Network); + byte[] message = ScriptContainer!.GetSignData(ProtocolSettings!.Network); int m = signatures.Length, n = pubkeys.Length; if (n == 0 || m == 0 || m > n) throw new ArgumentException(); AddGas(CheckSigPrice * n * ExecFeeFactor); diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index 293b245bd7..6d7b9d1f9b 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -10,7 +10,6 @@ // modifications are permitted. using Neo.Cryptography.ECC; -using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.SmartContract.Native; using Neo.VM; @@ -36,7 +35,7 @@ partial class ApplicationEngine /// public const int MaxNotificationSize = 1024; - private uint random_times = 0; + private uint random_times; /// /// The of System.Runtime.Platform. @@ -169,7 +168,7 @@ internal protected static string GetPlatform() /// The magic number of the current network. internal protected uint GetNetwork() { - return ProtocolSettings.Network; + return ProtocolSettings!.Network; } /// @@ -179,7 +178,7 @@ internal protected uint GetNetwork() /// The address version of the current network. internal protected byte GetAddressVersion() { - return ProtocolSettings.AddressVersion; + return ProtocolSettings!.AddressVersion; } /// @@ -189,7 +188,7 @@ internal protected byte GetAddressVersion() /// The timestamp of the current block. protected internal ulong GetTime() { - return PersistingBlock.Timestamp; + return PersistingBlock!.Timestamp; } /// @@ -212,7 +211,7 @@ protected internal void RuntimeLoadScript(byte[] script, CallFlags callFlags, Ar if ((callFlags & ~CallFlags.All) != 0) throw new ArgumentOutOfRangeException(nameof(callFlags)); - ExecutionContextState state = CurrentContext.GetState(); + ExecutionContextState state = CurrentContext!.GetState(); ExecutionContext context = LoadScript(new Script(script, true), configureState: p => { p.CallingContext = CurrentContext; @@ -253,17 +252,17 @@ protected internal bool CheckWitnessInternal(UInt160 hash) if (ScriptContainer is Transaction tx) { Signer[] signers; - OracleResponse response = tx.GetAttribute(); + OracleResponse? response = tx.GetAttribute(); if (response is null) { signers = tx.Signers; } else { - OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id); - signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid).Signers; + OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id).NotNull(); + signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid)!.Signers; } - Signer signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); + Signer? signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); if (signer is null) return false; foreach (WitnessRule rule in signer.GetAllRules()) { @@ -290,9 +289,9 @@ protected internal bool CheckWitnessInternal(UInt160 hash) /// The number of times the current contract has been called during the execution. protected internal int GetInvocationCounter() { - if (!invocationCounter.TryGetValue(CurrentScriptHash, out var counter)) + if (!invocationCounter.TryGetValue(CurrentScriptHash!, out var counter)) { - invocationCounter[CurrentScriptHash] = counter = 1; + invocationCounter[CurrentScriptHash!] = counter = 1; } return counter; } @@ -308,12 +307,12 @@ protected internal BigInteger GetRandom() long price; if (IsHardforkEnabled(Hardfork.HF_Aspidochelone)) { - buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network + random_times++); + buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings!.Network + random_times++); price = 1 << 13; } else { - buffer = nonceData = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network); + buffer = nonceData = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings!.Network); price = 1 << 4; } AddGas(price * ExecFeeFactor); @@ -331,7 +330,7 @@ protected internal void RuntimeLog(byte[] state) try { string message = Utility.StrictUTF8.GetString(state); - Log?.Invoke(this, new LogEventArgs(ScriptContainer, CurrentScriptHash, message)); + Log?.Invoke(this, new LogEventArgs(ScriptContainer!, CurrentScriptHash!, message)); } catch { @@ -354,7 +353,7 @@ protected internal void RuntimeNotify(byte[] eventName, Array state) } if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); string name = Utility.StrictUTF8.GetString(eventName); - ContractState contract = CurrentContext.GetState().Contract; + ContractState? contract = CurrentContext?.GetState().Contract; if (contract is null) throw new InvalidOperationException("Notifications are not allowed in dynamic scripts."); var @event = contract.Manifest.Abi.Events.FirstOrDefault(p => string.Equals(p.Name, name, StringComparison.Ordinal)); @@ -371,18 +370,21 @@ protected internal void RuntimeNotify(byte[] eventName, Array state) using MemoryStream ms = new(MaxNotificationSize); using BinaryWriter writer = new(ms, Utility.StrictUTF8, true); BinarySerializer.Serialize(writer, state, MaxNotificationSize, Limits.MaxStackSize); - SendNotification(CurrentScriptHash, name, state); + if (CurrentScriptHash != null) + { + SendNotification(CurrentScriptHash, name, state); + } } protected internal void RuntimeNotifyV1(byte[] eventName, Array state) { if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); - if (CurrentContext.GetState().Contract is null) + if (CurrentContext?.GetState().Contract is null) throw new InvalidOperationException("Notifications are not allowed in dynamic scripts."); using MemoryStream ms = new(MaxNotificationSize); using BinaryWriter writer = new(ms, Utility.StrictUTF8, true); BinarySerializer.Serialize(writer, state, MaxNotificationSize, Limits.MaxStackSize); - SendNotification(CurrentScriptHash, Utility.StrictUTF8.GetString(eventName), state); + SendNotification(CurrentScriptHash!, Utility.StrictUTF8.GetString(eventName), state); } /// @@ -393,11 +395,14 @@ protected internal void RuntimeNotifyV1(byte[] eventName, Array state) /// The arguments of the event. protected internal void SendNotification(UInt160 hash, string eventName, Array state) { - NotifyEventArgs notification = new(ScriptContainer, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); - Notify?.Invoke(this, notification); + NotifyEventArgs notification = new(ScriptContainer!, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); + Notify.Invoke(this, notification); notifications ??= new List(); notifications.Add(notification); - CurrentContext.GetState().NotificationCount++; + if (CurrentContext != null) + { + CurrentContext.GetState().NotificationCount++; + } } /// @@ -406,12 +411,12 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s /// /// The hash of the specified contract. It can be set to to get all notifications. /// The notifications sent during the execution. - protected internal NotifyEventArgs[] GetNotifications(UInt160 hash) + protected internal NotifyEventArgs[] GetNotifications(UInt160? hash) { - IEnumerable notifications = Notifications; + IEnumerable notifyEventArgsEnumerable = Notifications; if (hash != null) // must filter by scriptHash - notifications = notifications.Where(p => p.ScriptHash == hash); - NotifyEventArgs[] array = notifications.ToArray(); + notifyEventArgsEnumerable = notifyEventArgsEnumerable.Where(p => p.ScriptHash == hash); + NotifyEventArgs[] array = notifyEventArgsEnumerable.ToArray(); if (array.Length > Limits.MaxStackSize) throw new InvalidOperationException(); return array; } @@ -432,7 +437,7 @@ protected internal void BurnGas(long gas) /// Get the Signers of the current transaction. /// /// The signers of the current transaction, or null if is not related to a transaction execution. - protected internal Signer[] GetCurrentSigners() + protected internal Signer[]? GetCurrentSigners() { if (ScriptContainer is Transaction tx) return tx.Signers; @@ -463,7 +468,10 @@ private static bool CheckItemType(StackItem item, ContractParameterType type) _ = Utility.StrictUTF8.GetString(item.GetSpan()); // Prevent any non-UTF8 string return true; } - catch { } + catch + { + // ignored + } } return false; } diff --git a/src/Neo/SmartContract/ApplicationEngine.Storage.cs b/src/Neo/SmartContract/ApplicationEngine.Storage.cs index 3a8bb9d122..557e1f73bc 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Storage.cs @@ -9,6 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.IO; using Neo.Persistence; using Neo.SmartContract.Iterators; using Neo.SmartContract.Native; @@ -77,7 +78,7 @@ partial class ApplicationEngine /// The storage context for the current contract. protected internal StorageContext GetStorageContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!)!; return new StorageContext { Id = contract.Id, @@ -92,7 +93,7 @@ protected internal StorageContext GetStorageContext() /// The storage context for the current contract. protected internal StorageContext GetReadOnlyContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!)!; return new StorageContext { Id = contract.Id, @@ -177,7 +178,7 @@ protected internal void Put(StorageContext context, byte[] key, byte[] value) Id = context.Id, Key = key }; - StorageItem item = Snapshot.GetAndChange(skey); + StorageItem? item = Snapshot.GetAndChange(skey); if (item is null) { newDataSize = key.Length + value.Length; diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index ba161e6951..8d99880871 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -40,20 +40,20 @@ public partial class ApplicationEngine : ExecutionEngine /// /// Triggered when a contract calls System.Runtime.Notify. /// - public static event EventHandler Notify; + public static event EventHandler Notify = null!; /// /// Triggered when a contract calls System.Runtime.Log. /// - public static event EventHandler Log; + public static event EventHandler Log = null!; private static readonly IList AllHardforks = Enum.GetValues(typeof(Hardfork)).Cast().ToArray(); - private static Dictionary services; + private static Dictionary? services; private readonly long gas_amount; - private Dictionary states; - private readonly DataCache originalSnapshot; - private List notifications; - private List disposables; + private Dictionary? states; + private readonly DataCache? originalSnapshot; + private List? notifications; + private List? disposables; private readonly Dictionary invocationCounter = new(); private readonly Dictionary contractTasks = new(); internal readonly uint ExecFeeFactor; @@ -63,17 +63,17 @@ public partial class ApplicationEngine : ExecutionEngine /// /// Gets or sets the provider used to create the . /// - public static IApplicationEngineProvider Provider { get; set; } + public static IApplicationEngineProvider? Provider { get; set; } /// /// Gets the descriptors of all interoperable services available in NEO. /// - public static IReadOnlyDictionary Services => services; + public static IReadOnlyDictionary Services => services!; /// /// The diagnostic used by the engine. This property can be . /// - public IDiagnostic Diagnostic { get; } + public IDiagnostic? Diagnostic { get; } private List Disposables => disposables ??= new List(); @@ -85,27 +85,27 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The container that containing the executed script. This field could be if the contract is invoked by system. /// - public IVerifiable ScriptContainer { get; } + public IVerifiable? ScriptContainer { get; } /// /// The snapshot used to read or write data. /// - public DataCache Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot; + public DataCache Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot ?? throw new InvalidOperationException("No snapshot available."); /// /// The block being persisted. This field could be if the is . /// - public Block PersistingBlock { get; } + public Block? PersistingBlock { get; } /// /// The used by the engine. /// - public ProtocolSettings ProtocolSettings { get; } + public ProtocolSettings? ProtocolSettings { get; } /// /// GAS spent to execute. /// - public long GasConsumed { get; private set; } = 0; + public long GasConsumed { get; private set; } /// /// The remaining GAS that can be spent in order to complete the execution. @@ -115,30 +115,30 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The exception that caused the execution to terminate abnormally. This field could be if no exception is thrown. /// - public Exception FaultException { get; private set; } + public Exception FaultException { get; private set; } = null!; /// /// The script hash of the current context. This field could be if no context is loaded to the engine. /// - public UInt160 CurrentScriptHash => CurrentContext?.GetScriptHash(); + public UInt160? CurrentScriptHash => CurrentContext?.GetScriptHash(); /// /// The script hash of the calling contract. This field could be if the current context is the entry context. /// - public UInt160 CallingScriptHash + public UInt160? CallingScriptHash { get { if (CurrentContext is null) return null; var state = CurrentContext.GetState(); - return state.NativeCallingScriptHash ?? state.CallingContext?.GetState().ScriptHash; + return state.NativeCallingScriptHash ?? state.CallingContext.GetState().ScriptHash; } } /// /// The script hash of the entry context. This field could be if no context is loaded to the engine. /// - public UInt160 EntryScriptHash => EntryContext?.GetScriptHash(); + public UInt160? EntryScriptHash => EntryContext?.GetScriptHash(); /// /// The notifications sent during the execution. @@ -155,7 +155,7 @@ public UInt160 CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic) { this.Trigger = trigger; this.ScriptContainer = container; @@ -202,9 +202,9 @@ internal void Throw(Exception ex) private ExecutionContext CallContractInternal(UInt160 contractHash, string method, CallFlags flags, bool hasReturnValue, StackItem[] args) { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Length); + ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Length); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Length} parameter(s) doesn't exist in the contract {contractHash}."); return CallContractInternal(contract, md, flags, hasReturnValue, args); } @@ -220,7 +220,7 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe } else { - ContractState currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + ContractState? currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!); if (currentContract?.CanCall(contract, method.Name) == false) throw new InvalidOperationException($"Cannot Call Method {method.Name} Of Contract {contract.Hash} From Contract {CurrentScriptHash}"); } @@ -234,7 +234,7 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe invocationCounter[contract.Hash] = 1; } - ExecutionContext currentContext = CurrentContext; + ExecutionContext currentContext = CurrentContext.NullExceptionOr(); ExecutionContextState state = currentContext.GetState(); CallFlags callingFlags = state.CallFlags; @@ -295,7 +295,7 @@ protected override void ContextUnloaded(ExecutionContext context) else { if (state.NotificationCount > 0) - notifications.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); + notifications?.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); } } Diagnostic?.ContextUnloaded(context); @@ -318,7 +318,7 @@ protected override void ContextUnloaded(ExecutionContext context) /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock = null, ProtocolSettings? settings = null, long gas = TestModeGas, IDiagnostic? diagnostic = null) { return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -378,12 +378,12 @@ public ExecutionContext LoadContract(ContractState contract, ContractMethodDescr /// The initial position of the instruction pointer. /// The action used to configure the state of the loaded context. /// The loaded context. - public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action configureState = null) + public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action? configureState = null) { // Create and configure context ExecutionContext context = CreateContext(script, rvcount, initialPosition); ExecutionContextState state = context.GetState(); - state.Snapshot = Snapshot?.CreateSnapshot(); + state.Snapshot = Snapshot.CreateSnapshot(); configureState?.Invoke(state); // Load context @@ -394,16 +394,16 @@ public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialP protected override ExecutionContext LoadToken(ushort tokenId) { ValidateCallFlags(CallFlags.ReadStates | CallFlags.AllowCall); - ContractState contract = CurrentContext.GetState().Contract; + ContractState? contract = CurrentContext?.GetState().Contract; if (contract is null || tokenId >= contract.Nef.Tokens.Length) throw new InvalidOperationException(); MethodToken token = contract.Nef.Tokens[tokenId]; - if (token.ParametersCount > CurrentContext.EvaluationStack.Count) + if (token.ParametersCount > CurrentContext?.EvaluationStack.Count) throw new InvalidOperationException(); StackItem[] args = new StackItem[token.ParametersCount]; for (int i = 0; i < token.ParametersCount; i++) args[i] = Pop(); - return CallContractInternal(token.Hash, token.Method, token.CallFlags, token.HasReturnValue, args); + return CallContractInternal(token.Hash!, token.Method!, token.CallFlags, token.HasReturnValue, args); } /// @@ -455,7 +455,7 @@ protected internal object Convert(StackItem item, InteropParameterDescriptor des Array av; if (item is VMArray array) { - av = Array.CreateInstance(descriptor.Type.GetElementType(), array.Count); + av = Array.CreateInstance(descriptor.Type.GetElementType()!, array.Count); for (int i = 0; i < av.Length; i++) av.SetValue(descriptor.Converter(array[i]), i); } @@ -463,7 +463,7 @@ protected internal object Convert(StackItem item, InteropParameterDescriptor des { int count = (int)item.GetInteger(); if (count > Limits.MaxStackSize) throw new InvalidOperationException(); - av = Array.CreateInstance(descriptor.Type.GetElementType(), count); + av = Array.CreateInstance(descriptor.Type.GetElementType()!, count); for (int i = 0; i < av.Length; i++) av.SetValue(descriptor.Converter(Pop()), i); } @@ -498,14 +498,14 @@ public override void Dispose() /// The requirements to check. internal protected void ValidateCallFlags(CallFlags requiredCallFlags) { - ExecutionContextState state = CurrentContext.GetState(); - if (!state.CallFlags.HasFlag(requiredCallFlags)) - throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state.CallFlags}."); + ExecutionContextState? state = CurrentContext?.GetState(); + if (state == null || !state.CallFlags.HasFlag(requiredCallFlags)) + throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state?.CallFlags}."); } protected override void OnSysCall(uint method) { - OnSysCall(services[method]); + OnSysCall(services![method]); } /// @@ -521,8 +521,8 @@ protected virtual void OnSysCall(InteropDescriptor descriptor) for (int i = 0; i < parameters.Length; i++) parameters[i] = Convert(Pop(), descriptor.Parameters[i]); - object returnValue = descriptor.Handler.Invoke(this, parameters); - if (descriptor.Handler.ReturnType != typeof(void)) + object? returnValue = descriptor.Handler.Invoke(this, parameters); + if (returnValue is not null && descriptor.Handler.ReturnType != typeof(void)) Push(Convert(returnValue)); } @@ -541,7 +541,7 @@ protected override void PostExecuteInstruction(Instruction instruction) private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings settings) { UInt256 hash = NativeContract.Ledger.CurrentHash(snapshot); - Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash); + Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash)!; return new Block { Header = new Header @@ -565,7 +565,7 @@ private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings setti private static InteropDescriptor Register(string name, string handler, long fixedPrice, CallFlags requiredCallFlags) { MethodInfo method = typeof(ApplicationEngine).GetMethod(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) - ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).GetMethod; + ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)!.GetMethod!; InteropDescriptor descriptor = new() { Name = name, @@ -590,7 +590,7 @@ private static InteropDescriptor Register(string name, string handler, long fixe /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable container = null, Block persistingBlock = null, ProtocolSettings settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic diagnostic = null) + public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable? container = null, Block? persistingBlock = null, ProtocolSettings? settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic? diagnostic = null) { persistingBlock ??= CreateDummyBlock(snapshot, settings ?? ProtocolSettings.Default); ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -601,35 +601,38 @@ public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snaps public T GetState() { - if (states is null) return default; - if (!states.TryGetValue(typeof(T), out object state)) return default; + if (states is null) return default!; + if (!states.TryGetValue(typeof(T), out object? state)) return default!; return (T)state; } public void SetState(T state) { states ??= new Dictionary(); - states[typeof(T)] = state; + if (state != null) + { + states[typeof(T)] = state; + } } public bool IsHardforkEnabled(Hardfork hardfork) { // Return true if there's no specific configuration or PersistingBlock is null - if (PersistingBlock is null || ProtocolSettings.Hardforks.Count == 0) + if (PersistingBlock is null || ProtocolSettings?.Hardforks.Count == 0) return true; // If the hardfork isn't specified in the configuration, check if it's a new one. - if (!ProtocolSettings.Hardforks.ContainsKey(hardfork)) + if (ProtocolSettings is not null && !ProtocolSettings!.Hardforks.ContainsKey(hardfork)) { int currentHardforkIndex = AllHardforks.IndexOf(hardfork); - int lastConfiguredHardforkIndex = AllHardforks.IndexOf(ProtocolSettings.Hardforks.Keys.Last()); + int lastConfiguredHardforkIndex = AllHardforks.IndexOf(ProtocolSettings!.Hardforks.Keys.Last()); // If it's a newer hardfork compared to the ones in the configuration, disable it. if (currentHardforkIndex > lastConfiguredHardforkIndex) return false; } - if (ProtocolSettings.Hardforks.TryGetValue(hardfork, out uint height)) + if (ProtocolSettings is not null && ProtocolSettings!.Hardforks.TryGetValue(hardfork, out uint height)) { // If the hardfork has a specific height in the configuration, check the block height. return PersistingBlock.Index >= height; diff --git a/src/Neo/SmartContract/BinarySerializer.cs b/src/Neo/SmartContract/BinarySerializer.cs index 2bdeced678..14236e139a 100644 --- a/src/Neo/SmartContract/BinarySerializer.cs +++ b/src/Neo/SmartContract/BinarySerializer.cs @@ -39,7 +39,7 @@ public ContainerPlaceholder(StackItemType type, int count) ElementCount = count; } - public override bool Equals(StackItem other) => throw new NotSupportedException(); + public override bool Equals(StackItem? other) => throw new NotSupportedException(); public override int GetHashCode() => throw new NotSupportedException(); @@ -53,7 +53,7 @@ public ContainerPlaceholder(StackItemType type, int count) /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) { MemoryReader reader = new(data); return Deserialize(ref reader, (uint)Math.Min(data.Length, limits.MaxItemSize), limits.MaxStackSize, referenceCounter); @@ -66,7 +66,7 @@ public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLi /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) { return Deserialize(ref reader, limits.MaxItemSize, limits.MaxStackSize, referenceCounter); } @@ -79,7 +79,7 @@ public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimi /// The max of items to serialize /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter? referenceCounter = null) { Stack deserialized = new(); int undeserialized = 1; diff --git a/src/Neo/SmartContract/Contract.cs b/src/Neo/SmartContract/Contract.cs index dc60c42d50..45f8a3fe8b 100644 --- a/src/Neo/SmartContract/Contract.cs +++ b/src/Neo/SmartContract/Contract.cs @@ -25,14 +25,14 @@ public class Contract /// /// The script of the contract. /// - public byte[] Script; + public byte[]? Script; /// /// The parameters of the contract. /// - public ContractParameterType[] ParameterList; + public ContractParameterType[] ParameterList = Array.Empty(); - private UInt160 _scriptHash; + private UInt160? _scriptHash; /// /// The hash of the contract. /// @@ -42,9 +42,9 @@ public virtual UInt160 ScriptHash { if (_scriptHash == null) { - _scriptHash = Script.ToScriptHash(); + _scriptHash = Script?.ToScriptHash(); } - return _scriptHash; + return _scriptHash!; } } diff --git a/src/Neo/SmartContract/ContractParameter.cs b/src/Neo/SmartContract/ContractParameter.cs index 027fa50e00..a289156726 100644 --- a/src/Neo/SmartContract/ContractParameter.cs +++ b/src/Neo/SmartContract/ContractParameter.cs @@ -10,6 +10,7 @@ // modifications are permitted. using Neo.Cryptography.ECC; +using Neo.IO; using Neo.Json; using System; using System.Collections.Generic; @@ -32,7 +33,7 @@ public class ContractParameter /// /// The value of the parameter. /// - public object Value; + public object? Value; /// /// Initializes a new instance of the class. @@ -72,20 +73,21 @@ public static ContractParameter FromJson(JObject json) { ContractParameter parameter = new() { - Type = Enum.Parse(json["type"].GetString()) + Type = Enum.Parse(json["type"]!.GetString()) }; - if (json["value"] != null) + var value = json["value"]; + if (value != null) parameter.Value = parameter.Type switch { - ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(json["value"].AsString()), - ContractParameterType.Boolean => json["value"].AsBoolean(), - ContractParameterType.Integer => BigInteger.Parse(json["value"].AsString()), - ContractParameterType.Hash160 => UInt160.Parse(json["value"].AsString()), - ContractParameterType.Hash256 => UInt256.Parse(json["value"].AsString()), - ContractParameterType.PublicKey => ECPoint.Parse(json["value"].AsString(), ECCurve.Secp256r1), - ContractParameterType.String => json["value"].AsString(), - ContractParameterType.Array => ((JArray)json["value"]).Select(p => FromJson((JObject)p)).ToList(), - ContractParameterType.Map => ((JArray)json["value"]).Select(p => new KeyValuePair(FromJson((JObject)p["key"]), FromJson((JObject)p["value"]))).ToList(), + ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(value.AsString()), + ContractParameterType.Boolean => value.AsBoolean(), + ContractParameterType.Integer => BigInteger.Parse(value.AsString()), + ContractParameterType.Hash160 => UInt160.Parse(value.AsString()), + ContractParameterType.Hash256 => UInt256.Parse(value.AsString()), + ContractParameterType.PublicKey => ECPoint.Parse(value.AsString(), ECCurve.Secp256r1), + ContractParameterType.String => value.AsString(), + ContractParameterType.Array => ((JArray)value).Select(p => FromJson(p.NullExceptionOr())).ToList(), + ContractParameterType.Map => ((JArray)value).Select(p => new KeyValuePair(FromJson((JObject)p!["key"]!), FromJson(p["value"].NullExceptionOr()))).ToList(), _ => throw new ArgumentException(null, nameof(json)), }; return parameter; @@ -139,7 +141,7 @@ public JObject ToJson() return ToJson(this, null); } - private static JObject ToJson(ContractParameter parameter, HashSet context) + private static JObject ToJson(ContractParameter parameter, HashSet? context) { JObject json = new(); json["type"] = parameter.Type; @@ -191,7 +193,7 @@ public override string ToString() return ToString(this, null); } - private static string ToString(ContractParameter parameter, HashSet context) + private static string ToString(ContractParameter parameter, HashSet? context) { switch (parameter.Value) { @@ -246,7 +248,7 @@ private static string ToString(ContractParameter parameter, HashSet Signatures; public ContextItem(Contract contract) { - this.Script = contract.Script; + this.Script = contract.Script!; this.Parameters = contract.ParameterList.Select(p => new ContractParameter { Type = p }).ToArray(); this.Signatures = new Dictionary(); } public ContextItem(JObject json) { - this.Script = Convert.FromBase64String(json["script"].AsString()); - this.Parameters = ((JArray)json["parameters"]).Select(p => ContractParameter.FromJson((JObject)p)).ToArray(); - this.Signatures = ((JObject)json["signatures"]).Properties.Select(p => new + this.Script = Convert.FromBase64String(json["script"]!.AsString()); + this.Parameters = json["parameters"].NullExceptionOr().Select(p => ContractParameter.FromJson(p.NullExceptionOr())).ToArray(); + this.Signatures = json["signatures"].NullExceptionOr().Properties.Select(p => new { PublicKey = ECPoint.Parse(p.Key, ECCurve.Secp256r1), - Signature = Convert.FromBase64String(p.Value.AsString()) + Signature = Convert.FromBase64String(p.Value!.AsString()) }).ToDictionary(p => p.PublicKey, p => p.Signature); } public JObject ToJson() { JObject json = new(); - json["script"] = Convert.ToBase64String(Script); + json["script"] = Convert.ToBase64String(Script!); json["parameters"] = new JArray(Parameters.Select(p => p.ToJson())); json["signatures"] = new JObject(); foreach (var signature in Signatures) - json["signatures"][signature.Key.ToString()] = Convert.ToBase64String(signature.Value); + json["signatures"]![signature.Key.ToString()] = Convert.ToBase64String(signature.Value); return json; } } @@ -80,7 +80,7 @@ public JObject ToJson() /// public readonly uint Network; - private readonly Dictionary ContextItems; + private readonly Dictionary ContextItems; /// /// Determines whether all witnesses are ready to be added. @@ -95,7 +95,7 @@ public bool Completed } } - private UInt160[] _ScriptHashes = null; + private UInt160[]? _ScriptHashes; /// /// Gets the script hashes to be verified for the . /// @@ -111,7 +111,7 @@ public ContractParametersContext(DataCache snapshot, IVerifiable verifiable, uin { this.Verifiable = verifiable; this.Snapshot = snapshot; - this.ContextItems = new Dictionary(); + this.ContextItems = new Dictionary(); this.Network = network; } @@ -124,7 +124,7 @@ public ContractParametersContext(DataCache snapshot, IVerifiable verifiable, uin /// if the parameter is added successfully; otherwise, . public bool Add(Contract contract, int index, object parameter) { - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; item.Parameters[index].Value = parameter; return true; @@ -138,7 +138,7 @@ public bool Add(Contract contract, int index, object parameter) /// if the parameters are added successfully; otherwise, . public bool Add(Contract contract, params object[] parameters) { - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; for (int index = 0; index < parameters.Length; index++) { @@ -156,10 +156,10 @@ public bool Add(Contract contract, params object[] parameters) /// if the signature is added successfully; otherwise, . public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) { - if (IsMultiSigContract(contract.Script, out _, out ECPoint[] points)) + if (IsMultiSigContract(contract.Script, out _, out ECPoint[]? points)) { if (!points.Contains(pubkey)) return false; - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; if (item.Parameters.All(p => p.Value != null)) return false; if (!item.Signatures.TryAdd(pubkey, signature)) @@ -198,7 +198,7 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) // return now to prevent array index out of bounds exception return false; } - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; if (!item.Signatures.TryAdd(pubkey, signature)) return false; @@ -207,9 +207,9 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) } } - private ContextItem CreateItem(Contract contract) + private ContextItem? CreateItem(Contract contract) { - if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem item)) + if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem? item)) return item; if (!ScriptHashes.Contains(contract.ScriptHash)) return null; @@ -226,22 +226,22 @@ private ContextItem CreateItem(Contract contract) /// The converted context. public static ContractParametersContext FromJson(JObject json, DataCache snapshot) { - var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"].AsString()); + var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"]!.AsString()); if (!typeof(IVerifiable).IsAssignableFrom(type)) throw new FormatException(); - var verifiable = (IVerifiable)Activator.CreateInstance(type); - byte[] data = Convert.FromBase64String(json["data"].AsString()); + var verifiable = (IVerifiable)Activator.CreateInstance(type)!; + byte[] data = Convert.FromBase64String(json["data"]!.AsString()); MemoryReader reader = new(data); verifiable.DeserializeUnsigned(ref reader); if (json.ContainsProperty("hash")) { - UInt256 hash = UInt256.Parse(json["hash"].GetString()); + UInt256? hash = UInt256.Parse(json["hash"]!.GetString()); if (hash != verifiable.Hash) throw new FormatException(); } - ContractParametersContext context = new(snapshot, verifiable, (uint)json["network"].GetInt32()); - foreach (var (key, value) in ((JObject)json["items"]).Properties) + ContractParametersContext context = new(snapshot, verifiable, (uint)json["network"]!.GetInt32()); + foreach (var (key, value) in ((JObject)json["items"]!).Properties) { - context.ContextItems.Add(UInt160.Parse(key), new ContextItem((JObject)value)); + context.ContextItems.Add(UInt160.Parse(key), new ContextItem((JObject)value!)); } return context; } @@ -252,7 +252,7 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// The hash of the witness script. /// The specified index. /// The parameter with the specified index. - public ContractParameter GetParameter(UInt160 scriptHash, int index) + public ContractParameter? GetParameter(UInt160 scriptHash, int index) { return GetParameters(scriptHash)?[index]; } @@ -262,11 +262,11 @@ public ContractParameter GetParameter(UInt160 scriptHash, int index) /// /// The hash of the witness script. /// The parameters from the witness script. - public IReadOnlyList GetParameters(UInt160 scriptHash) + public IReadOnlyList? GetParameters(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) return null; - return item.Parameters; + return item?.Parameters; } /// @@ -274,11 +274,11 @@ public IReadOnlyList GetParameters(UInt160 scriptHash) /// /// The hash of the witness script. /// The signatures from the witness script. - public IReadOnlyDictionary GetSignatures(UInt160 scriptHash) + public IReadOnlyDictionary? GetSignatures(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) return null; - return item.Signatures; + return item?.Signatures; } /// @@ -286,11 +286,11 @@ public IReadOnlyDictionary GetSignatures(UInt160 scriptHash) /// /// The hash of the witness script. /// The witness script. - public byte[] GetScript(UInt160 scriptHash) + public byte[]? GetScript(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) return null; - return item.Script; + return item?.Script; } /// @@ -304,7 +304,8 @@ public Witness[] GetWitnesses() Witness[] witnesses = new Witness[ScriptHashes.Count]; for (int i = 0; i < ScriptHashes.Count; i++) { - ContextItem item = ContextItems[ScriptHashes[i]]; + ContextItem? item = ContextItems[ScriptHashes[i]]; + if (item == null) continue; using ScriptBuilder sb = new(); for (int j = item.Parameters.Length - 1; j >= 0; j--) { @@ -327,7 +328,7 @@ public Witness[] GetWitnesses() /// The parsed context. public static ContractParametersContext Parse(string value, DataCache snapshot) { - return FromJson((JObject)JToken.Parse(value), snapshot); + return FromJson((JObject)JToken.Parse(value)!, snapshot); } /// @@ -348,7 +349,7 @@ public JObject ToJson() } json["items"] = new JObject(); foreach (var item in ContextItems) - json["items"][item.Key.ToString()] = item.Value.ToJson(); + json["items"]![item.Key.ToString()] = item!.Value!.ToJson(); json["network"] = Network; return json; } diff --git a/src/Neo/SmartContract/ContractState.cs b/src/Neo/SmartContract/ContractState.cs index 83ac9d3353..873b65f514 100644 --- a/src/Neo/SmartContract/ContractState.cs +++ b/src/Neo/SmartContract/ContractState.cs @@ -38,17 +38,17 @@ public class ContractState : IInteroperable /// /// The hash of the contract. /// - public UInt160 Hash; + public UInt160 Hash = null!; /// /// The nef of the contract. /// - public NefFile Nef; + public NefFile Nef = null!; /// /// The manifest of the contract. /// - public ContractManifest Manifest; + public ContractManifest Manifest = null!; /// /// The script of the contract. @@ -114,9 +114,9 @@ public JObject ToJson() }; } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { - return new Array(referenceCounter, new StackItem[] { Id, (int)UpdateCounter, Hash.ToArray(), Nef.ToArray(), Manifest.ToStackItem(referenceCounter) }); + return new Array(referenceCounter, new[] { Id, (int)UpdateCounter, Hash.ToArray(), Nef.ToArray(), Manifest.ToStackItem(referenceCounter) }); } } } diff --git a/src/Neo/SmartContract/ContractTask.cs b/src/Neo/SmartContract/ContractTask.cs index 6df3627c37..72d4b91472 100644 --- a/src/Neo/SmartContract/ContractTask.cs +++ b/src/Neo/SmartContract/ContractTask.cs @@ -33,7 +33,7 @@ public ContractTask() protected virtual ContractTaskAwaiter CreateAwaiter() => new(); public virtual ContractTaskAwaiter GetAwaiter() => awaiter; - public virtual object GetResult() => null; + public virtual object? GetResult() => null; } [AsyncMethodBuilder(typeof(ContractTaskMethodBuilder<>))] @@ -41,6 +41,6 @@ class ContractTask : ContractTask { protected override ContractTaskAwaiter CreateAwaiter() => new ContractTaskAwaiter(); public override ContractTaskAwaiter GetAwaiter() => (ContractTaskAwaiter)base.GetAwaiter(); - public override object GetResult() => ((ContractTaskAwaiter)GetAwaiter()).GetResult(); + public override object? GetResult() => ((ContractTaskAwaiter)GetAwaiter()).GetResult(); } } diff --git a/src/Neo/SmartContract/ContractTaskAwaiter.cs b/src/Neo/SmartContract/ContractTaskAwaiter.cs index a0a0c9a1bb..2bd23d3fc2 100644 --- a/src/Neo/SmartContract/ContractTaskAwaiter.cs +++ b/src/Neo/SmartContract/ContractTaskAwaiter.cs @@ -17,15 +17,15 @@ namespace Neo.SmartContract { class ContractTaskAwaiter : INotifyCompletion { - private Action continuation; - private Exception exception; + private Action _continuation = null!; + private Exception _exception = null!; public bool IsCompleted { get; private set; } public void GetResult() { - if (exception is not null) - throw exception; + if (_exception is not null) + throw _exception; } public void SetResult() => RunContinuation(); @@ -34,35 +34,35 @@ public void GetResult() public void SetException(Exception exception) { - this.exception = exception; + this._exception = exception; RunContinuation(); } public void OnCompleted(Action continuation) { - Interlocked.CompareExchange(ref this.continuation, continuation, null); + Interlocked.CompareExchange(ref this._continuation, continuation, null); } protected void RunContinuation() { IsCompleted = true; - continuation?.Invoke(); + _continuation.Invoke(); } } class ContractTaskAwaiter : ContractTaskAwaiter { - private T result; + private T _result = default!; public new T GetResult() { base.GetResult(); - return result; + return _result; } public void SetResult(T result) { - this.result = result; + this._result = result; RunContinuation(); } diff --git a/src/Neo/SmartContract/ContractTaskMethodBuilder.cs b/src/Neo/SmartContract/ContractTaskMethodBuilder.cs index bae1146f25..2cf6030635 100644 --- a/src/Neo/SmartContract/ContractTaskMethodBuilder.cs +++ b/src/Neo/SmartContract/ContractTaskMethodBuilder.cs @@ -16,7 +16,7 @@ namespace Neo.SmartContract { sealed class ContractTaskMethodBuilder { - private ContractTask task; + private ContractTask? task; public ContractTask Task => task ??= new ContractTask(); @@ -58,7 +58,7 @@ public void SetStateMachine(IAsyncStateMachine stateMachine) sealed class ContractTaskMethodBuilder { - private ContractTask task; + private ContractTask? task; public ContractTask Task => task ??= new ContractTask(); diff --git a/src/Neo/SmartContract/DeployedContract.cs b/src/Neo/SmartContract/DeployedContract.cs index 0587a029e5..4ea6c7845d 100644 --- a/src/Neo/SmartContract/DeployedContract.cs +++ b/src/Neo/SmartContract/DeployedContract.cs @@ -32,7 +32,7 @@ public DeployedContract(ContractState contract) Script = null; ScriptHash = contract.Hash; - ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor? descriptor = contract.Manifest.Abi.GetMethod("verify", -1); if (descriptor is null) throw new NotSupportedException("The smart contract haven't got verify method."); ParameterList = descriptor.Parameters.Select(u => u.Type).ToArray(); diff --git a/src/Neo/SmartContract/ExecutionContextState.cs b/src/Neo/SmartContract/ExecutionContextState.cs index 8b61ff1197..abbdfb3aa1 100644 --- a/src/Neo/SmartContract/ExecutionContextState.cs +++ b/src/Neo/SmartContract/ExecutionContextState.cs @@ -22,29 +22,29 @@ public class ExecutionContextState /// /// The script hash of the current context. /// - public UInt160 ScriptHash { get; set; } + public UInt160? ScriptHash { get; set; } /// /// The calling context. /// - public ExecutionContext CallingContext { get; set; } + public ExecutionContext CallingContext { get; set; } = null!; /// /// The script hash of the calling native contract. Used in native contracts only. /// - internal UInt160 NativeCallingScriptHash { get; set; } + internal UInt160? NativeCallingScriptHash { get; set; } /// /// The of the current context. /// - public ContractState Contract { get; set; } + public ContractState Contract { get; set; } = null!; /// /// The of the current context. /// public CallFlags CallFlags { get; set; } = CallFlags.All; - public DataCache Snapshot { get; set; } + public DataCache Snapshot { get; set; } = null!; public int NotificationCount { get; set; } diff --git a/src/Neo/SmartContract/Helper.cs b/src/Neo/SmartContract/Helper.cs index 5045c74717..1b12b2fd28 100644 --- a/src/Neo/SmartContract/Helper.cs +++ b/src/Neo/SmartContract/Helper.cs @@ -20,6 +20,7 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Neo.SmartContract @@ -110,7 +111,7 @@ public static UInt160 GetContractHash(UInt160 sender, uint nefCheckSum, string n /// The script hash of the context. public static UInt160 GetScriptHash(this ExecutionContext context) { - return context.GetState().ScriptHash; + return context.GetState().ScriptHash!; } /// @@ -142,7 +143,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out /// The minimum number of correct signatures that need to be provided in order for the verification to pass. /// The public keys in the account. /// if the contract is a multi-signature contract; otherwise, . - public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out ECPoint[] points) + public static bool IsMultiSigContract(ReadOnlySpan script, out int m, [NotNullWhen(true)] out ECPoint[]? points) { List list = new(); if (IsMultiSigContract(script, out m, out _, list)) @@ -157,7 +158,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out } } - private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List points) + private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List? points) { m = 0; n = 0; int i = 0; @@ -316,13 +317,13 @@ internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings { return false; } - using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.CreateSnapshot(), null, settings, gas)) + using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot.CreateSnapshot(), null, settings, gas)) { if (witness.VerificationScript.Length == 0) { - ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash); + ContractState? cs = NativeContract.ContractManagement.GetContract(snapshot, hash); if (cs is null) return false; - ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor? md = cs.Manifest.Abi.GetMethod("verify", -1); if (md?.ReturnType != ContractParameterType.Boolean) return false; engine.LoadContract(cs, md, CallFlags.ReadOnly); } diff --git a/src/Neo/SmartContract/IApplicationEngineProvider.cs b/src/Neo/SmartContract/IApplicationEngineProvider.cs index ef06c6b92c..d39286fda8 100644 --- a/src/Neo/SmartContract/IApplicationEngineProvider.cs +++ b/src/Neo/SmartContract/IApplicationEngineProvider.cs @@ -30,6 +30,6 @@ public interface IApplicationEngineProvider /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic); + ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic); } } diff --git a/src/Neo/SmartContract/IInteroperable.cs b/src/Neo/SmartContract/IInteroperable.cs index 5254898efe..d9009625b1 100644 --- a/src/Neo/SmartContract/IInteroperable.cs +++ b/src/Neo/SmartContract/IInteroperable.cs @@ -31,7 +31,7 @@ public interface IInteroperable /// /// The used by the . /// The converted . - StackItem ToStackItem(ReferenceCounter referenceCounter); + StackItem ToStackItem(ReferenceCounter? referenceCounter); public IInteroperable Clone() { diff --git a/src/Neo/SmartContract/InteropDescriptor.cs b/src/Neo/SmartContract/InteropDescriptor.cs index 29c88f46ed..f21ba88b49 100644 --- a/src/Neo/SmartContract/InteropDescriptor.cs +++ b/src/Neo/SmartContract/InteropDescriptor.cs @@ -26,7 +26,7 @@ public record InteropDescriptor /// /// The name of the interoperable service. /// - public string Name { get; init; } + public string Name { get; init; } = null!; private uint _hash; /// @@ -45,9 +45,9 @@ public uint Hash /// /// The used to handle the interoperable service. /// - public MethodInfo Handler { get; init; } + public MethodInfo Handler { get; init; } = null!; - private IReadOnlyList _parameters; + private IReadOnlyList? _parameters; /// /// The parameters of the interoperable service. /// diff --git a/src/Neo/SmartContract/InteropParameterDescriptor.cs b/src/Neo/SmartContract/InteropParameterDescriptor.cs index 6a65beb93f..603c91f3ad 100644 --- a/src/Neo/SmartContract/InteropParameterDescriptor.cs +++ b/src/Neo/SmartContract/InteropParameterDescriptor.cs @@ -24,12 +24,12 @@ namespace Neo.SmartContract /// public class InteropParameterDescriptor { - private readonly ValidatorAttribute[] validators; + private readonly ValidatorAttribute[] validators = null!; /// /// The name of the parameter. /// - public string Name { get; } + public string Name { get; } = null!; /// /// The type of the parameter. @@ -56,7 +56,7 @@ public class InteropParameterDescriptor /// public bool IsInterface { get; } - private static readonly Dictionary> converters = new() + private static readonly Dictionary> converters = new() { [typeof(StackItem)] = p => p, [typeof(VM.Types.Pointer)] = p => p, @@ -82,7 +82,7 @@ public class InteropParameterDescriptor internal InteropParameterDescriptor(ParameterInfo parameterInfo) : this(parameterInfo.ParameterType) { - this.Name = parameterInfo.Name; + this.Name = parameterInfo.Name!; this.validators = parameterInfo.GetCustomAttributes(true).ToArray(); } @@ -91,19 +91,19 @@ internal InteropParameterDescriptor(Type type) this.Type = type; if (IsEnum) { - Converter = converters[type.GetEnumUnderlyingType()]; + Converter = converters[type.GetEnumUnderlyingType()]!; } else if (IsArray) { - Converter = converters[type.GetElementType()]; + Converter = converters[type.GetElementType()!]!; } else { IsInterface = !converters.TryGetValue(type, out var converter); if (IsInterface) - Converter = converters[typeof(InteropInterface)]; + Converter = converters[typeof(InteropInterface)]!; else - Converter = converter; + Converter = converter!; } } diff --git a/src/Neo/SmartContract/JsonSerializer.cs b/src/Neo/SmartContract/JsonSerializer.cs index 4d77104a6e..ca2d0eaffd 100644 --- a/src/Neo/SmartContract/JsonSerializer.cs +++ b/src/Neo/SmartContract/JsonSerializer.cs @@ -36,7 +36,7 @@ public static class JsonSerializer /// /// The to serialize. /// The serialized object. - public static JToken Serialize(StackItem item) + public static JToken? Serialize(StackItem item) { switch (item) { @@ -71,7 +71,10 @@ public static JToken Serialize(StackItem item) var key = entry.Key.GetString(); var value = Serialize(entry.Value); - ret[key] = value; + if (key != null) + { + ret[key] = value; + } } return ret; @@ -142,7 +145,7 @@ public static byte[] SerializeToByteArray(StackItem item, uint maxSize) writer.WriteEndObject(); break; case JsonTokenType.PropertyName: - writer.WritePropertyName(((StackItem)stack.Pop()).GetString()); + writer.WritePropertyName(((StackItem)stack.Pop()!).GetString()!); break; case Null _: writer.WriteNullValue(); @@ -165,13 +168,13 @@ public static byte[] SerializeToByteArray(StackItem item, uint maxSize) /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ApplicationEngine engine, JToken json, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ApplicationEngine engine, JToken json, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) { uint maxStackSize = limits.MaxStackSize; return Deserialize(engine, json, ref maxStackSize, referenceCounter); } - private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref uint maxStackSize, ReferenceCounter referenceCounter) + private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref uint maxStackSize, ReferenceCounter? referenceCounter) { if (maxStackSize-- == 0) throw new FormatException(); switch (json) @@ -183,7 +186,7 @@ private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref case JArray array: { List list = new(array.Count); - foreach (JToken obj in array) + foreach (JToken obj in array.Select(p => p != null)) list.Add(Deserialize(engine, obj, ref maxStackSize, referenceCounter)); return new Array(referenceCounter, list); } @@ -213,7 +216,7 @@ private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref if (maxStackSize-- == 0) throw new FormatException(); var key = entry.Key; - var value = Deserialize(engine, entry.Value, ref maxStackSize, referenceCounter); + var value = Deserialize(engine, entry.Value!, ref maxStackSize, referenceCounter); item[key] = value; } diff --git a/src/Neo/SmartContract/Manifest/ContractAbi.cs b/src/Neo/SmartContract/Manifest/ContractAbi.cs index 3660d1a99e..b9df716799 100644 --- a/src/Neo/SmartContract/Manifest/ContractAbi.cs +++ b/src/Neo/SmartContract/Manifest/ContractAbi.cs @@ -25,17 +25,17 @@ namespace Neo.SmartContract.Manifest /// For more details, see NEP-14. public class ContractAbi : IInteroperable { - private IReadOnlyDictionary<(string, int), ContractMethodDescriptor> methodDictionary; + private IReadOnlyDictionary<(string, int), ContractMethodDescriptor>? methodDictionary; /// /// Gets the methods in the ABI. /// - public ContractMethodDescriptor[] Methods { get; set; } + public ContractMethodDescriptor[] Methods { get; set; } = null!; /// /// Gets the events in the ABI. /// - public ContractEventDescriptor[] Events { get; set; } + public ContractEventDescriptor[] Events { get; set; } = null!; void IInteroperable.FromStackItem(StackItem stackItem) { @@ -44,7 +44,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) Events = ((Array)@struct[1]).Select(p => p.ToInteroperable()).ToArray(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { @@ -62,8 +62,8 @@ public static ContractAbi FromJson(JObject json) { ContractAbi abi = new() { - Methods = ((JArray)json["methods"]).Select(u => ContractMethodDescriptor.FromJson((JObject)u)).ToArray(), - Events = ((JArray)json["events"]).Select(u => ContractEventDescriptor.FromJson((JObject)u)).ToArray() + Methods = json["methods"].NullExceptionOr().Select(u => ContractMethodDescriptor.FromJson(u.NullExceptionOr())).ToArray(), + Events = json["events"].NullExceptionOr().Select(u => ContractEventDescriptor.FromJson(u.NullExceptionOr())).ToArray() }; if (abi.Methods.Length == 0) throw new FormatException(); return abi; @@ -75,7 +75,7 @@ public static ContractAbi FromJson(JObject json) /// The name of the method. /// The number of parameters of the method. It can be set to -1 to search for the method with the specified name and any number of parameters. /// The method that matches the specified name and number of parameters. If is set to -1, the first method with the specified name will be returned. - public ContractMethodDescriptor GetMethod(string name, int pcount) + public ContractMethodDescriptor? GetMethod(string name, int pcount) { if (pcount < -1 || pcount > ushort.MaxValue) throw new ArgumentOutOfRangeException(nameof(pcount)); if (pcount >= 0) diff --git a/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs index 90227dd78d..7a637c12cc 100644 --- a/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs @@ -9,6 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.IO; using Neo.Json; using Neo.VM; using Neo.VM.Types; @@ -26,21 +27,21 @@ public class ContractEventDescriptor : IInteroperable /// /// The name of the event or method. /// - public string Name { get; set; } + public string Name { get; set; } = null!; /// /// The parameters of the event or method. /// - public ContractParameterDefinition[] Parameters { get; set; } + public ContractParameterDefinition[] Parameters { get; set; } = null!; public virtual void FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; - Name = @struct[0].GetString(); + Name = @struct[0].GetString()!; Parameters = ((Array)@struct[1]).Select(p => p.ToInteroperable()).ToArray(); } - public virtual StackItem ToStackItem(ReferenceCounter referenceCounter) + public virtual StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { @@ -58,8 +59,8 @@ public static ContractEventDescriptor FromJson(JObject json) { ContractEventDescriptor descriptor = new() { - Name = json["name"].GetString(), - Parameters = ((JArray)json["parameters"]).Select(u => ContractParameterDefinition.FromJson((JObject)u)).ToArray(), + Name = json["name"]!.GetString(), + Parameters = json["parameters"].NullExceptionOr().Select(u => ContractParameterDefinition.FromJson(u.NullExceptionOr())).ToArray(), }; if (string.IsNullOrEmpty(descriptor.Name)) throw new FormatException(); _ = descriptor.Parameters.ToDictionary(p => p.Name); diff --git a/src/Neo/SmartContract/Manifest/ContractGroup.cs b/src/Neo/SmartContract/Manifest/ContractGroup.cs index 231354327c..b24ba00613 100644 --- a/src/Neo/SmartContract/Manifest/ContractGroup.cs +++ b/src/Neo/SmartContract/Manifest/ContractGroup.cs @@ -29,12 +29,12 @@ public class ContractGroup : IInteroperable /// /// The public key of the group. /// - public ECPoint PubKey { get; set; } + public ECPoint PubKey { get; set; } = null!; /// /// The signature of the contract hash which can be verified by . /// - public byte[] Signature { get; set; } + public byte[] Signature { get; set; } = null!; void IInteroperable.FromStackItem(StackItem stackItem) { @@ -43,7 +43,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) Signature = @struct[1].GetSpan().ToArray(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { PubKey.ToArray(), Signature }; } @@ -57,8 +57,8 @@ public static ContractGroup FromJson(JObject json) { ContractGroup group = new() { - PubKey = ECPoint.Parse(json["pubkey"].GetString(), ECCurve.Secp256r1), - Signature = Convert.FromBase64String(json["signature"].GetString()), + PubKey = ECPoint.Parse(json["pubkey"]!.GetString(), ECCurve.Secp256r1), + Signature = Convert.FromBase64String(json["signature"]!.GetString()), }; if (group.Signature.Length != 64) throw new FormatException(); return group; diff --git a/src/Neo/SmartContract/Manifest/ContractManifest.cs b/src/Neo/SmartContract/Manifest/ContractManifest.cs index 078e8fd35e..7bdb4575aa 100644 --- a/src/Neo/SmartContract/Manifest/ContractManifest.cs +++ b/src/Neo/SmartContract/Manifest/ContractManifest.cs @@ -35,47 +35,47 @@ public class ContractManifest : IInteroperable /// /// The name of the contract. /// - public string Name { get; set; } + public string Name { get; set; } = null!; /// /// The groups of the contract. /// - public ContractGroup[] Groups { get; set; } + public ContractGroup[] Groups { get; set; } = null!; /// /// Indicates which standards the contract supports. It can be a list of NEPs. /// - public string[] SupportedStandards { get; set; } + public string[] SupportedStandards { get; set; } = null!; /// /// The ABI of the contract. /// - public ContractAbi Abi { get; set; } + public ContractAbi Abi { get; set; } = null!; /// /// The permissions of the contract. /// - public ContractPermission[] Permissions { get; set; } + public ContractPermission[] Permissions { get; set; } = null!; /// /// The trusted contracts and groups of the contract. /// If a contract is trusted, the user interface will not give any warnings when called by the contract. /// - public WildcardContainer Trusts { get; set; } + public WildcardContainer Trusts { get; set; } = null!; /// /// Custom user data. /// - public JObject Extra { get; set; } + public JObject? Extra { get; set; } void IInteroperable.FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; - Name = @struct[0].GetString(); + Name = @struct[0].GetString().NullExceptionOr(); Groups = ((Array)@struct[1]).Select(p => p.ToInteroperable()).ToArray(); if (((Map)@struct[2]).Count != 0) throw new ArgumentException(null, nameof(stackItem)); - SupportedStandards = ((Array)@struct[3]).Select(p => p.GetString()).ToArray(); + SupportedStandards = @struct[3].NullExceptionOr().Select(p => p.GetString()).ToArray()!; Abi = @struct[4].ToInteroperable(); Permissions = ((Array)@struct[5]).Select(p => p.ToInteroperable()).ToArray(); Trusts = @struct[6] switch @@ -85,10 +85,10 @@ void IInteroperable.FromStackItem(StackItem stackItem) Array array => WildcardContainer.Create(array.Select(ContractPermissionDescriptor.Create).ToArray()), _ => throw new ArgumentException(null, nameof(stackItem)) }; - Extra = (JObject)JToken.Parse(@struct[7].GetSpan()); + Extra = (JObject)JToken.Parse(@struct[7].GetSpan())!; } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { @@ -112,13 +112,13 @@ public static ContractManifest FromJson(JObject json) { ContractManifest manifest = new() { - Name = json["name"].GetString(), - Groups = ((JArray)json["groups"]).Select(u => ContractGroup.FromJson((JObject)u)).ToArray(), - SupportedStandards = ((JArray)json["supportedstandards"]).Select(u => u.GetString()).ToArray(), - Abi = ContractAbi.FromJson((JObject)json["abi"]), - Permissions = ((JArray)json["permissions"]).Select(u => ContractPermission.FromJson((JObject)u)).ToArray(), - Trusts = WildcardContainer.FromJson(json["trusts"], u => ContractPermissionDescriptor.FromJson((JString)u)), - Extra = (JObject)json["extra"] + Name = json["name"]!.GetString(), + Groups = json["groups"].NullExceptionOr().Select(u => ContractGroup.FromJson(u.NullExceptionOr())).ToArray(), + SupportedStandards = json["supportedstandards"].NullExceptionOr().Select(u => u!.GetString()).ToArray(), + Abi = ContractAbi.FromJson(json["abi"].NullExceptionOr()), + Permissions = json["permissions"].NullExceptionOr().Select(u => ContractPermission.FromJson(u.NullExceptionOr())).ToArray(), + Trusts = WildcardContainer.FromJson(json["trusts"]!, u => ContractPermissionDescriptor.FromJson((JString)u)), + Extra = json["extra"].NullExceptionOr() }; if (string.IsNullOrEmpty(manifest.Name)) throw new FormatException(); @@ -141,7 +141,7 @@ public static ContractManifest FromJson(JObject json) public static ContractManifest Parse(ReadOnlySpan json) { if (json.Length > MaxLength) throw new ArgumentException(null, nameof(json)); - return FromJson((JObject)JToken.Parse(json)); + return FromJson(JToken.Parse(json).NullExceptionOr()); } /// diff --git a/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs index cc8d0a16d5..84ee8b2963 100644 --- a/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs @@ -9,6 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.IO; using Neo.Json; using Neo.VM; using Neo.VM.Types; @@ -47,7 +48,7 @@ public override void FromStackItem(StackItem stackItem) Safe = @struct[4].GetBoolean(); } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { Struct @struct = (Struct)base.ToStackItem(referenceCounter); @struct.Add((byte)ReturnType); @@ -65,11 +66,11 @@ public override StackItem ToStackItem(ReferenceCounter referenceCounter) { ContractMethodDescriptor descriptor = new() { - Name = json["name"].GetString(), - Parameters = ((JArray)json["parameters"]).Select(u => ContractParameterDefinition.FromJson((JObject)u)).ToArray(), - ReturnType = Enum.Parse(json["returntype"].GetString()), - Offset = json["offset"].GetInt32(), - Safe = json["safe"].GetBoolean() + Name = json["name"]!.GetString(), + Parameters = json["parameters"].NullExceptionOr().Select(u => ContractParameterDefinition.FromJson(u.NullExceptionOr())).ToArray(), + ReturnType = Enum.Parse(json["returntype"]!.GetString()), + Offset = json["offset"]!.GetInt32(), + Safe = json["safe"]!.GetBoolean() }; if (string.IsNullOrEmpty(descriptor.Name)) throw new FormatException(); _ = descriptor.Parameters.ToDictionary(p => p.Name); diff --git a/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs b/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs index 61906558d0..fd7292e345 100644 --- a/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs +++ b/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs @@ -24,7 +24,7 @@ public class ContractParameterDefinition : IInteroperable /// /// The name of the parameter. /// - public string Name { get; set; } + public string Name { get; set; } = null!; /// /// The type of the parameter. It can be any value of except . @@ -34,11 +34,11 @@ public class ContractParameterDefinition : IInteroperable void IInteroperable.FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; - Name = @struct[0].GetString(); + Name = @struct[0].GetString()!; Type = (ContractParameterType)(byte)@struct[1].GetInteger(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { Name, (byte)Type }; } @@ -52,8 +52,8 @@ public static ContractParameterDefinition FromJson(JObject json) { ContractParameterDefinition parameter = new() { - Name = json["name"].GetString(), - Type = Enum.Parse(json["type"].GetString()) + Name = json["name"]!.GetString(), + Type = Enum.Parse(json["type"]!.GetString()) }; if (string.IsNullOrEmpty(parameter.Name)) throw new FormatException(); diff --git a/src/Neo/SmartContract/Manifest/ContractPermission.cs b/src/Neo/SmartContract/Manifest/ContractPermission.cs index 44c67fd9a1..d9c9d910ed 100644 --- a/src/Neo/SmartContract/Manifest/ContractPermission.cs +++ b/src/Neo/SmartContract/Manifest/ContractPermission.cs @@ -34,14 +34,14 @@ public class ContractPermission : IInteroperable /// If it specifies a public key of a group, then any contract in this group /// may be invoked; If it specifies a wildcard *, then any contract may be invoked. /// - public ContractPermissionDescriptor Contract { get; set; } + public ContractPermissionDescriptor Contract { get; set; } = null!; /// /// Indicates which methods to be called. /// It can also be assigned with a wildcard *. If it is a wildcard *, /// then it means that any method can be called. /// - public WildcardContainer Methods { get; set; } + public WildcardContainer Methods { get; set; } = null!; /// /// A default permission that both and fields are set to wildcard *. @@ -63,16 +63,16 @@ void IInteroperable.FromStackItem(StackItem stackItem) Methods = @struct[1] switch { Null => WildcardContainer.CreateWildcard(), - Array array => WildcardContainer.Create(array.Select(p => p.GetString()).ToArray()), + Array array => WildcardContainer.Create(array.Select(p => p.GetString()!).ToArray()), _ => throw new ArgumentException(null, nameof(stackItem)) }; } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { - Contract.IsWildcard ? StackItem.Null : Contract.IsHash ? Contract.Hash.ToArray() : Contract.Group.ToArray(), + Contract.IsWildcard ? StackItem.Null : Contract.IsHash ? Contract.Hash!.ToArray() : Contract.Group!.ToArray(), Methods.IsWildcard ? StackItem.Null : new Array(referenceCounter, Methods.Select(p => (StackItem)p)), }; } @@ -86,10 +86,10 @@ public static ContractPermission FromJson(JObject json) { ContractPermission permission = new() { - Contract = ContractPermissionDescriptor.FromJson((JString)json["contract"]), - Methods = WildcardContainer.FromJson(json["methods"], u => u.GetString()), + Contract = ContractPermissionDescriptor.FromJson(json["contract"].NullExceptionOr()), + Methods = WildcardContainer.FromJson(json["methods"]!, u => u.GetString()), }; - if (permission.Methods.Any(p => string.IsNullOrEmpty(p))) + if (permission.Methods.Any(string.IsNullOrEmpty)) throw new FormatException(); _ = permission.Methods.ToDictionary(p => p); return permission; @@ -103,7 +103,7 @@ public JObject ToJson() { var json = new JObject(); json["contract"] = Contract.ToJson(); - json["methods"] = Methods.ToJson(p => p); + json["methods"] = Methods.ToJson(p => p!); return json; } @@ -117,7 +117,7 @@ public bool IsAllowed(ContractState targetContract, string targetMethod) { if (Contract.IsHash) { - if (!Contract.Hash.Equals(targetContract.Hash)) return false; + if (!Contract.Hash!.Equals(targetContract.Hash)) return false; } else if (Contract.IsGroup) { diff --git a/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs index ce85889423..60b642f07c 100644 --- a/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs @@ -25,12 +25,12 @@ public class ContractPermissionDescriptor : IEquatable /// The hash of the contract. It can't be set with . /// - public UInt160 Hash { get; } + public UInt160? Hash { get; } /// /// The group of the contracts. It can't be set with . /// - public ECPoint Group { get; } + public ECPoint? Group { get; } /// /// Indicates whether is set. @@ -47,7 +47,7 @@ public class ContractPermissionDescriptor : IEquatable public bool IsWildcard => Hash is null && Group is null; - private ContractPermissionDescriptor(UInt160 hash, ECPoint group) + private ContractPermissionDescriptor(UInt160? hash, ECPoint? group) { this.Hash = hash; this.Group = group; @@ -102,19 +102,19 @@ public static ContractPermissionDescriptor CreateWildcard() return new ContractPermissionDescriptor(null, null); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is not ContractPermissionDescriptor other) return false; return Equals(other); } - public bool Equals(ContractPermissionDescriptor other) + public bool Equals(ContractPermissionDescriptor? other) { if (other is null) return false; - if (this == other) return true; + if (this.Equals(other)) return true; if (IsWildcard == other.IsWildcard) return true; - if (IsHash) return Hash.Equals(other.Hash); - else return Group.Equals(other.Group); + if (IsHash) return Hash!.Equals(other.Hash); + return IsGroup && Group!.Equals(other.Group); } public override int GetHashCode() @@ -145,16 +145,16 @@ public static ContractPermissionDescriptor FromJson(JString json) /// The permission descriptor represented by a JSON object. public JString ToJson() { - if (IsHash) return Hash.ToString(); - if (IsGroup) return Group.ToString(); - return "*"; + if (IsHash) return Hash!.ToString()!; + if (IsGroup) return Group!.ToString()!; + return "*"!; } /// /// Converts the permission descriptor to byte array. /// /// The converted byte array. Or if it is a wildcard. - public byte[] ToArray() + public byte[]? ToArray() { return Hash?.ToArray() ?? Group?.EncodePoint(true); } diff --git a/src/Neo/SmartContract/Manifest/WildCardContainer.cs b/src/Neo/SmartContract/Manifest/WildCardContainer.cs index 3002042d04..56a4df55e8 100644 --- a/src/Neo/SmartContract/Manifest/WildCardContainer.cs +++ b/src/Neo/SmartContract/Manifest/WildCardContainer.cs @@ -23,9 +23,9 @@ namespace Neo.SmartContract.Manifest /// The type of the elements. public class WildcardContainer : IReadOnlyList { - private readonly T[] _data; + private readonly T[]? _data; - public T this[int index] => _data[index]; + public T this[int index] => _data![index]; public int Count => _data?.Length ?? 0; @@ -34,7 +34,7 @@ public class WildcardContainer : IReadOnlyList /// public bool IsWildcard => _data is null; - private WildcardContainer(T[] data) + private WildcardContainer(T[]? data) { _data = data; } @@ -66,7 +66,7 @@ public static WildcardContainer FromJson(JToken json, Func element if (str.Value != "*") throw new FormatException(); return CreateWildcard(); case JArray array: - return Create(array.Select(p => elementSelector(p)).ToArray()); + return Create(array.Select(p => elementSelector(p!)).ToArray()); default: throw new FormatException(); } @@ -87,8 +87,8 @@ public IEnumerator GetEnumerator() /// The list represented by a JSON object. public JToken ToJson(Func elementSelector) { - if (IsWildcard) return "*"; - return _data.Select(p => elementSelector(p)).ToArray(); + if (IsWildcard) return "*"!; + return _data!.Select(p => elementSelector(p)).ToArray(); } } } diff --git a/src/Neo/SmartContract/MethodToken.cs b/src/Neo/SmartContract/MethodToken.cs index 1b391edd32..3812c1c742 100644 --- a/src/Neo/SmartContract/MethodToken.cs +++ b/src/Neo/SmartContract/MethodToken.cs @@ -24,12 +24,12 @@ public class MethodToken : ISerializable /// /// The hash of the contract to be called. /// - public UInt160 Hash; + public UInt160 Hash = null!; /// /// The name of the method to be called. /// - public string Method; + public string Method = null!; /// /// The number of parameters of the method to be called. diff --git a/src/Neo/SmartContract/Native/AccountState.cs b/src/Neo/SmartContract/Native/AccountState.cs index 031b37f8eb..cc0d0b056a 100644 --- a/src/Neo/SmartContract/Native/AccountState.cs +++ b/src/Neo/SmartContract/Native/AccountState.cs @@ -30,7 +30,7 @@ public virtual void FromStackItem(StackItem stackItem) Balance = ((Struct)stackItem)[0].GetInteger(); } - public virtual StackItem ToStackItem(ReferenceCounter referenceCounter) + public virtual StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { Balance }; } diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 0f846a37cc..13030a8a8e 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -39,10 +39,10 @@ internal ContractManagement() { var events = new List(Manifest.Abi.Events) { - new ContractEventDescriptor + new() { Name = "Deploy", - Parameters = new ContractParameterDefinition[] + Parameters = new[] { new ContractParameterDefinition() { @@ -51,10 +51,10 @@ internal ContractManagement() } } }, - new ContractEventDescriptor + new() { Name = "Update", - Parameters = new ContractParameterDefinition[] + Parameters = new[] { new ContractParameterDefinition() { @@ -63,10 +63,10 @@ internal ContractManagement() } } }, - new ContractEventDescriptor + new() { Name = "Destroy", - Parameters = new ContractParameterDefinition[] + Parameters = new[] { new ContractParameterDefinition() { @@ -82,7 +82,7 @@ internal ContractManagement() private int GetNextAvailableId(DataCache snapshot) { - StorageItem item = snapshot.GetAndChange(CreateStorageKey(Prefix_NextAvailableId)); + StorageItem item = snapshot.GetAndChange(CreateStorageKey(Prefix_NextAvailableId))!; int value = (int)(BigInteger)item; item.Add(1); return value; @@ -97,7 +97,7 @@ internal override ContractTask Initialize(ApplicationEngine engine) private async ContractTask OnDeploy(ApplicationEngine engine, ContractState contract, StackItem data, bool update) { - ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2); + ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod("_deploy", 2); if (md is not null) await engine.CallFromNativeContract(Hash, contract.Hash, md.Name, data, update); engine.SendNotification(Hash, update ? "Update" : "Deploy", new VM.Types.Array(engine.ReferenceCounter) { contract.Hash.ToArray() }); @@ -107,7 +107,7 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) { foreach (NativeContract contract in Contracts) { - if (contract.IsInitializeBlock(engine.ProtocolSettings, engine.PersistingBlock.Index)) + if (contract.IsInitializeBlock(engine.ProtocolSettings!, engine.PersistingBlock!.Index)) { engine.Snapshot.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(new ContractState { @@ -125,7 +125,7 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private long GetMinimumDeploymentFee(DataCache snapshot) { - return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_MinimumDeploymentFee)]; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_MinimumDeploymentFee)]!; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -133,7 +133,7 @@ private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) { if (value < 0) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_MinimumDeploymentFee)).Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_MinimumDeploymentFee))!.Set(value); } /// @@ -143,7 +143,7 @@ private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) /// The hash of the deployed contract. /// The deployed contract. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - public ContractState GetContract(DataCache snapshot, UInt160 hash) + public ContractState? GetContract(DataCache snapshot, UInt160 hash) { return snapshot.TryGet(CreateStorageKey(Prefix_Contract).Add(hash))?.GetInteroperable(); } @@ -155,9 +155,9 @@ public ContractState GetContract(DataCache snapshot, UInt160 hash) /// Contract ID. /// The deployed contract. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - public ContractState GetContractById(DataCache snapshot, int id) + public ContractState? GetContractById(DataCache snapshot, int id) { - StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_ContractHash).AddBigEndian(id)); + StorageItem? item = snapshot.TryGet(CreateStorageKey(Prefix_ContractHash).AddBigEndian(id)); if (item is null) return null; var hash = new UInt160(item.Value.Span); return GetContract(snapshot, hash); @@ -273,7 +273,7 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); - var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable(); + var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash!))?.GetInteroperable(); if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}"); if (contract.UpdateCounter == ushort.MaxValue) throw new InvalidOperationException($"The contract reached the maximum number of updates."); @@ -304,9 +304,9 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private void Destroy(ApplicationEngine engine) { - UInt160 hash = engine.CallingScriptHash; + UInt160 hash = engine.CallingScriptHash!; StorageKey ckey = CreateStorageKey(Prefix_Contract).Add(hash); - ContractState contract = engine.Snapshot.TryGet(ckey)?.GetInteroperable(); + ContractState? contract = engine.Snapshot.TryGet(ckey)?.GetInteroperable(); if (contract is null) return; engine.Snapshot.Delete(ckey); engine.Snapshot.Delete(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id)); diff --git a/src/Neo/SmartContract/Native/ContractMethodAttribute.cs b/src/Neo/SmartContract/Native/ContractMethodAttribute.cs index 55940f2eb3..ce0e545f0a 100644 --- a/src/Neo/SmartContract/Native/ContractMethodAttribute.cs +++ b/src/Neo/SmartContract/Native/ContractMethodAttribute.cs @@ -16,7 +16,7 @@ namespace Neo.SmartContract.Native [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false)] internal class ContractMethodAttribute : Attribute { - public string Name { get; init; } + public string? Name { get; init; } public CallFlags RequiredCallFlags { get; init; } public long CpuFee { get; init; } public long StorageFee { get; init; } diff --git a/src/Neo/SmartContract/Native/ContractMethodMetadata.cs b/src/Neo/SmartContract/Native/ContractMethodMetadata.cs index 83c24191fd..8e90d6e401 100644 --- a/src/Neo/SmartContract/Native/ContractMethodMetadata.cs +++ b/src/Neo/SmartContract/Native/ContractMethodMetadata.cs @@ -42,7 +42,7 @@ public ContractMethodMetadata(MemberInfo member, ContractMethodAttribute attribu MethodInfo m => m, PropertyInfo p => p.GetMethod, _ => throw new ArgumentException(null, nameof(member)) - }; + } ?? throw new NullReferenceException("Method not found"); ParameterInfo[] parameterInfos = this.Handler.GetParameters(); if (parameterInfos.Length > 0) { diff --git a/src/Neo/SmartContract/Native/FungibleToken.cs b/src/Neo/SmartContract/Native/FungibleToken.cs index 1a3a2ac532..bcec1f98c1 100644 --- a/src/Neo/SmartContract/Native/FungibleToken.cs +++ b/src/Neo/SmartContract/Native/FungibleToken.cs @@ -96,11 +96,11 @@ internal async ContractTask Mint(ApplicationEngine engine, UInt160 account, BigI { if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); if (amount.IsZero) return; - StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account), () => new StorageItem(new TState())); + StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account), () => new StorageItem(new TState())).NullExceptionOr(); TState state = storage.GetInteroperable(); OnBalanceChanging(engine, account, state, amount); state.Balance += amount; - storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)); + storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)).NullExceptionOr(); storage.Add(amount); await PostTransfer(engine, null, account, amount, StackItem.Null, callOnPayment); } @@ -110,7 +110,7 @@ internal async ContractTask Burn(ApplicationEngine engine, UInt160 account, BigI if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); if (amount.IsZero) return; StorageKey key = CreateStorageKey(Prefix_Account).Add(account); - StorageItem storage = engine.Snapshot.GetAndChange(key); + StorageItem storage = engine.Snapshot.GetAndChange(key).NullExceptionOr(); TState state = storage.GetInteroperable(); if (state.Balance < amount) throw new InvalidOperationException(); OnBalanceChanging(engine, account, state, -amount); @@ -118,7 +118,7 @@ internal async ContractTask Burn(ApplicationEngine engine, UInt160 account, BigI engine.Snapshot.Delete(key); else state.Balance -= amount; - storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply)); + storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply)).NullExceptionOr(); storage.Add(-amount); await PostTransfer(engine, account, null, amount, StackItem.Null, false); } @@ -131,7 +131,7 @@ internal async ContractTask Burn(ApplicationEngine engine, UInt160 account, BigI [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public virtual BigInteger TotalSupply(DataCache snapshot) { - StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_TotalSupply)); + StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_TotalSupply)); if (storage is null) return BigInteger.Zero; return storage; } @@ -145,7 +145,7 @@ public virtual BigInteger TotalSupply(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public virtual BigInteger BalanceOf(DataCache snapshot, UInt160 account) { - StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); + StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); if (storage is null) return BigInteger.Zero; return storage.GetInteroperable().Balance; } @@ -159,7 +159,7 @@ private protected async ContractTask Transfer(ApplicationEngine engine, UI if (!from.Equals(engine.CallingScriptHash) && !engine.CheckWitnessInternal(from)) return false; StorageKey key_from = CreateStorageKey(Prefix_Account).Add(from); - StorageItem storage_from = engine.Snapshot.GetAndChange(key_from); + StorageItem? storage_from = engine.Snapshot.GetAndChange(key_from); if (amount.IsZero) { if (storage_from != null) @@ -185,7 +185,7 @@ private protected async ContractTask Transfer(ApplicationEngine engine, UI else state_from.Balance -= amount; StorageKey key_to = CreateStorageKey(Prefix_Account).Add(to); - StorageItem storage_to = engine.Snapshot.GetAndChange(key_to, () => new StorageItem(new TState())); + StorageItem storage_to = engine.Snapshot.GetAndChange(key_to, () => new StorageItem(new TState())).NullExceptionOr(); TState state_to = storage_to.GetInteroperable(); OnBalanceChanging(engine, to, state_to, amount); state_to.Balance += amount; @@ -199,7 +199,7 @@ internal virtual void OnBalanceChanging(ApplicationEngine engine, UInt160 accoun { } - private protected virtual async ContractTask PostTransfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount, StackItem data, bool callOnPayment) + private protected virtual async ContractTask PostTransfer(ApplicationEngine engine, UInt160? from, UInt160? to, BigInteger amount, StackItem data, bool callOnPayment) { // Send notification diff --git a/src/Neo/SmartContract/Native/GasToken.cs b/src/Neo/SmartContract/Native/GasToken.cs index 0c5a721edc..df991342ef 100644 --- a/src/Neo/SmartContract/Native/GasToken.cs +++ b/src/Neo/SmartContract/Native/GasToken.cs @@ -28,19 +28,20 @@ internal GasToken() internal override ContractTask Initialize(ApplicationEngine engine) { - UInt160 account = Contract.GetBFTAddress(engine.ProtocolSettings.StandbyValidators); - return Mint(engine, account, engine.ProtocolSettings.InitialGasDistribution, false); + UInt160 account = Contract.GetBFTAddress(engine.ProtocolSettings!.StandbyValidators); + return Mint(engine, account, engine.ProtocolSettings!.InitialGasDistribution, false); } internal override async ContractTask OnPersist(ApplicationEngine engine) { long totalNetworkFee = 0; - foreach (Transaction tx in engine.PersistingBlock.Transactions) + foreach (Transaction? tx in engine.PersistingBlock!.Transactions) { + if (tx == null) continue; await Burn(engine, tx.Sender, tx.SystemFee + tx.NetworkFee); totalNetworkFee += tx.NetworkFee; } - ECPoint[] validators = NEO.GetNextBlockValidators(engine.Snapshot, engine.ProtocolSettings.ValidatorsCount); + ECPoint[] validators = NEO.GetNextBlockValidators(engine.Snapshot, engine.ProtocolSettings!.ValidatorsCount); UInt160 primary = Contract.CreateSignatureRedeemScript(validators[engine.PersistingBlock.PrimaryIndex]).ToScriptHash(); await Mint(engine, primary, totalNetworkFee, false); } diff --git a/src/Neo/SmartContract/Native/HashIndexState.cs b/src/Neo/SmartContract/Native/HashIndexState.cs index 229458ffdd..0302117cf1 100644 --- a/src/Neo/SmartContract/Native/HashIndexState.cs +++ b/src/Neo/SmartContract/Native/HashIndexState.cs @@ -17,7 +17,7 @@ namespace Neo.SmartContract.Native { class HashIndexState : IInteroperable { - public UInt256 Hash; + public UInt256 Hash = null!; public uint Index; void IInteroperable.FromStackItem(StackItem stackItem) @@ -27,7 +27,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) Index = (uint)@struct[1].GetInteger(); } - StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { Hash.ToArray(), Index }; } diff --git a/src/Neo/SmartContract/Native/InteroperableList.cs b/src/Neo/SmartContract/Native/InteroperableList.cs index e118db7621..178c6be236 100644 --- a/src/Neo/SmartContract/Native/InteroperableList.cs +++ b/src/Neo/SmartContract/Native/InteroperableList.cs @@ -19,7 +19,7 @@ namespace Neo.SmartContract.Native { abstract class InteroperableList : IList, IInteroperable { - private List list; + private List? list; private List List => list ??= new(); public T this[int index] { get => List[index]; set => List[index] = value; } @@ -40,7 +40,7 @@ abstract class InteroperableList : IList, IInteroperable public void Sort() => List.Sort(); protected abstract T ElementFromStackItem(StackItem item); - protected abstract StackItem ElementToStackItem(T element, ReferenceCounter referenceCounter); + protected abstract StackItem ElementToStackItem(T element, ReferenceCounter? referenceCounter); public void FromStackItem(StackItem stackItem) { @@ -51,7 +51,7 @@ public void FromStackItem(StackItem stackItem) } } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Array(referenceCounter, this.Select(p => ElementToStackItem(p, referenceCounter))); } diff --git a/src/Neo/SmartContract/Native/LedgerContract.cs b/src/Neo/SmartContract/Native/LedgerContract.cs index 3bb7568adf..d7c6578fa9 100644 --- a/src/Neo/SmartContract/Native/LedgerContract.cs +++ b/src/Neo/SmartContract/Native/LedgerContract.cs @@ -38,6 +38,8 @@ internal LedgerContract() internal override ContractTask OnPersist(ApplicationEngine engine) { + if (engine.PersistingBlock == null) throw new NullReferenceException("engine.PersistingBlock"); + TransactionState[] transactions = engine.PersistingBlock.Transactions.Select(p => new TransactionState { BlockIndex = engine.PersistingBlock.Index, @@ -50,16 +52,16 @@ internal override ContractTask OnPersist(ApplicationEngine engine) { // It's possible that there are previously saved malicious conflict records for this transaction. // If so, then remove it and store the relevant transaction itself. - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(tx.Transaction.Hash), () => new StorageItem(new TransactionState())).FromReplica(new StorageItem(tx)); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(tx.Transaction!.Hash), () => new StorageItem(new TransactionState()))?.FromReplica(new StorageItem(tx)); // Store transaction's conflicits. - var conflictingSigners = tx.Transaction.Signers.Select(s => s.Account); + var conflictingSigners = tx.Transaction.Signers.Select(s => s.Account).ToArray(); foreach (var attr in tx.Transaction.GetAttributes()) { - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash), () => new StorageItem(new TransactionState())).FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash), () => new StorageItem(new TransactionState()))?.FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); foreach (var signer in conflictingSigners) { - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash).Add(signer), () => new StorageItem(new TransactionState())).FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash).Add(signer), () => new StorageItem(new TransactionState()))?.FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); } } } @@ -69,9 +71,13 @@ internal override ContractTask OnPersist(ApplicationEngine engine) internal override ContractTask PostPersist(ApplicationEngine engine) { - HashIndexState state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_CurrentBlock), () => new StorageItem(new HashIndexState())).GetInteroperable(); - state.Hash = engine.PersistingBlock.Hash; - state.Index = engine.PersistingBlock.Index; + HashIndexState state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_CurrentBlock), () => new StorageItem(new HashIndexState()))?.GetInteroperable()!; + if (engine.PersistingBlock != null) + { + state.Hash = engine.PersistingBlock.Hash; + state.Index = engine.PersistingBlock.Index; + } + return ContractTask.CompletedTask; } @@ -93,9 +99,9 @@ private bool IsTraceableBlock(DataCache snapshot, uint index, uint maxTraceableB /// The snapshot used to read data. /// The index of the block. /// The hash of the block. - public UInt256 GetBlockHash(DataCache snapshot, uint index) + public UInt256? GetBlockHash(DataCache snapshot, uint index) { - StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_BlockHash).AddBigEndian(index)); + StorageItem? item = snapshot.TryGet(CreateStorageKey(Prefix_BlockHash).AddBigEndian(index)); if (item is null) return null; return new UInt256(item.Value.Span); } @@ -108,7 +114,7 @@ public UInt256 GetBlockHash(DataCache snapshot, uint index) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public UInt256 CurrentHash(DataCache snapshot) { - return snapshot[CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable().Hash; + return snapshot[CreateStorageKey(Prefix_CurrentBlock)]!.GetInteroperable().Hash; } /// @@ -119,7 +125,7 @@ public UInt256 CurrentHash(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public uint CurrentIndex(DataCache snapshot) { - return snapshot[CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable().Index; + return snapshot[CreateStorageKey(Prefix_CurrentBlock)]!.GetInteroperable().Index; } /// @@ -178,17 +184,17 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerableThe snapshot used to read data. /// The hash of the block. /// The trimmed block. - public TrimmedBlock GetTrimmedBlock(DataCache snapshot, UInt256 hash) + public TrimmedBlock? GetTrimmedBlock(DataCache snapshot, UInt256 hash) { - StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_Block).Add(hash)); + StorageItem? item = snapshot.TryGet(CreateStorageKey(Prefix_Block).Add(hash)); if (item is null) return null; return item.Value.AsSerializable(); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - private TrimmedBlock GetBlock(ApplicationEngine engine, byte[] indexOrHash) + private TrimmedBlock? GetBlock(ApplicationEngine engine, byte[] indexOrHash) { - UInt256 hash; + UInt256? hash; if (indexOrHash.Length < UInt256.Length) hash = GetBlockHash(engine.Snapshot, (uint)new BigInteger(indexOrHash)); else if (indexOrHash.Length == UInt256.Length) @@ -196,8 +202,8 @@ private TrimmedBlock GetBlock(ApplicationEngine engine, byte[] indexOrHash) else throw new ArgumentException(null, nameof(indexOrHash)); if (hash is null) return null; - TrimmedBlock block = GetTrimmedBlock(engine.Snapshot, hash); - if (block is null || !IsTraceableBlock(engine.Snapshot, block.Index, engine.ProtocolSettings.MaxTraceableBlocks)) return null; + TrimmedBlock? block = GetTrimmedBlock(engine.Snapshot, hash); + if (block is null || !IsTraceableBlock(engine.Snapshot, block.Index, engine.ProtocolSettings!.MaxTraceableBlocks)) return null; return block; } @@ -207,14 +213,14 @@ private TrimmedBlock GetBlock(ApplicationEngine engine, byte[] indexOrHash) /// The snapshot used to read data. /// The hash of the block. /// The block with the specified hash. - public Block GetBlock(DataCache snapshot, UInt256 hash) + public Block? GetBlock(DataCache snapshot, UInt256 hash) { - TrimmedBlock state = GetTrimmedBlock(snapshot, hash); + TrimmedBlock? state = GetTrimmedBlock(snapshot, hash); if (state is null) return null; return new Block { Header = state.Header, - Transactions = state.Hashes.Select(p => GetTransaction(snapshot, p)).ToArray() + Transactions = state.Hashes.Select(p => GetTransaction(snapshot, p)!).ToArray() }; } @@ -224,9 +230,9 @@ public Block GetBlock(DataCache snapshot, UInt256 hash) /// The snapshot used to read data. /// The index of the block. /// The block with the specified index. - public Block GetBlock(DataCache snapshot, uint index) + public Block? GetBlock(DataCache snapshot, uint index) { - UInt256 hash = GetBlockHash(snapshot, index); + UInt256? hash = GetBlockHash(snapshot, index); if (hash is null) return null; return GetBlock(snapshot, hash); } @@ -237,7 +243,7 @@ public Block GetBlock(DataCache snapshot, uint index) /// The snapshot used to read data. /// The hash of the block. /// The block header with the specified hash. - public Header GetHeader(DataCache snapshot, UInt256 hash) + public Header? GetHeader(DataCache snapshot, UInt256 hash) { return GetTrimmedBlock(snapshot, hash)?.Header; } @@ -248,9 +254,9 @@ public Header GetHeader(DataCache snapshot, UInt256 hash) /// The snapshot used to read data. /// The index of the block. /// The block header with the specified index. - public Header GetHeader(DataCache snapshot, uint index) + public Header? GetHeader(DataCache snapshot, uint index) { - UInt256 hash = GetBlockHash(snapshot, index); + UInt256? hash = GetBlockHash(snapshot, index); if (hash is null) return null; return GetHeader(snapshot, hash); } @@ -261,7 +267,7 @@ public Header GetHeader(DataCache snapshot, uint index) /// The snapshot used to read data. /// The hash of the transaction. /// The with the specified hash. - public TransactionState GetTransactionState(DataCache snapshot, UInt256 hash) + public TransactionState? GetTransactionState(DataCache snapshot, UInt256 hash) { var state = snapshot.TryGet(CreateStorageKey(Prefix_Transaction).Add(hash))?.GetInteroperable(); if (state?.Transaction is null) return null; @@ -274,47 +280,47 @@ public TransactionState GetTransactionState(DataCache snapshot, UInt256 hash) /// The snapshot used to read data. /// The hash of the transaction. /// The transaction with the specified hash. - public Transaction GetTransaction(DataCache snapshot, UInt256 hash) + public Transaction? GetTransaction(DataCache snapshot, UInt256 hash) { return GetTransactionState(snapshot, hash)?.Transaction; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates, Name = "getTransaction")] - private Transaction GetTransactionForContract(ApplicationEngine engine, UInt256 hash) + private Transaction? GetTransactionForContract(ApplicationEngine engine, UInt256 hash) { - TransactionState state = GetTransactionState(engine.Snapshot, hash); - if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return null; + TransactionState? state = GetTransactionState(engine.Snapshot, hash); + if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings!.MaxTraceableBlocks)) return null; return state.Transaction; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - private Signer[] GetTransactionSigners(ApplicationEngine engine, UInt256 hash) + private Signer[]? GetTransactionSigners(ApplicationEngine engine, UInt256 hash) { - TransactionState state = GetTransactionState(engine.Snapshot, hash); - if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return null; - return state.Transaction.Signers; + TransactionState? state = GetTransactionState(engine.Snapshot, hash); + if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings!.MaxTraceableBlocks)) return null; + return state.Transaction?.Signers; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private VMState GetTransactionVMState(ApplicationEngine engine, UInt256 hash) { - TransactionState state = GetTransactionState(engine.Snapshot, hash); - if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return VMState.NONE; + TransactionState? state = GetTransactionState(engine.Snapshot, hash); + if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings!.MaxTraceableBlocks)) return VMState.NONE; return state.State; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private int GetTransactionHeight(ApplicationEngine engine, UInt256 hash) { - TransactionState state = GetTransactionState(engine.Snapshot, hash); - if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return -1; + TransactionState? state = GetTransactionState(engine.Snapshot, hash); + if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings!.MaxTraceableBlocks)) return -1; return (int)state.BlockIndex; } [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.ReadStates)] - private Transaction GetTransactionFromBlock(ApplicationEngine engine, byte[] blockIndexOrHash, int txIndex) + private Transaction? GetTransactionFromBlock(ApplicationEngine engine, byte[] blockIndexOrHash, int txIndex) { - UInt256 hash; + UInt256? hash; if (blockIndexOrHash.Length < UInt256.Length) hash = GetBlockHash(engine.Snapshot, (uint)new BigInteger(blockIndexOrHash)); else if (blockIndexOrHash.Length == UInt256.Length) @@ -322,8 +328,8 @@ private Transaction GetTransactionFromBlock(ApplicationEngine engine, byte[] blo else throw new ArgumentException(null, nameof(blockIndexOrHash)); if (hash is null) return null; - TrimmedBlock block = GetTrimmedBlock(engine.Snapshot, hash); - if (block is null || !IsTraceableBlock(engine.Snapshot, block.Index, engine.ProtocolSettings.MaxTraceableBlocks)) return null; + TrimmedBlock? block = GetTrimmedBlock(engine.Snapshot, hash); + if (block is null || !IsTraceableBlock(engine.Snapshot, block.Index, engine.ProtocolSettings!.MaxTraceableBlocks)) return null; if (txIndex < 0 || txIndex >= block.Hashes.Length) throw new ArgumentOutOfRangeException(nameof(txIndex)); return GetTransaction(engine.Snapshot, block.Hashes[txIndex]); diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index 0229582310..a3d6193f21 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -121,7 +121,7 @@ protected NativeContract() List descriptors = new(); foreach (MemberInfo member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { - ContractMethodAttribute attribute = member.GetCustomAttribute(); + ContractMethodAttribute? attribute = member.GetCustomAttribute(); if (attribute is null) continue; descriptors.Add(new ContractMethodMetadata(member, attribute)); } @@ -223,7 +223,7 @@ private protected KeyBuilder CreateStorageKey(byte prefix) /// /// The hash of the native contract. /// The native contract with the specified hash. - public static NativeContract GetContract(UInt160 hash) + public static NativeContract? GetContract(UInt160 hash) { contractsDictionary.TryGetValue(hash, out var contract); return contract; @@ -235,7 +235,7 @@ internal async void Invoke(ApplicationEngine engine, byte version) { if (version != 0) throw new InvalidOperationException($"The native contract of version {version} is not active."); - ExecutionContext context = engine.CurrentContext; + ExecutionContext context = engine.CurrentContext ?? throw new InvalidOperationException("No context available."); ContractMethodMetadata method = methods[context.InstructionPointer]; ExecutionContextState state = context.GetState(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) @@ -246,7 +246,7 @@ internal async void Invoke(ApplicationEngine engine, byte version) if (method.NeedSnapshot) parameters.Add(engine.Snapshot); for (int i = 0; i < method.Parameters.Length; i++) parameters.Add(engine.Convert(context.EvaluationStack.Peek(i), method.Parameters[i])); - object returnValue = method.Handler.Invoke(this, parameters.ToArray()); + object? returnValue = method.Handler.Invoke(this, parameters.ToArray()); if (returnValue is ContractTask task) { await task; @@ -256,7 +256,7 @@ internal async void Invoke(ApplicationEngine engine, byte version) { context.EvaluationStack.Pop(); } - if (method.Handler.ReturnType != typeof(void) && method.Handler.ReturnType != typeof(ContractTask)) + if (returnValue != null && method.Handler.ReturnType != typeof(void) && method.Handler.ReturnType != typeof(ContractTask)) { context.EvaluationStack.Push(engine.Convert(returnValue)); } diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 2fd26d04a7..8917e9dde9 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -61,10 +61,10 @@ internal NeoToken() var events = new List(Manifest.Abi.Events) { - new ContractEventDescriptor + new() { Name = "CandidateStateChanged", - Parameters = new ContractParameterDefinition[] + Parameters = new[] { new ContractParameterDefinition() { @@ -83,10 +83,10 @@ internal NeoToken() } } }, - new ContractEventDescriptor + new() { Name = "Vote", - Parameters = new ContractParameterDefinition[] + Parameters = new[] { new ContractParameterDefinition() { @@ -122,30 +122,33 @@ public override BigInteger TotalSupply(DataCache snapshot) internal override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { - GasDistribution distribution = DistributeGas(engine, account, state); + GasDistribution? distribution = DistributeGas(engine, account, state); if (distribution is not null) { - var list = engine.CurrentContext.GetState>(); - list.Add(distribution); + var list = engine.CurrentContext?.GetState>(); + list?.Add(distribution); } if (amount.IsZero) return; if (state.VoteTo is null) return; - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)).Add(amount); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount))?.Add(amount); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state.VoteTo); - CandidateState candidate = engine.Snapshot.GetAndChange(key).GetInteroperable(); - candidate.Votes += amount; - CheckCandidate(engine.Snapshot, state.VoteTo, candidate); + CandidateState? candidate = engine.Snapshot.GetAndChange(key)?.GetInteroperable(); + if (candidate != null) + { + candidate.Votes += amount; + CheckCandidate(engine.Snapshot, state.VoteTo, candidate); + } } - private protected override async ContractTask PostTransfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount, StackItem data, bool callOnPayment) + private protected override async ContractTask PostTransfer(ApplicationEngine engine, UInt160? from, UInt160? to, BigInteger amount, StackItem data, bool callOnPayment) { await base.PostTransfer(engine, from, to, amount, data, callOnPayment); - var list = engine.CurrentContext.GetState>(); - foreach (var distribution in list) + var list = engine.CurrentContext?.GetState>(); + foreach (var distribution in list ?? Enumerable.Empty()) await GAS.Mint(engine, distribution.Account, distribution.Amount, callOnPayment); } - private GasDistribution DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state) + private GasDistribution? DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state) { // PersistingBlock is null when running under the debugger if (engine.PersistingBlock is null) return null; @@ -222,23 +225,23 @@ private void CheckCandidate(DataCache snapshot, ECPoint pubkey, CandidateState c internal override ContractTask Initialize(ApplicationEngine engine) { - var cachedCommittee = new CachedCommittee(engine.ProtocolSettings.StandbyCommittee.Select(p => (p, BigInteger.Zero))); + var cachedCommittee = new CachedCommittee(engine.ProtocolSettings!.StandbyCommittee.Select(p => (p, BigInteger.Zero))); engine.Snapshot.Add(CreateStorageKey(Prefix_Committee), new StorageItem(cachedCommittee)); engine.Snapshot.Add(CreateStorageKey(Prefix_VotersCount), new StorageItem(System.Array.Empty())); engine.Snapshot.Add(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(0u), new StorageItem(5 * GAS.Factor)); engine.Snapshot.Add(CreateStorageKey(Prefix_RegisterPrice), new StorageItem(1000 * GAS.Factor)); - return Mint(engine, Contract.GetBFTAddress(engine.ProtocolSettings.StandbyValidators), TotalAmount, false); + return Mint(engine, Contract.GetBFTAddress(engine.ProtocolSettings!.StandbyValidators), TotalAmount, false); } internal override ContractTask OnPersist(ApplicationEngine engine) { // Set next committee - if (ShouldRefreshCommittee(engine.PersistingBlock.Index, engine.ProtocolSettings.CommitteeMembersCount)) + if (engine.PersistingBlock != null && ShouldRefreshCommittee(engine.PersistingBlock.Index, engine.ProtocolSettings!.CommitteeMembersCount)) { - StorageItem storageItem = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Committee)); - var cachedCommittee = storageItem.GetInteroperable(); - cachedCommittee.Clear(); - cachedCommittee.AddRange(ComputeCommitteeMembers(engine.Snapshot, engine.ProtocolSettings)); + StorageItem? storageItem = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Committee)); + var cachedCommittee = storageItem?.GetInteroperable(); + cachedCommittee?.Clear(); + cachedCommittee?.AddRange(ComputeCommitteeMembers(engine.Snapshot, engine.ProtocolSettings)); } return ContractTask.CompletedTask; } @@ -247,9 +250,9 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) { // Distribute GAS for committee - int m = engine.ProtocolSettings.CommitteeMembersCount; - int n = engine.ProtocolSettings.ValidatorsCount; - int index = (int)(engine.PersistingBlock.Index % (uint)m); + int m = engine.ProtocolSettings!.CommitteeMembersCount; + int n = engine.ProtocolSettings!.ValidatorsCount; + int index = (int)(engine.PersistingBlock!.Index % (uint)m); var gasPerBlock = GetGasPerBlock(engine.Snapshot); var committee = GetCommitteeFromCache(engine.Snapshot); var pubkey = committee[index].PublicKey; @@ -269,8 +272,8 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) { BigInteger voterSumRewardPerNEO = factor * voterRewardOfEachCommittee / Votes; StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(PublicKey); - StorageItem lastRewardPerNeo = engine.Snapshot.GetAndChange(voterRewardKey, () => new StorageItem(BigInteger.Zero)); - lastRewardPerNeo.Add(voterSumRewardPerNEO); + StorageItem? lastRewardPerNeo = engine.Snapshot.GetAndChange(voterRewardKey, () => new StorageItem(BigInteger.Zero)); + lastRewardPerNeo?.Add(voterSumRewardPerNEO); } } } @@ -283,9 +286,9 @@ private void SetGasPerBlock(ApplicationEngine engine, BigInteger gasPerBlock) throw new ArgumentOutOfRangeException(nameof(gasPerBlock)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - uint index = engine.PersistingBlock.Index + 1; - StorageItem entry = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(index), () => new StorageItem(gasPerBlock)); - entry.Set(gasPerBlock); + uint index = engine.PersistingBlock!.Index + 1; + StorageItem? entry = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(index), () => new StorageItem(gasPerBlock)); + entry?.Set(gasPerBlock); } /// @@ -305,7 +308,7 @@ private void SetRegisterPrice(ApplicationEngine engine, long registerPrice) if (registerPrice <= 0) throw new ArgumentOutOfRangeException(nameof(registerPrice)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RegisterPrice)).Set(registerPrice); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RegisterPrice))?.Set(registerPrice); } /// @@ -316,7 +319,7 @@ private void SetRegisterPrice(ApplicationEngine engine, long registerPrice) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public long GetRegisterPrice(DataCache snapshot) { - return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_RegisterPrice)]; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_RegisterPrice)]!; } private IEnumerable<(uint Index, BigInteger GasPerBlock)> GetSortedGasRecords(DataCache snapshot, uint end) @@ -337,7 +340,7 @@ public long GetRegisterPrice(DataCache snapshot) [ContractMethod(CpuFee = 1 << 17, RequiredCallFlags = CallFlags.ReadStates)] public BigInteger UnclaimedGas(DataCache snapshot, UInt160 account, uint end) { - StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); + StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); if (storage is null) return BigInteger.Zero; NeoAccountState state = storage.GetInteroperable(); return CalculateBonus(snapshot, state, end); @@ -350,7 +353,7 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) return false; engine.AddGas(GetRegisterPrice(engine.Snapshot)); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); - StorageItem item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState())); + StorageItem item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState()))!; CandidateState state = item.GetInteroperable(); if (state.Registered) return true; state.Registered = true; @@ -366,7 +369,7 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) return false; StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); if (engine.Snapshot.TryGet(key) is null) return true; - StorageItem item = engine.Snapshot.GetAndChange(key); + StorageItem item = engine.Snapshot.GetAndChange(key)!; CandidateState state = item.GetInteroperable(); if (!state.Registered) return true; state.Registered = false; @@ -377,13 +380,13 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) } [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] - private async ContractTask Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) + private async ContractTask Vote(ApplicationEngine engine, UInt160 account, ECPoint? voteTo) { if (!engine.CheckWitnessInternal(account)) return false; - NeoAccountState state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); + NeoAccountState? state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); if (state_account is null) return false; if (state_account.Balance == 0) return false; - CandidateState validator_new = null; + CandidateState? validator_new = null; if (voteTo != null) { validator_new = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(voteTo))?.GetInteroperable(); @@ -392,28 +395,28 @@ private async ContractTask Vote(ApplicationEngine engine, UInt160 account, } if (state_account.VoteTo is null ^ voteTo is null) { - StorageItem item = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)); + StorageItem item = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount))!; if (state_account.VoteTo is null) item.Add(state_account.Balance); else item.Add(-state_account.Balance); } - GasDistribution gasDistribution = DistributeGas(engine, account, state_account); + GasDistribution? gasDistribution = DistributeGas(engine, account, state_account); if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state_account.VoteTo); - StorageItem storage_validator = engine.Snapshot.GetAndChange(key); + StorageItem storage_validator = engine.Snapshot.GetAndChange(key)!; CandidateState state_validator = storage_validator.GetInteroperable(); state_validator.Votes -= state_account.Balance; CheckCandidate(engine.Snapshot, state_account.VoteTo, state_validator); } - if (voteTo != null && voteTo != state_account.VoteTo) + if (voteTo != null && voteTo.Equals(state_account.VoteTo)) { StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(voteTo); var latestGasPerVote = engine.Snapshot.TryGet(voterRewardKey) ?? BigInteger.Zero; state_account.LastGasPerVote = latestGasPerVote; } - ECPoint from = state_account.VoteTo; + ECPoint? from = state_account.VoteTo; state_account.VoteTo = voteTo; if (validator_new != null) @@ -474,8 +477,8 @@ private IIterator GetAllCandidates(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public BigInteger GetCandidateVote(DataCache snapshot, ECPoint pubKey) { - StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubKey)); - CandidateState state = storage?.GetInteroperable(); + StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubKey)); + CandidateState? state = storage?.GetInteroperable(); return state?.Registered == true ? state.Votes : -1; } @@ -497,7 +500,7 @@ public ECPoint[] GetCommittee(DataCache snapshot) /// account /// The state of the account. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - public NeoAccountState GetAccountState(DataCache snapshot, UInt160 account) + public NeoAccountState? GetAccountState(DataCache snapshot, UInt160 account) { return snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); } @@ -515,7 +518,7 @@ public UInt160 GetCommitteeAddress(DataCache snapshot) private CachedCommittee GetCommitteeFromCache(DataCache snapshot) { - return snapshot[CreateStorageKey(Prefix_Committee)].GetInteroperable(); + return snapshot[CreateStorageKey(Prefix_Committee)]!.GetInteroperable(); } /// @@ -531,7 +534,7 @@ public ECPoint[] ComputeNextBlockValidators(DataCache snapshot, ProtocolSettings private IEnumerable<(ECPoint PublicKey, BigInteger Votes)> ComputeCommitteeMembers(DataCache snapshot, ProtocolSettings settings) { - decimal votersCount = (decimal)(BigInteger)snapshot[CreateStorageKey(Prefix_VotersCount)]; + decimal votersCount = (decimal)(BigInteger)snapshot[CreateStorageKey(Prefix_VotersCount)].NullExceptionOr(); decimal voterTurnout = votersCount / (decimal)TotalAmount; var candidates = GetCandidatesInternal(snapshot) .Select(p => (p.PublicKey, p.State.Votes)) @@ -547,7 +550,7 @@ public ECPoint[] ComputeNextBlockValidators(DataCache snapshot, ProtocolSettings [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.ReadStates)] private ECPoint[] GetNextBlockValidators(ApplicationEngine engine) { - return GetNextBlockValidators(engine.Snapshot, engine.ProtocolSettings.ValidatorsCount); + return GetNextBlockValidators(engine.Snapshot, engine.ProtocolSettings!.ValidatorsCount); } /// @@ -578,7 +581,7 @@ public class NeoAccountState : AccountState /// /// The voting target of the account. This field can be . /// - public ECPoint VoteTo; + public ECPoint? VoteTo; public BigInteger LastGasPerVote; @@ -591,7 +594,7 @@ public override void FromStackItem(StackItem stackItem) LastGasPerVote = @struct[3].GetInteger(); } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { Struct @struct = (Struct)base.ToStackItem(referenceCounter); @struct.Add(BalanceHeight); @@ -613,7 +616,7 @@ public void FromStackItem(StackItem stackItem) Votes = @struct[1].GetInteger(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { Registered, Votes }; } @@ -630,7 +633,7 @@ protected override (ECPoint, BigInteger) ElementFromStackItem(StackItem item) return (ECPoint.DecodePoint(@struct[0].GetSpan(), ECCurve.Secp256r1), @struct[1].GetInteger()); } - protected override StackItem ElementToStackItem((ECPoint PublicKey, BigInteger Votes) element, ReferenceCounter referenceCounter) + protected override StackItem ElementToStackItem((ECPoint PublicKey, BigInteger Votes) element, ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { element.PublicKey.ToArray(), element.Votes }; } @@ -638,7 +641,7 @@ protected override StackItem ElementToStackItem((ECPoint PublicKey, BigInteger V private record GasDistribution { - public UInt160 Account { get; init; } + public UInt160 Account { get; init; } = null!; public BigInteger Amount { get; init; } } } diff --git a/src/Neo/SmartContract/Native/OracleContract.cs b/src/Neo/SmartContract/Native/OracleContract.cs index 42f41f5720..f21c6262f7 100644 --- a/src/Neo/SmartContract/Native/OracleContract.cs +++ b/src/Neo/SmartContract/Native/OracleContract.cs @@ -23,6 +23,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using Array = System.Array; namespace Neo.SmartContract.Native { @@ -45,10 +46,10 @@ internal OracleContract() { var events = new List(Manifest.Abi.Events) { - new ContractEventDescriptor + new() { Name = "OracleRequest", - Parameters = new ContractParameterDefinition[] + Parameters = new[] { new ContractParameterDefinition() { @@ -72,10 +73,10 @@ internal OracleContract() } } }, - new ContractEventDescriptor + new() { Name = "OracleResponse", - Parameters = new ContractParameterDefinition[] + Parameters = new[] { new ContractParameterDefinition() { @@ -100,7 +101,7 @@ private void SetPrice(ApplicationEngine engine, long price) if (price <= 0) throw new ArgumentOutOfRangeException(nameof(price)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Price)).Set(price); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Price))?.Set(price); } /// @@ -111,7 +112,7 @@ private void SetPrice(ApplicationEngine engine, long price) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public long GetPrice(DataCache snapshot) { - return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_Price)]; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_Price)]!; } [ContractMethod(RequiredCallFlags = CallFlags.States | CallFlags.AllowCall | CallFlags.AllowNotify)] @@ -119,23 +120,23 @@ private ContractTask Finish(ApplicationEngine engine) { if (engine.InvocationStack.Count != 2) throw new InvalidOperationException(); if (engine.GetInvocationCounter() != 1) throw new InvalidOperationException(); - Transaction tx = (Transaction)engine.ScriptContainer; - OracleResponse response = tx.GetAttribute(); + Transaction tx = (Transaction)engine.ScriptContainer!; + OracleResponse? response = tx.GetAttribute(); if (response == null) throw new ArgumentException("Oracle response was not found"); - OracleRequest request = GetRequest(engine.Snapshot, response.Id); + OracleRequest? request = GetRequest(engine.Snapshot, response.Id); if (request == null) throw new ArgumentException("Oracle request was not found"); engine.SendNotification(Hash, "OracleResponse", new VM.Types.Array(engine.ReferenceCounter) { response.Id, request.OriginalTxid.ToArray() }); StackItem userData = BinarySerializer.Deserialize(request.UserData, engine.Limits, engine.ReferenceCounter); return engine.CallFromNativeContract(Hash, request.CallbackContract, request.CallbackMethod, request.Url, userData, (int)response.Code, response.Result); } - private UInt256 GetOriginalTxid(ApplicationEngine engine) + private UInt256? GetOriginalTxid(ApplicationEngine engine) { - Transaction tx = (Transaction)engine.ScriptContainer; - OracleResponse response = tx.GetAttribute(); + Transaction tx = (Transaction)engine.ScriptContainer!; + OracleResponse? response = tx.GetAttribute(); if (response is null) return tx.Hash; - OracleRequest request = GetRequest(engine.Snapshot, response.Id); - return request.OriginalTxid; + OracleRequest? request = GetRequest(engine.Snapshot, response.Id); + return request?.OriginalTxid; } /// @@ -144,7 +145,7 @@ private UInt256 GetOriginalTxid(ApplicationEngine engine) /// The snapshot used to read data. /// The id of the request. /// The pending request. Or if no request with the specified id is found. - public OracleRequest GetRequest(DataCache snapshot, ulong id) + public OracleRequest? GetRequest(DataCache snapshot, ulong id) { return snapshot.TryGet(CreateStorageKey(Prefix_Request).AddBigEndian(id))?.GetInteroperable(); } @@ -165,12 +166,12 @@ public OracleRequest GetRequest(DataCache snapshot, ulong id) /// The snapshot used to read data. /// The url of the requests. /// All the requests with the specified url. - public IEnumerable<(ulong, OracleRequest)> GetRequestsByUrl(DataCache snapshot, string url) + public IEnumerable<(ulong, OracleRequest?)> GetRequestsByUrl(DataCache snapshot, string url) { - IdList list = snapshot.TryGet(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)))?.GetInteroperable(); + IdList? list = snapshot.TryGet(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)))?.GetInteroperable(); if (list is null) yield break; foreach (ulong id in list) - yield return (id, snapshot[CreateStorageKey(Prefix_Request).AddBigEndian(id)].GetInteroperable()); + yield return (id, snapshot[CreateStorageKey(Prefix_Request).AddBigEndian(id)]?.GetInteroperable()); } private static byte[] GetUrlHash(string url) @@ -187,27 +188,27 @@ internal override ContractTask Initialize(ApplicationEngine engine) internal override async ContractTask PostPersist(ApplicationEngine engine) { - (UInt160 Account, BigInteger GAS)[] nodes = null; - foreach (Transaction tx in engine.PersistingBlock.Transactions) + (UInt160 Account, BigInteger GAS)[]? nodes = null; + foreach (Transaction? tx in engine.PersistingBlock?.Transactions ?? Array.Empty()) { //Filter the response transactions - OracleResponse response = tx.GetAttribute(); + OracleResponse? response = tx.GetAttribute(); if (response is null) continue; //Remove the request from storage StorageKey key = CreateStorageKey(Prefix_Request).AddBigEndian(response.Id); - OracleRequest request = engine.Snapshot.TryGet(key)?.GetInteroperable(); + OracleRequest? request = engine.Snapshot.TryGet(key)?.GetInteroperable(); if (request == null) continue; engine.Snapshot.Delete(key); //Remove the id from IdList key = CreateStorageKey(Prefix_IdList).Add(GetUrlHash(request.Url)); - IdList list = engine.Snapshot.GetAndChange(key).GetInteroperable(); - if (!list.Remove(response.Id)) throw new InvalidOperationException(); - if (list.Count == 0) engine.Snapshot.Delete(key); + IdList? list = engine.Snapshot.GetAndChange(key)?.GetInteroperable(); + if (list != null && !list.Remove(response.Id)) throw new InvalidOperationException(); + if (list != null && list.Count == 0) engine.Snapshot.Delete(key); //Mint GAS for oracle nodes - nodes ??= RoleManagement.GetDesignatedByRole(engine.Snapshot, Role.Oracle, engine.PersistingBlock.Index).Select(p => (Contract.CreateSignatureRedeemScript(p).ToScriptHash(), BigInteger.Zero)).ToArray(); + nodes ??= RoleManagement.GetDesignatedByRole(engine.Snapshot, Role.Oracle, engine.PersistingBlock!.Index).Select(p => (Contract.CreateSignatureRedeemScript(p).ToScriptHash(), BigInteger.Zero)).ToArray(); if (nodes.Length > 0) { int index = (int)(response.Id % (ulong)nodes.Length); @@ -225,7 +226,7 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) } [ContractMethod(RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] - private async ContractTask Request(ApplicationEngine engine, string url, string filter, string callback, StackItem userData, long gasForResponse) + private async ContractTask Request(ApplicationEngine engine, string url, string? filter, string callback, StackItem userData, long gasForResponse) { //Check the arguments if (Utility.StrictUTF8.GetByteCount(url) > MaxUrlLength @@ -241,37 +242,37 @@ private async ContractTask Request(ApplicationEngine engine, string url, string await GAS.Mint(engine, Hash, gasForResponse, false); //Increase the request id - StorageItem item_id = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RequestId)); + StorageItem item_id = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RequestId)).NullExceptionOr(); ulong id = (ulong)(BigInteger)item_id; item_id.Add(1); //Put the request to storage - if (ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash) is null) + if (ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash.NotNull()) is null) throw new InvalidOperationException(); engine.Snapshot.Add(CreateStorageKey(Prefix_Request).AddBigEndian(id), new StorageItem(new OracleRequest { - OriginalTxid = GetOriginalTxid(engine), + OriginalTxid = GetOriginalTxid(engine)!, GasForResponse = gasForResponse, Url = url, Filter = filter, - CallbackContract = engine.CallingScriptHash, + CallbackContract = engine.CallingScriptHash!, CallbackMethod = callback, UserData = BinarySerializer.Serialize(userData, MaxUserDataLength, engine.Limits.MaxStackSize) })); //Add the id to the IdList - var list = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)), () => new StorageItem(new IdList())).GetInteroperable(); - if (list.Count >= 256) + var list = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)), () => new StorageItem(new IdList()))?.GetInteroperable(); + if (list?.Count >= 256) throw new InvalidOperationException("There are too many pending responses for this url"); - list.Add(id); + list?.Add(id); - engine.SendNotification(Hash, "OracleRequest", new VM.Types.Array(engine.ReferenceCounter) { id, engine.CallingScriptHash.ToArray(), url, filter ?? StackItem.Null }); + engine.SendNotification(Hash, "OracleRequest", new VM.Types.Array(engine.ReferenceCounter) { id, engine.CallingScriptHash!.ToArray(), url, filter ?? StackItem.Null }); } [ContractMethod(CpuFee = 1 << 15)] private bool Verify(ApplicationEngine engine) { - Transaction tx = (Transaction)engine.ScriptContainer; + Transaction tx = (Transaction)engine.ScriptContainer!; return tx?.GetAttribute() != null; } @@ -282,7 +283,7 @@ protected override ulong ElementFromStackItem(StackItem item) return (ulong)item.GetInteger(); } - protected override StackItem ElementToStackItem(ulong element, ReferenceCounter referenceCounter) + protected override StackItem ElementToStackItem(ulong element, ReferenceCounter? referenceCounter) { return element; } diff --git a/src/Neo/SmartContract/Native/OracleRequest.cs b/src/Neo/SmartContract/Native/OracleRequest.cs index d18968ef00..b8d04cd1c6 100644 --- a/src/Neo/SmartContract/Native/OracleRequest.cs +++ b/src/Neo/SmartContract/Native/OracleRequest.cs @@ -24,7 +24,7 @@ public class OracleRequest : IInteroperable /// /// The original transaction that sent the related request. /// - public UInt256 OriginalTxid; + public UInt256 OriginalTxid = null!; /// /// The maximum amount of GAS that can be used when executing response callback. @@ -34,41 +34,41 @@ public class OracleRequest : IInteroperable /// /// The url of the request. /// - public string Url; + public string Url = null!; /// /// The filter for the response. /// - public string Filter; + public string? Filter; /// /// The hash of the callback contract. /// - public UInt160 CallbackContract; + public UInt160 CallbackContract = null!; /// /// The name of the callback method. /// - public string CallbackMethod; + public string CallbackMethod = null!; /// /// The user-defined object that will be passed to the callback. /// - public byte[] UserData; + public byte[] UserData = null!; public void FromStackItem(StackItem stackItem) { Array array = (Array)stackItem; OriginalTxid = new UInt256(array[0].GetSpan()); GasForResponse = (long)array[1].GetInteger(); - Url = array[2].GetString(); + Url = array[2].GetString()!; Filter = array[3].GetString(); CallbackContract = new UInt160(array[4].GetSpan()); - CallbackMethod = array[5].GetString(); + CallbackMethod = array[5].GetString()!; UserData = array[6].GetSpan().ToArray(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Array(referenceCounter) { diff --git a/src/Neo/SmartContract/Native/PolicyContract.cs b/src/Neo/SmartContract/Native/PolicyContract.cs index c633cb7309..e83c969f6f 100644 --- a/src/Neo/SmartContract/Native/PolicyContract.cs +++ b/src/Neo/SmartContract/Native/PolicyContract.cs @@ -84,7 +84,7 @@ internal override ContractTask Initialize(ApplicationEngine engine) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public long GetFeePerByte(DataCache snapshot) { - return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_FeePerByte)]; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_FeePerByte)]!; } /// @@ -95,7 +95,7 @@ public long GetFeePerByte(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public uint GetExecFeeFactor(DataCache snapshot) { - return (uint)(BigInteger)snapshot[CreateStorageKey(Prefix_ExecFeeFactor)]; + return (uint)(BigInteger)snapshot[CreateStorageKey(Prefix_ExecFeeFactor)]!; } /// @@ -106,7 +106,7 @@ public uint GetExecFeeFactor(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public uint GetStoragePrice(DataCache snapshot) { - return (uint)(BigInteger)snapshot[CreateStorageKey(Prefix_StoragePrice)]; + return (uint)(BigInteger)snapshot[CreateStorageKey(Prefix_StoragePrice)]!; } /// @@ -119,7 +119,7 @@ public uint GetStoragePrice(DataCache snapshot) public uint GetAttributeFee(DataCache snapshot, byte attributeType) { if (!Enum.IsDefined(typeof(TransactionAttributeType), attributeType)) throw new InvalidOperationException(); - StorageItem entry = snapshot.TryGet(CreateStorageKey(Prefix_AttributeFee).Add(attributeType)); + StorageItem? entry = snapshot.TryGet(CreateStorageKey(Prefix_AttributeFee).Add(attributeType)); if (entry == null) return DefaultAttributeFee; return (uint)(BigInteger)entry; @@ -144,7 +144,7 @@ private void SetAttributeFee(ApplicationEngine engine, byte attributeType, uint if (value > MaxAttributeFee) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_AttributeFee).Add(attributeType), () => new StorageItem(DefaultAttributeFee)).Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_AttributeFee).Add(attributeType), () => new StorageItem(DefaultAttributeFee))!.Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -152,7 +152,7 @@ private void SetFeePerByte(ApplicationEngine engine, long value) { if (value < 0 || value > 1_00000000) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_FeePerByte)).Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_FeePerByte))!.Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -160,7 +160,7 @@ private void SetExecFeeFactor(ApplicationEngine engine, uint value) { if (value == 0 || value > MaxExecFeeFactor) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_ExecFeeFactor)).Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_ExecFeeFactor))!.Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -168,7 +168,7 @@ private void SetStoragePrice(ApplicationEngine engine, uint value) { if (value == 0 || value > MaxStoragePrice) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_StoragePrice)).Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_StoragePrice))!.Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] diff --git a/src/Neo/SmartContract/Native/RoleManagement.cs b/src/Neo/SmartContract/Native/RoleManagement.cs index 1c2fa0a299..ead9224400 100644 --- a/src/Neo/SmartContract/Native/RoleManagement.cs +++ b/src/Neo/SmartContract/Native/RoleManagement.cs @@ -102,7 +102,7 @@ protected override ECPoint ElementFromStackItem(StackItem item) return ECPoint.DecodePoint(item.GetSpan(), ECCurve.Secp256r1); } - protected override StackItem ElementToStackItem(ECPoint element, ReferenceCounter referenceCounter) + protected override StackItem ElementToStackItem(ECPoint element, ReferenceCounter? referenceCounter) { return element.ToArray(); } diff --git a/src/Neo/SmartContract/Native/StdLib.cs b/src/Neo/SmartContract/Native/StdLib.cs index 3ca836a3ec..ba04e9b0d0 100644 --- a/src/Neo/SmartContract/Native/StdLib.cs +++ b/src/Neo/SmartContract/Native/StdLib.cs @@ -50,7 +50,7 @@ private static byte[] JsonSerialize(ApplicationEngine engine, StackItem item) [ContractMethod(CpuFee = 1 << 14)] private static StackItem JsonDeserialize(ApplicationEngine engine, byte[] json) { - return JsonSerializer.Deserialize(engine, JToken.Parse(json, 10), engine.Limits, engine.ReferenceCounter); + return JsonSerializer.Deserialize(engine, JToken.Parse(json, 10)!, engine.Limits, engine.ReferenceCounter); } /// diff --git a/src/Neo/SmartContract/Native/TransactionState.cs b/src/Neo/SmartContract/Native/TransactionState.cs index b17296b42d..1dce060702 100644 --- a/src/Neo/SmartContract/Native/TransactionState.cs +++ b/src/Neo/SmartContract/Native/TransactionState.cs @@ -31,7 +31,7 @@ public class TransactionState : IInteroperable /// /// The transaction, if the transaction is trimmed this value will be null /// - public Transaction Transaction; + public Transaction? Transaction; /// /// The execution state @@ -75,7 +75,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) State = (VMState)(byte)@struct[2].GetInteger(); } - StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) { if (Transaction is null) return new Struct(referenceCounter) { BlockIndex }; diff --git a/src/Neo/SmartContract/Native/TrimmedBlock.cs b/src/Neo/SmartContract/Native/TrimmedBlock.cs index 4cc4c39c0f..64e6d4f2d8 100644 --- a/src/Neo/SmartContract/Native/TrimmedBlock.cs +++ b/src/Neo/SmartContract/Native/TrimmedBlock.cs @@ -15,7 +15,6 @@ using Neo.VM.Types; using System; using System.IO; -using System.Linq; namespace Neo.SmartContract.Native { @@ -27,12 +26,12 @@ public class TrimmedBlock : IInteroperable, ISerializable /// /// The header of the block. /// - public Header Header; + public Header Header = null!; /// /// The hashes of the transactions of the block. /// - public UInt256[] Hashes; + public UInt256[] Hashes = null!; /// /// The hash of the block. @@ -79,7 +78,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) throw new NotSupportedException(); } - StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) { return new VM.Types.Array(referenceCounter, new StackItem[] { diff --git a/src/Neo/SmartContract/NefFile.cs b/src/Neo/SmartContract/NefFile.cs index 1ffa7baf20..ed818b0052 100644 --- a/src/Neo/SmartContract/NefFile.cs +++ b/src/Neo/SmartContract/NefFile.cs @@ -51,17 +51,17 @@ public class NefFile : ISerializable /// /// The name and version of the compiler that generated this nef file. /// - public string Compiler { get; set; } + public string Compiler { get; set; } = null!; /// /// The url of the source files. /// - public string Source { get; set; } + public string Source { get; set; } = null!; /// /// The methods that to be called statically. /// - public MethodToken[] Tokens { get; set; } + public MethodToken[] Tokens { get; set; } = null!; /// /// The script of the contract. diff --git a/src/Neo/SmartContract/NotifyEventArgs.cs b/src/Neo/SmartContract/NotifyEventArgs.cs index 0a509101c1..e4860113b7 100644 --- a/src/Neo/SmartContract/NotifyEventArgs.cs +++ b/src/Neo/SmartContract/NotifyEventArgs.cs @@ -63,7 +63,7 @@ public void FromStackItem(StackItem stackItem) throw new NotSupportedException(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Array(referenceCounter) { diff --git a/src/Neo/SmartContract/StorageItem.cs b/src/Neo/SmartContract/StorageItem.cs index 0f13c3c1f0..0383a2303c 100644 --- a/src/Neo/SmartContract/StorageItem.cs +++ b/src/Neo/SmartContract/StorageItem.cs @@ -23,7 +23,7 @@ namespace Neo.SmartContract public class StorageItem : ISerializable { private ReadOnlyMemory value; - private object cache; + private object? cache; public int Size => Value.GetVarSize(); diff --git a/src/Neo/SmartContract/StorageKey.cs b/src/Neo/SmartContract/StorageKey.cs index a0136e4456..08c5396504 100644 --- a/src/Neo/SmartContract/StorageKey.cs +++ b/src/Neo/SmartContract/StorageKey.cs @@ -30,7 +30,7 @@ public sealed record StorageKey /// public ReadOnlyMemory Key { get; init; } - private byte[] cache = null; + private byte[]? cache = null; public StorageKey() { } @@ -55,7 +55,7 @@ public static byte[] CreateSearchPrefix(int id, ReadOnlySpan prefix) return buffer; } - public bool Equals(StorageKey other) + public bool Equals(StorageKey? other) { if (other is null) return false; From 28a1cca64303440b5915a691aa766dfbf5c98ffd Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 10:16:13 +0800 Subject: [PATCH 06/36] Revert "use nullable smartcontract" This reverts commit f6879088498e0f8a29d5ddcd7f15586609fb4cc4. --- .../ApplicationEngine.Contract.cs | 14 +-- .../SmartContract/ApplicationEngine.Crypto.cs | 4 +- .../ApplicationEngine.Runtime.cs | 64 +++++----- .../ApplicationEngine.Storage.cs | 7 +- src/Neo/SmartContract/ApplicationEngine.cs | 103 ++++++++-------- src/Neo/SmartContract/BinarySerializer.cs | 8 +- src/Neo/SmartContract/Contract.cs | 10 +- src/Neo/SmartContract/ContractParameter.cs | 32 +++-- .../ContractParametersContext.cs | 77 ++++++------ src/Neo/SmartContract/ContractState.cs | 10 +- src/Neo/SmartContract/ContractTask.cs | 4 +- src/Neo/SmartContract/ContractTaskAwaiter.cs | 20 ++-- .../ContractTaskMethodBuilder.cs | 4 +- src/Neo/SmartContract/DeployedContract.cs | 2 +- .../SmartContract/ExecutionContextState.cs | 10 +- src/Neo/SmartContract/Helper.cs | 13 +- .../IApplicationEngineProvider.cs | 2 +- src/Neo/SmartContract/IInteroperable.cs | 2 +- src/Neo/SmartContract/InteropDescriptor.cs | 6 +- .../InteropParameterDescriptor.cs | 16 +-- src/Neo/SmartContract/JsonSerializer.cs | 17 ++- src/Neo/SmartContract/Manifest/ContractAbi.cs | 14 +-- .../Manifest/ContractEventDescriptor.cs | 13 +- .../SmartContract/Manifest/ContractGroup.cs | 10 +- .../Manifest/ContractManifest.cs | 38 +++--- .../Manifest/ContractMethodDescriptor.cs | 13 +- .../Manifest/ContractParameterDefinition.cs | 10 +- .../Manifest/ContractPermission.cs | 20 ++-- .../Manifest/ContractPermissionDescriptor.cs | 24 ++-- .../Manifest/WildCardContainer.cs | 12 +- src/Neo/SmartContract/MethodToken.cs | 4 +- src/Neo/SmartContract/Native/AccountState.cs | 2 +- .../Native/ContractManagement.cs | 34 +++--- .../Native/ContractMethodAttribute.cs | 2 +- .../Native/ContractMethodMetadata.cs | 2 +- src/Neo/SmartContract/Native/FungibleToken.cs | 18 +-- src/Neo/SmartContract/Native/GasToken.cs | 9 +- .../SmartContract/Native/HashIndexState.cs | 4 +- .../SmartContract/Native/InteroperableList.cs | 6 +- .../SmartContract/Native/LedgerContract.cs | 90 +++++++------- .../SmartContract/Native/NativeContract.cs | 10 +- src/Neo/SmartContract/Native/NeoToken.cs | 111 +++++++++--------- .../SmartContract/Native/OracleContract.cs | 75 ++++++------ src/Neo/SmartContract/Native/OracleRequest.cs | 18 +-- .../SmartContract/Native/PolicyContract.cs | 16 +-- .../SmartContract/Native/RoleManagement.cs | 2 +- src/Neo/SmartContract/Native/StdLib.cs | 2 +- .../SmartContract/Native/TransactionState.cs | 4 +- src/Neo/SmartContract/Native/TrimmedBlock.cs | 7 +- src/Neo/SmartContract/NefFile.cs | 6 +- src/Neo/SmartContract/NotifyEventArgs.cs | 2 +- src/Neo/SmartContract/StorageItem.cs | 2 +- src/Neo/SmartContract/StorageKey.cs | 4 +- 53 files changed, 489 insertions(+), 520 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.Contract.cs b/src/Neo/SmartContract/ApplicationEngine.Contract.cs index dc6c17d036..5e45ba4645 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Contract.cs @@ -76,9 +76,9 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl if ((callFlags & ~CallFlags.All) != 0) throw new ArgumentOutOfRangeException(nameof(callFlags)); - ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Count); + ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Count); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Count} parameter(s) doesn't exist in the contract {contractHash}."); bool hasReturnValue = md.ReturnType != ContractParameterType.Void; @@ -93,10 +93,10 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl /// The version of the native contract to be called. protected internal void CallNativeContract(byte version) { - NativeContract? contract = NativeContract.GetContract(CurrentScriptHash!); + NativeContract contract = NativeContract.GetContract(CurrentScriptHash); if (contract is null) throw new InvalidOperationException("It is not allowed to use \"System.Contract.CallNative\" directly."); - if (!contract.IsActive(ProtocolSettings!, NativeContract.Ledger.CurrentIndex(Snapshot))) + if (!contract.IsActive(ProtocolSettings, NativeContract.Ledger.CurrentIndex(Snapshot))) throw new InvalidOperationException($"The native contract {contract.Name} is not active."); contract.Invoke(this, version); } @@ -108,7 +108,7 @@ protected internal void CallNativeContract(byte version) /// The of the current context. protected internal CallFlags GetCallFlags() { - var state = CurrentContext!.GetState(); + var state = CurrentContext.GetState(); return state.CallFlags; } @@ -155,7 +155,7 @@ protected internal async void NativeOnPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings!, PersistingBlock!.Index)) + if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) await contract.OnPersist(this); } } @@ -177,7 +177,7 @@ protected internal async void NativePostPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings!, PersistingBlock!.Index)) + if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) await contract.PostPersist(this); } } diff --git a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs index 7c151e6f2e..1a8b2c7d6d 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs @@ -46,7 +46,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) { try { - return Crypto.VerifySignature(ScriptContainer!.GetSignData(ProtocolSettings!.Network), signature, pubkey, ECCurve.Secp256r1); + return Crypto.VerifySignature(ScriptContainer.GetSignData(ProtocolSettings.Network), signature, pubkey, ECCurve.Secp256r1); } catch (ArgumentException) { @@ -63,7 +63,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) /// if the signatures are valid; otherwise, . protected internal bool CheckMultisig(byte[][] pubkeys, byte[][] signatures) { - byte[] message = ScriptContainer!.GetSignData(ProtocolSettings!.Network); + byte[] message = ScriptContainer.GetSignData(ProtocolSettings.Network); int m = signatures.Length, n = pubkeys.Length; if (n == 0 || m == 0 || m > n) throw new ArgumentException(); AddGas(CheckSigPrice * n * ExecFeeFactor); diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index 6d7b9d1f9b..293b245bd7 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -10,6 +10,7 @@ // modifications are permitted. using Neo.Cryptography.ECC; +using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.SmartContract.Native; using Neo.VM; @@ -35,7 +36,7 @@ partial class ApplicationEngine /// public const int MaxNotificationSize = 1024; - private uint random_times; + private uint random_times = 0; /// /// The of System.Runtime.Platform. @@ -168,7 +169,7 @@ internal protected static string GetPlatform() /// The magic number of the current network. internal protected uint GetNetwork() { - return ProtocolSettings!.Network; + return ProtocolSettings.Network; } /// @@ -178,7 +179,7 @@ internal protected uint GetNetwork() /// The address version of the current network. internal protected byte GetAddressVersion() { - return ProtocolSettings!.AddressVersion; + return ProtocolSettings.AddressVersion; } /// @@ -188,7 +189,7 @@ internal protected byte GetAddressVersion() /// The timestamp of the current block. protected internal ulong GetTime() { - return PersistingBlock!.Timestamp; + return PersistingBlock.Timestamp; } /// @@ -211,7 +212,7 @@ protected internal void RuntimeLoadScript(byte[] script, CallFlags callFlags, Ar if ((callFlags & ~CallFlags.All) != 0) throw new ArgumentOutOfRangeException(nameof(callFlags)); - ExecutionContextState state = CurrentContext!.GetState(); + ExecutionContextState state = CurrentContext.GetState(); ExecutionContext context = LoadScript(new Script(script, true), configureState: p => { p.CallingContext = CurrentContext; @@ -252,17 +253,17 @@ protected internal bool CheckWitnessInternal(UInt160 hash) if (ScriptContainer is Transaction tx) { Signer[] signers; - OracleResponse? response = tx.GetAttribute(); + OracleResponse response = tx.GetAttribute(); if (response is null) { signers = tx.Signers; } else { - OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id).NotNull(); - signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid)!.Signers; + OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id); + signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid).Signers; } - Signer? signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); + Signer signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); if (signer is null) return false; foreach (WitnessRule rule in signer.GetAllRules()) { @@ -289,9 +290,9 @@ protected internal bool CheckWitnessInternal(UInt160 hash) /// The number of times the current contract has been called during the execution. protected internal int GetInvocationCounter() { - if (!invocationCounter.TryGetValue(CurrentScriptHash!, out var counter)) + if (!invocationCounter.TryGetValue(CurrentScriptHash, out var counter)) { - invocationCounter[CurrentScriptHash!] = counter = 1; + invocationCounter[CurrentScriptHash] = counter = 1; } return counter; } @@ -307,12 +308,12 @@ protected internal BigInteger GetRandom() long price; if (IsHardforkEnabled(Hardfork.HF_Aspidochelone)) { - buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings!.Network + random_times++); + buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network + random_times++); price = 1 << 13; } else { - buffer = nonceData = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings!.Network); + buffer = nonceData = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network); price = 1 << 4; } AddGas(price * ExecFeeFactor); @@ -330,7 +331,7 @@ protected internal void RuntimeLog(byte[] state) try { string message = Utility.StrictUTF8.GetString(state); - Log?.Invoke(this, new LogEventArgs(ScriptContainer!, CurrentScriptHash!, message)); + Log?.Invoke(this, new LogEventArgs(ScriptContainer, CurrentScriptHash, message)); } catch { @@ -353,7 +354,7 @@ protected internal void RuntimeNotify(byte[] eventName, Array state) } if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); string name = Utility.StrictUTF8.GetString(eventName); - ContractState? contract = CurrentContext?.GetState().Contract; + ContractState contract = CurrentContext.GetState().Contract; if (contract is null) throw new InvalidOperationException("Notifications are not allowed in dynamic scripts."); var @event = contract.Manifest.Abi.Events.FirstOrDefault(p => string.Equals(p.Name, name, StringComparison.Ordinal)); @@ -370,21 +371,18 @@ protected internal void RuntimeNotify(byte[] eventName, Array state) using MemoryStream ms = new(MaxNotificationSize); using BinaryWriter writer = new(ms, Utility.StrictUTF8, true); BinarySerializer.Serialize(writer, state, MaxNotificationSize, Limits.MaxStackSize); - if (CurrentScriptHash != null) - { - SendNotification(CurrentScriptHash, name, state); - } + SendNotification(CurrentScriptHash, name, state); } protected internal void RuntimeNotifyV1(byte[] eventName, Array state) { if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); - if (CurrentContext?.GetState().Contract is null) + if (CurrentContext.GetState().Contract is null) throw new InvalidOperationException("Notifications are not allowed in dynamic scripts."); using MemoryStream ms = new(MaxNotificationSize); using BinaryWriter writer = new(ms, Utility.StrictUTF8, true); BinarySerializer.Serialize(writer, state, MaxNotificationSize, Limits.MaxStackSize); - SendNotification(CurrentScriptHash!, Utility.StrictUTF8.GetString(eventName), state); + SendNotification(CurrentScriptHash, Utility.StrictUTF8.GetString(eventName), state); } /// @@ -395,14 +393,11 @@ protected internal void RuntimeNotifyV1(byte[] eventName, Array state) /// The arguments of the event. protected internal void SendNotification(UInt160 hash, string eventName, Array state) { - NotifyEventArgs notification = new(ScriptContainer!, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); - Notify.Invoke(this, notification); + NotifyEventArgs notification = new(ScriptContainer, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); + Notify?.Invoke(this, notification); notifications ??= new List(); notifications.Add(notification); - if (CurrentContext != null) - { - CurrentContext.GetState().NotificationCount++; - } + CurrentContext.GetState().NotificationCount++; } /// @@ -411,12 +406,12 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s /// /// The hash of the specified contract. It can be set to to get all notifications. /// The notifications sent during the execution. - protected internal NotifyEventArgs[] GetNotifications(UInt160? hash) + protected internal NotifyEventArgs[] GetNotifications(UInt160 hash) { - IEnumerable notifyEventArgsEnumerable = Notifications; + IEnumerable notifications = Notifications; if (hash != null) // must filter by scriptHash - notifyEventArgsEnumerable = notifyEventArgsEnumerable.Where(p => p.ScriptHash == hash); - NotifyEventArgs[] array = notifyEventArgsEnumerable.ToArray(); + notifications = notifications.Where(p => p.ScriptHash == hash); + NotifyEventArgs[] array = notifications.ToArray(); if (array.Length > Limits.MaxStackSize) throw new InvalidOperationException(); return array; } @@ -437,7 +432,7 @@ protected internal void BurnGas(long gas) /// Get the Signers of the current transaction. /// /// The signers of the current transaction, or null if is not related to a transaction execution. - protected internal Signer[]? GetCurrentSigners() + protected internal Signer[] GetCurrentSigners() { if (ScriptContainer is Transaction tx) return tx.Signers; @@ -468,10 +463,7 @@ private static bool CheckItemType(StackItem item, ContractParameterType type) _ = Utility.StrictUTF8.GetString(item.GetSpan()); // Prevent any non-UTF8 string return true; } - catch - { - // ignored - } + catch { } } return false; } diff --git a/src/Neo/SmartContract/ApplicationEngine.Storage.cs b/src/Neo/SmartContract/ApplicationEngine.Storage.cs index 557e1f73bc..3a8bb9d122 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Storage.cs @@ -9,7 +9,6 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo.IO; using Neo.Persistence; using Neo.SmartContract.Iterators; using Neo.SmartContract.Native; @@ -78,7 +77,7 @@ partial class ApplicationEngine /// The storage context for the current contract. protected internal StorageContext GetStorageContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!)!; + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); return new StorageContext { Id = contract.Id, @@ -93,7 +92,7 @@ protected internal StorageContext GetStorageContext() /// The storage context for the current contract. protected internal StorageContext GetReadOnlyContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!)!; + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); return new StorageContext { Id = contract.Id, @@ -178,7 +177,7 @@ protected internal void Put(StorageContext context, byte[] key, byte[] value) Id = context.Id, Key = key }; - StorageItem? item = Snapshot.GetAndChange(skey); + StorageItem item = Snapshot.GetAndChange(skey); if (item is null) { newDataSize = key.Length + value.Length; diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 8d99880871..ba161e6951 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -40,20 +40,20 @@ public partial class ApplicationEngine : ExecutionEngine /// /// Triggered when a contract calls System.Runtime.Notify. /// - public static event EventHandler Notify = null!; + public static event EventHandler Notify; /// /// Triggered when a contract calls System.Runtime.Log. /// - public static event EventHandler Log = null!; + public static event EventHandler Log; private static readonly IList AllHardforks = Enum.GetValues(typeof(Hardfork)).Cast().ToArray(); - private static Dictionary? services; + private static Dictionary services; private readonly long gas_amount; - private Dictionary? states; - private readonly DataCache? originalSnapshot; - private List? notifications; - private List? disposables; + private Dictionary states; + private readonly DataCache originalSnapshot; + private List notifications; + private List disposables; private readonly Dictionary invocationCounter = new(); private readonly Dictionary contractTasks = new(); internal readonly uint ExecFeeFactor; @@ -63,17 +63,17 @@ public partial class ApplicationEngine : ExecutionEngine /// /// Gets or sets the provider used to create the . /// - public static IApplicationEngineProvider? Provider { get; set; } + public static IApplicationEngineProvider Provider { get; set; } /// /// Gets the descriptors of all interoperable services available in NEO. /// - public static IReadOnlyDictionary Services => services!; + public static IReadOnlyDictionary Services => services; /// /// The diagnostic used by the engine. This property can be . /// - public IDiagnostic? Diagnostic { get; } + public IDiagnostic Diagnostic { get; } private List Disposables => disposables ??= new List(); @@ -85,27 +85,27 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The container that containing the executed script. This field could be if the contract is invoked by system. /// - public IVerifiable? ScriptContainer { get; } + public IVerifiable ScriptContainer { get; } /// /// The snapshot used to read or write data. /// - public DataCache Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot ?? throw new InvalidOperationException("No snapshot available."); + public DataCache Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot; /// /// The block being persisted. This field could be if the is . /// - public Block? PersistingBlock { get; } + public Block PersistingBlock { get; } /// /// The used by the engine. /// - public ProtocolSettings? ProtocolSettings { get; } + public ProtocolSettings ProtocolSettings { get; } /// /// GAS spent to execute. /// - public long GasConsumed { get; private set; } + public long GasConsumed { get; private set; } = 0; /// /// The remaining GAS that can be spent in order to complete the execution. @@ -115,30 +115,30 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The exception that caused the execution to terminate abnormally. This field could be if no exception is thrown. /// - public Exception FaultException { get; private set; } = null!; + public Exception FaultException { get; private set; } /// /// The script hash of the current context. This field could be if no context is loaded to the engine. /// - public UInt160? CurrentScriptHash => CurrentContext?.GetScriptHash(); + public UInt160 CurrentScriptHash => CurrentContext?.GetScriptHash(); /// /// The script hash of the calling contract. This field could be if the current context is the entry context. /// - public UInt160? CallingScriptHash + public UInt160 CallingScriptHash { get { if (CurrentContext is null) return null; var state = CurrentContext.GetState(); - return state.NativeCallingScriptHash ?? state.CallingContext.GetState().ScriptHash; + return state.NativeCallingScriptHash ?? state.CallingContext?.GetState().ScriptHash; } } /// /// The script hash of the entry context. This field could be if no context is loaded to the engine. /// - public UInt160? EntryScriptHash => EntryContext?.GetScriptHash(); + public UInt160 EntryScriptHash => EntryContext?.GetScriptHash(); /// /// The notifications sent during the execution. @@ -155,7 +155,7 @@ public UInt160? CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic) + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) { this.Trigger = trigger; this.ScriptContainer = container; @@ -202,9 +202,9 @@ internal void Throw(Exception ex) private ExecutionContext CallContractInternal(UInt160 contractHash, string method, CallFlags flags, bool hasReturnValue, StackItem[] args) { - ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Length); + ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Length); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Length} parameter(s) doesn't exist in the contract {contractHash}."); return CallContractInternal(contract, md, flags, hasReturnValue, args); } @@ -220,7 +220,7 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe } else { - ContractState? currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!); + ContractState currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); if (currentContract?.CanCall(contract, method.Name) == false) throw new InvalidOperationException($"Cannot Call Method {method.Name} Of Contract {contract.Hash} From Contract {CurrentScriptHash}"); } @@ -234,7 +234,7 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe invocationCounter[contract.Hash] = 1; } - ExecutionContext currentContext = CurrentContext.NullExceptionOr(); + ExecutionContext currentContext = CurrentContext; ExecutionContextState state = currentContext.GetState(); CallFlags callingFlags = state.CallFlags; @@ -295,7 +295,7 @@ protected override void ContextUnloaded(ExecutionContext context) else { if (state.NotificationCount > 0) - notifications?.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); + notifications.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); } } Diagnostic?.ContextUnloaded(context); @@ -318,7 +318,7 @@ protected override void ContextUnloaded(ExecutionContext context) /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock = null, ProtocolSettings? settings = null, long gas = TestModeGas, IDiagnostic? diagnostic = null) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) { return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -378,12 +378,12 @@ public ExecutionContext LoadContract(ContractState contract, ContractMethodDescr /// The initial position of the instruction pointer. /// The action used to configure the state of the loaded context. /// The loaded context. - public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action? configureState = null) + public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action configureState = null) { // Create and configure context ExecutionContext context = CreateContext(script, rvcount, initialPosition); ExecutionContextState state = context.GetState(); - state.Snapshot = Snapshot.CreateSnapshot(); + state.Snapshot = Snapshot?.CreateSnapshot(); configureState?.Invoke(state); // Load context @@ -394,16 +394,16 @@ public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialP protected override ExecutionContext LoadToken(ushort tokenId) { ValidateCallFlags(CallFlags.ReadStates | CallFlags.AllowCall); - ContractState? contract = CurrentContext?.GetState().Contract; + ContractState contract = CurrentContext.GetState().Contract; if (contract is null || tokenId >= contract.Nef.Tokens.Length) throw new InvalidOperationException(); MethodToken token = contract.Nef.Tokens[tokenId]; - if (token.ParametersCount > CurrentContext?.EvaluationStack.Count) + if (token.ParametersCount > CurrentContext.EvaluationStack.Count) throw new InvalidOperationException(); StackItem[] args = new StackItem[token.ParametersCount]; for (int i = 0; i < token.ParametersCount; i++) args[i] = Pop(); - return CallContractInternal(token.Hash!, token.Method!, token.CallFlags, token.HasReturnValue, args); + return CallContractInternal(token.Hash, token.Method, token.CallFlags, token.HasReturnValue, args); } /// @@ -455,7 +455,7 @@ protected internal object Convert(StackItem item, InteropParameterDescriptor des Array av; if (item is VMArray array) { - av = Array.CreateInstance(descriptor.Type.GetElementType()!, array.Count); + av = Array.CreateInstance(descriptor.Type.GetElementType(), array.Count); for (int i = 0; i < av.Length; i++) av.SetValue(descriptor.Converter(array[i]), i); } @@ -463,7 +463,7 @@ protected internal object Convert(StackItem item, InteropParameterDescriptor des { int count = (int)item.GetInteger(); if (count > Limits.MaxStackSize) throw new InvalidOperationException(); - av = Array.CreateInstance(descriptor.Type.GetElementType()!, count); + av = Array.CreateInstance(descriptor.Type.GetElementType(), count); for (int i = 0; i < av.Length; i++) av.SetValue(descriptor.Converter(Pop()), i); } @@ -498,14 +498,14 @@ public override void Dispose() /// The requirements to check. internal protected void ValidateCallFlags(CallFlags requiredCallFlags) { - ExecutionContextState? state = CurrentContext?.GetState(); - if (state == null || !state.CallFlags.HasFlag(requiredCallFlags)) - throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state?.CallFlags}."); + ExecutionContextState state = CurrentContext.GetState(); + if (!state.CallFlags.HasFlag(requiredCallFlags)) + throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state.CallFlags}."); } protected override void OnSysCall(uint method) { - OnSysCall(services![method]); + OnSysCall(services[method]); } /// @@ -521,8 +521,8 @@ protected virtual void OnSysCall(InteropDescriptor descriptor) for (int i = 0; i < parameters.Length; i++) parameters[i] = Convert(Pop(), descriptor.Parameters[i]); - object? returnValue = descriptor.Handler.Invoke(this, parameters); - if (returnValue is not null && descriptor.Handler.ReturnType != typeof(void)) + object returnValue = descriptor.Handler.Invoke(this, parameters); + if (descriptor.Handler.ReturnType != typeof(void)) Push(Convert(returnValue)); } @@ -541,7 +541,7 @@ protected override void PostExecuteInstruction(Instruction instruction) private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings settings) { UInt256 hash = NativeContract.Ledger.CurrentHash(snapshot); - Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash)!; + Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash); return new Block { Header = new Header @@ -565,7 +565,7 @@ private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings setti private static InteropDescriptor Register(string name, string handler, long fixedPrice, CallFlags requiredCallFlags) { MethodInfo method = typeof(ApplicationEngine).GetMethod(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) - ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)!.GetMethod!; + ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).GetMethod; InteropDescriptor descriptor = new() { Name = name, @@ -590,7 +590,7 @@ private static InteropDescriptor Register(string name, string handler, long fixe /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable? container = null, Block? persistingBlock = null, ProtocolSettings? settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic? diagnostic = null) + public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable container = null, Block persistingBlock = null, ProtocolSettings settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic diagnostic = null) { persistingBlock ??= CreateDummyBlock(snapshot, settings ?? ProtocolSettings.Default); ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -601,38 +601,35 @@ public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snaps public T GetState() { - if (states is null) return default!; - if (!states.TryGetValue(typeof(T), out object? state)) return default!; + if (states is null) return default; + if (!states.TryGetValue(typeof(T), out object state)) return default; return (T)state; } public void SetState(T state) { states ??= new Dictionary(); - if (state != null) - { - states[typeof(T)] = state; - } + states[typeof(T)] = state; } public bool IsHardforkEnabled(Hardfork hardfork) { // Return true if there's no specific configuration or PersistingBlock is null - if (PersistingBlock is null || ProtocolSettings?.Hardforks.Count == 0) + if (PersistingBlock is null || ProtocolSettings.Hardforks.Count == 0) return true; // If the hardfork isn't specified in the configuration, check if it's a new one. - if (ProtocolSettings is not null && !ProtocolSettings!.Hardforks.ContainsKey(hardfork)) + if (!ProtocolSettings.Hardforks.ContainsKey(hardfork)) { int currentHardforkIndex = AllHardforks.IndexOf(hardfork); - int lastConfiguredHardforkIndex = AllHardforks.IndexOf(ProtocolSettings!.Hardforks.Keys.Last()); + int lastConfiguredHardforkIndex = AllHardforks.IndexOf(ProtocolSettings.Hardforks.Keys.Last()); // If it's a newer hardfork compared to the ones in the configuration, disable it. if (currentHardforkIndex > lastConfiguredHardforkIndex) return false; } - if (ProtocolSettings is not null && ProtocolSettings!.Hardforks.TryGetValue(hardfork, out uint height)) + if (ProtocolSettings.Hardforks.TryGetValue(hardfork, out uint height)) { // If the hardfork has a specific height in the configuration, check the block height. return PersistingBlock.Index >= height; diff --git a/src/Neo/SmartContract/BinarySerializer.cs b/src/Neo/SmartContract/BinarySerializer.cs index 14236e139a..2bdeced678 100644 --- a/src/Neo/SmartContract/BinarySerializer.cs +++ b/src/Neo/SmartContract/BinarySerializer.cs @@ -39,7 +39,7 @@ public ContainerPlaceholder(StackItemType type, int count) ElementCount = count; } - public override bool Equals(StackItem? other) => throw new NotSupportedException(); + public override bool Equals(StackItem other) => throw new NotSupportedException(); public override int GetHashCode() => throw new NotSupportedException(); @@ -53,7 +53,7 @@ public ContainerPlaceholder(StackItemType type, int count) /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) + public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) { MemoryReader reader = new(data); return Deserialize(ref reader, (uint)Math.Min(data.Length, limits.MaxItemSize), limits.MaxStackSize, referenceCounter); @@ -66,7 +66,7 @@ public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLi /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) { return Deserialize(ref reader, limits.MaxItemSize, limits.MaxStackSize, referenceCounter); } @@ -79,7 +79,7 @@ public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimi /// The max of items to serialize /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter? referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter referenceCounter = null) { Stack deserialized = new(); int undeserialized = 1; diff --git a/src/Neo/SmartContract/Contract.cs b/src/Neo/SmartContract/Contract.cs index 45f8a3fe8b..dc60c42d50 100644 --- a/src/Neo/SmartContract/Contract.cs +++ b/src/Neo/SmartContract/Contract.cs @@ -25,14 +25,14 @@ public class Contract /// /// The script of the contract. /// - public byte[]? Script; + public byte[] Script; /// /// The parameters of the contract. /// - public ContractParameterType[] ParameterList = Array.Empty(); + public ContractParameterType[] ParameterList; - private UInt160? _scriptHash; + private UInt160 _scriptHash; /// /// The hash of the contract. /// @@ -42,9 +42,9 @@ public virtual UInt160 ScriptHash { if (_scriptHash == null) { - _scriptHash = Script?.ToScriptHash(); + _scriptHash = Script.ToScriptHash(); } - return _scriptHash!; + return _scriptHash; } } diff --git a/src/Neo/SmartContract/ContractParameter.cs b/src/Neo/SmartContract/ContractParameter.cs index a289156726..027fa50e00 100644 --- a/src/Neo/SmartContract/ContractParameter.cs +++ b/src/Neo/SmartContract/ContractParameter.cs @@ -10,7 +10,6 @@ // modifications are permitted. using Neo.Cryptography.ECC; -using Neo.IO; using Neo.Json; using System; using System.Collections.Generic; @@ -33,7 +32,7 @@ public class ContractParameter /// /// The value of the parameter. /// - public object? Value; + public object Value; /// /// Initializes a new instance of the class. @@ -73,21 +72,20 @@ public static ContractParameter FromJson(JObject json) { ContractParameter parameter = new() { - Type = Enum.Parse(json["type"]!.GetString()) + Type = Enum.Parse(json["type"].GetString()) }; - var value = json["value"]; - if (value != null) + if (json["value"] != null) parameter.Value = parameter.Type switch { - ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(value.AsString()), - ContractParameterType.Boolean => value.AsBoolean(), - ContractParameterType.Integer => BigInteger.Parse(value.AsString()), - ContractParameterType.Hash160 => UInt160.Parse(value.AsString()), - ContractParameterType.Hash256 => UInt256.Parse(value.AsString()), - ContractParameterType.PublicKey => ECPoint.Parse(value.AsString(), ECCurve.Secp256r1), - ContractParameterType.String => value.AsString(), - ContractParameterType.Array => ((JArray)value).Select(p => FromJson(p.NullExceptionOr())).ToList(), - ContractParameterType.Map => ((JArray)value).Select(p => new KeyValuePair(FromJson((JObject)p!["key"]!), FromJson(p["value"].NullExceptionOr()))).ToList(), + ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(json["value"].AsString()), + ContractParameterType.Boolean => json["value"].AsBoolean(), + ContractParameterType.Integer => BigInteger.Parse(json["value"].AsString()), + ContractParameterType.Hash160 => UInt160.Parse(json["value"].AsString()), + ContractParameterType.Hash256 => UInt256.Parse(json["value"].AsString()), + ContractParameterType.PublicKey => ECPoint.Parse(json["value"].AsString(), ECCurve.Secp256r1), + ContractParameterType.String => json["value"].AsString(), + ContractParameterType.Array => ((JArray)json["value"]).Select(p => FromJson((JObject)p)).ToList(), + ContractParameterType.Map => ((JArray)json["value"]).Select(p => new KeyValuePair(FromJson((JObject)p["key"]), FromJson((JObject)p["value"]))).ToList(), _ => throw new ArgumentException(null, nameof(json)), }; return parameter; @@ -141,7 +139,7 @@ public JObject ToJson() return ToJson(this, null); } - private static JObject ToJson(ContractParameter parameter, HashSet? context) + private static JObject ToJson(ContractParameter parameter, HashSet context) { JObject json = new(); json["type"] = parameter.Type; @@ -193,7 +191,7 @@ public override string ToString() return ToString(this, null); } - private static string ToString(ContractParameter parameter, HashSet? context) + private static string ToString(ContractParameter parameter, HashSet context) { switch (parameter.Value) { @@ -248,7 +246,7 @@ private static string ToString(ContractParameter parameter, HashSet Signatures; public ContextItem(Contract contract) { - this.Script = contract.Script!; + this.Script = contract.Script; this.Parameters = contract.ParameterList.Select(p => new ContractParameter { Type = p }).ToArray(); this.Signatures = new Dictionary(); } public ContextItem(JObject json) { - this.Script = Convert.FromBase64String(json["script"]!.AsString()); - this.Parameters = json["parameters"].NullExceptionOr().Select(p => ContractParameter.FromJson(p.NullExceptionOr())).ToArray(); - this.Signatures = json["signatures"].NullExceptionOr().Properties.Select(p => new + this.Script = Convert.FromBase64String(json["script"].AsString()); + this.Parameters = ((JArray)json["parameters"]).Select(p => ContractParameter.FromJson((JObject)p)).ToArray(); + this.Signatures = ((JObject)json["signatures"]).Properties.Select(p => new { PublicKey = ECPoint.Parse(p.Key, ECCurve.Secp256r1), - Signature = Convert.FromBase64String(p.Value!.AsString()) + Signature = Convert.FromBase64String(p.Value.AsString()) }).ToDictionary(p => p.PublicKey, p => p.Signature); } public JObject ToJson() { JObject json = new(); - json["script"] = Convert.ToBase64String(Script!); + json["script"] = Convert.ToBase64String(Script); json["parameters"] = new JArray(Parameters.Select(p => p.ToJson())); json["signatures"] = new JObject(); foreach (var signature in Signatures) - json["signatures"]![signature.Key.ToString()] = Convert.ToBase64String(signature.Value); + json["signatures"][signature.Key.ToString()] = Convert.ToBase64String(signature.Value); return json; } } @@ -80,7 +80,7 @@ public JObject ToJson() /// public readonly uint Network; - private readonly Dictionary ContextItems; + private readonly Dictionary ContextItems; /// /// Determines whether all witnesses are ready to be added. @@ -95,7 +95,7 @@ public bool Completed } } - private UInt160[]? _ScriptHashes; + private UInt160[] _ScriptHashes = null; /// /// Gets the script hashes to be verified for the . /// @@ -111,7 +111,7 @@ public ContractParametersContext(DataCache snapshot, IVerifiable verifiable, uin { this.Verifiable = verifiable; this.Snapshot = snapshot; - this.ContextItems = new Dictionary(); + this.ContextItems = new Dictionary(); this.Network = network; } @@ -124,7 +124,7 @@ public ContractParametersContext(DataCache snapshot, IVerifiable verifiable, uin /// if the parameter is added successfully; otherwise, . public bool Add(Contract contract, int index, object parameter) { - ContextItem? item = CreateItem(contract); + ContextItem item = CreateItem(contract); if (item == null) return false; item.Parameters[index].Value = parameter; return true; @@ -138,7 +138,7 @@ public bool Add(Contract contract, int index, object parameter) /// if the parameters are added successfully; otherwise, . public bool Add(Contract contract, params object[] parameters) { - ContextItem? item = CreateItem(contract); + ContextItem item = CreateItem(contract); if (item == null) return false; for (int index = 0; index < parameters.Length; index++) { @@ -156,10 +156,10 @@ public bool Add(Contract contract, params object[] parameters) /// if the signature is added successfully; otherwise, . public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) { - if (IsMultiSigContract(contract.Script, out _, out ECPoint[]? points)) + if (IsMultiSigContract(contract.Script, out _, out ECPoint[] points)) { if (!points.Contains(pubkey)) return false; - ContextItem? item = CreateItem(contract); + ContextItem item = CreateItem(contract); if (item == null) return false; if (item.Parameters.All(p => p.Value != null)) return false; if (!item.Signatures.TryAdd(pubkey, signature)) @@ -198,7 +198,7 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) // return now to prevent array index out of bounds exception return false; } - ContextItem? item = CreateItem(contract); + ContextItem item = CreateItem(contract); if (item == null) return false; if (!item.Signatures.TryAdd(pubkey, signature)) return false; @@ -207,9 +207,9 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) } } - private ContextItem? CreateItem(Contract contract) + private ContextItem CreateItem(Contract contract) { - if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem? item)) + if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem item)) return item; if (!ScriptHashes.Contains(contract.ScriptHash)) return null; @@ -226,22 +226,22 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) /// The converted context. public static ContractParametersContext FromJson(JObject json, DataCache snapshot) { - var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"]!.AsString()); + var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"].AsString()); if (!typeof(IVerifiable).IsAssignableFrom(type)) throw new FormatException(); - var verifiable = (IVerifiable)Activator.CreateInstance(type)!; - byte[] data = Convert.FromBase64String(json["data"]!.AsString()); + var verifiable = (IVerifiable)Activator.CreateInstance(type); + byte[] data = Convert.FromBase64String(json["data"].AsString()); MemoryReader reader = new(data); verifiable.DeserializeUnsigned(ref reader); if (json.ContainsProperty("hash")) { - UInt256? hash = UInt256.Parse(json["hash"]!.GetString()); + UInt256 hash = UInt256.Parse(json["hash"].GetString()); if (hash != verifiable.Hash) throw new FormatException(); } - ContractParametersContext context = new(snapshot, verifiable, (uint)json["network"]!.GetInt32()); - foreach (var (key, value) in ((JObject)json["items"]!).Properties) + ContractParametersContext context = new(snapshot, verifiable, (uint)json["network"].GetInt32()); + foreach (var (key, value) in ((JObject)json["items"]).Properties) { - context.ContextItems.Add(UInt160.Parse(key), new ContextItem((JObject)value!)); + context.ContextItems.Add(UInt160.Parse(key), new ContextItem((JObject)value)); } return context; } @@ -252,7 +252,7 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// The hash of the witness script. /// The specified index. /// The parameter with the specified index. - public ContractParameter? GetParameter(UInt160 scriptHash, int index) + public ContractParameter GetParameter(UInt160 scriptHash, int index) { return GetParameters(scriptHash)?[index]; } @@ -262,11 +262,11 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// /// The hash of the witness script. /// The parameters from the witness script. - public IReadOnlyList? GetParameters(UInt160 scriptHash) + public IReadOnlyList GetParameters(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) return null; - return item?.Parameters; + return item.Parameters; } /// @@ -274,11 +274,11 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// /// The hash of the witness script. /// The signatures from the witness script. - public IReadOnlyDictionary? GetSignatures(UInt160 scriptHash) + public IReadOnlyDictionary GetSignatures(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) return null; - return item?.Signatures; + return item.Signatures; } /// @@ -286,11 +286,11 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// /// The hash of the witness script. /// The witness script. - public byte[]? GetScript(UInt160 scriptHash) + public byte[] GetScript(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) return null; - return item?.Script; + return item.Script; } /// @@ -304,8 +304,7 @@ public Witness[] GetWitnesses() Witness[] witnesses = new Witness[ScriptHashes.Count]; for (int i = 0; i < ScriptHashes.Count; i++) { - ContextItem? item = ContextItems[ScriptHashes[i]]; - if (item == null) continue; + ContextItem item = ContextItems[ScriptHashes[i]]; using ScriptBuilder sb = new(); for (int j = item.Parameters.Length - 1; j >= 0; j--) { @@ -328,7 +327,7 @@ public Witness[] GetWitnesses() /// The parsed context. public static ContractParametersContext Parse(string value, DataCache snapshot) { - return FromJson((JObject)JToken.Parse(value)!, snapshot); + return FromJson((JObject)JToken.Parse(value), snapshot); } /// @@ -349,7 +348,7 @@ public JObject ToJson() } json["items"] = new JObject(); foreach (var item in ContextItems) - json["items"]![item.Key.ToString()] = item!.Value!.ToJson(); + json["items"][item.Key.ToString()] = item.Value.ToJson(); json["network"] = Network; return json; } diff --git a/src/Neo/SmartContract/ContractState.cs b/src/Neo/SmartContract/ContractState.cs index 873b65f514..83ac9d3353 100644 --- a/src/Neo/SmartContract/ContractState.cs +++ b/src/Neo/SmartContract/ContractState.cs @@ -38,17 +38,17 @@ public class ContractState : IInteroperable /// /// The hash of the contract. /// - public UInt160 Hash = null!; + public UInt160 Hash; /// /// The nef of the contract. /// - public NefFile Nef = null!; + public NefFile Nef; /// /// The manifest of the contract. /// - public ContractManifest Manifest = null!; + public ContractManifest Manifest; /// /// The script of the contract. @@ -114,9 +114,9 @@ public JObject ToJson() }; } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Array(referenceCounter, new[] { Id, (int)UpdateCounter, Hash.ToArray(), Nef.ToArray(), Manifest.ToStackItem(referenceCounter) }); + return new Array(referenceCounter, new StackItem[] { Id, (int)UpdateCounter, Hash.ToArray(), Nef.ToArray(), Manifest.ToStackItem(referenceCounter) }); } } } diff --git a/src/Neo/SmartContract/ContractTask.cs b/src/Neo/SmartContract/ContractTask.cs index 72d4b91472..6df3627c37 100644 --- a/src/Neo/SmartContract/ContractTask.cs +++ b/src/Neo/SmartContract/ContractTask.cs @@ -33,7 +33,7 @@ public ContractTask() protected virtual ContractTaskAwaiter CreateAwaiter() => new(); public virtual ContractTaskAwaiter GetAwaiter() => awaiter; - public virtual object? GetResult() => null; + public virtual object GetResult() => null; } [AsyncMethodBuilder(typeof(ContractTaskMethodBuilder<>))] @@ -41,6 +41,6 @@ class ContractTask : ContractTask { protected override ContractTaskAwaiter CreateAwaiter() => new ContractTaskAwaiter(); public override ContractTaskAwaiter GetAwaiter() => (ContractTaskAwaiter)base.GetAwaiter(); - public override object? GetResult() => ((ContractTaskAwaiter)GetAwaiter()).GetResult(); + public override object GetResult() => ((ContractTaskAwaiter)GetAwaiter()).GetResult(); } } diff --git a/src/Neo/SmartContract/ContractTaskAwaiter.cs b/src/Neo/SmartContract/ContractTaskAwaiter.cs index 2bd23d3fc2..a0a0c9a1bb 100644 --- a/src/Neo/SmartContract/ContractTaskAwaiter.cs +++ b/src/Neo/SmartContract/ContractTaskAwaiter.cs @@ -17,15 +17,15 @@ namespace Neo.SmartContract { class ContractTaskAwaiter : INotifyCompletion { - private Action _continuation = null!; - private Exception _exception = null!; + private Action continuation; + private Exception exception; public bool IsCompleted { get; private set; } public void GetResult() { - if (_exception is not null) - throw _exception; + if (exception is not null) + throw exception; } public void SetResult() => RunContinuation(); @@ -34,35 +34,35 @@ public void GetResult() public void SetException(Exception exception) { - this._exception = exception; + this.exception = exception; RunContinuation(); } public void OnCompleted(Action continuation) { - Interlocked.CompareExchange(ref this._continuation, continuation, null); + Interlocked.CompareExchange(ref this.continuation, continuation, null); } protected void RunContinuation() { IsCompleted = true; - _continuation.Invoke(); + continuation?.Invoke(); } } class ContractTaskAwaiter : ContractTaskAwaiter { - private T _result = default!; + private T result; public new T GetResult() { base.GetResult(); - return _result; + return result; } public void SetResult(T result) { - this._result = result; + this.result = result; RunContinuation(); } diff --git a/src/Neo/SmartContract/ContractTaskMethodBuilder.cs b/src/Neo/SmartContract/ContractTaskMethodBuilder.cs index 2cf6030635..bae1146f25 100644 --- a/src/Neo/SmartContract/ContractTaskMethodBuilder.cs +++ b/src/Neo/SmartContract/ContractTaskMethodBuilder.cs @@ -16,7 +16,7 @@ namespace Neo.SmartContract { sealed class ContractTaskMethodBuilder { - private ContractTask? task; + private ContractTask task; public ContractTask Task => task ??= new ContractTask(); @@ -58,7 +58,7 @@ public void SetStateMachine(IAsyncStateMachine stateMachine) sealed class ContractTaskMethodBuilder { - private ContractTask? task; + private ContractTask task; public ContractTask Task => task ??= new ContractTask(); diff --git a/src/Neo/SmartContract/DeployedContract.cs b/src/Neo/SmartContract/DeployedContract.cs index 4ea6c7845d..0587a029e5 100644 --- a/src/Neo/SmartContract/DeployedContract.cs +++ b/src/Neo/SmartContract/DeployedContract.cs @@ -32,7 +32,7 @@ public DeployedContract(ContractState contract) Script = null; ScriptHash = contract.Hash; - ContractMethodDescriptor? descriptor = contract.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod("verify", -1); if (descriptor is null) throw new NotSupportedException("The smart contract haven't got verify method."); ParameterList = descriptor.Parameters.Select(u => u.Type).ToArray(); diff --git a/src/Neo/SmartContract/ExecutionContextState.cs b/src/Neo/SmartContract/ExecutionContextState.cs index abbdfb3aa1..8b61ff1197 100644 --- a/src/Neo/SmartContract/ExecutionContextState.cs +++ b/src/Neo/SmartContract/ExecutionContextState.cs @@ -22,29 +22,29 @@ public class ExecutionContextState /// /// The script hash of the current context. /// - public UInt160? ScriptHash { get; set; } + public UInt160 ScriptHash { get; set; } /// /// The calling context. /// - public ExecutionContext CallingContext { get; set; } = null!; + public ExecutionContext CallingContext { get; set; } /// /// The script hash of the calling native contract. Used in native contracts only. /// - internal UInt160? NativeCallingScriptHash { get; set; } + internal UInt160 NativeCallingScriptHash { get; set; } /// /// The of the current context. /// - public ContractState Contract { get; set; } = null!; + public ContractState Contract { get; set; } /// /// The of the current context. /// public CallFlags CallFlags { get; set; } = CallFlags.All; - public DataCache Snapshot { get; set; } = null!; + public DataCache Snapshot { get; set; } public int NotificationCount { get; set; } diff --git a/src/Neo/SmartContract/Helper.cs b/src/Neo/SmartContract/Helper.cs index 1b12b2fd28..5045c74717 100644 --- a/src/Neo/SmartContract/Helper.cs +++ b/src/Neo/SmartContract/Helper.cs @@ -20,7 +20,6 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Neo.SmartContract @@ -111,7 +110,7 @@ public static UInt160 GetContractHash(UInt160 sender, uint nefCheckSum, string n /// The script hash of the context. public static UInt160 GetScriptHash(this ExecutionContext context) { - return context.GetState().ScriptHash!; + return context.GetState().ScriptHash; } /// @@ -143,7 +142,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out /// The minimum number of correct signatures that need to be provided in order for the verification to pass. /// The public keys in the account. /// if the contract is a multi-signature contract; otherwise, . - public static bool IsMultiSigContract(ReadOnlySpan script, out int m, [NotNullWhen(true)] out ECPoint[]? points) + public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out ECPoint[] points) { List list = new(); if (IsMultiSigContract(script, out m, out _, list)) @@ -158,7 +157,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, [Not } } - private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List? points) + private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List points) { m = 0; n = 0; int i = 0; @@ -317,13 +316,13 @@ internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings { return false; } - using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot.CreateSnapshot(), null, settings, gas)) + using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.CreateSnapshot(), null, settings, gas)) { if (witness.VerificationScript.Length == 0) { - ContractState? cs = NativeContract.ContractManagement.GetContract(snapshot, hash); + ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash); if (cs is null) return false; - ContractMethodDescriptor? md = cs.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify", -1); if (md?.ReturnType != ContractParameterType.Boolean) return false; engine.LoadContract(cs, md, CallFlags.ReadOnly); } diff --git a/src/Neo/SmartContract/IApplicationEngineProvider.cs b/src/Neo/SmartContract/IApplicationEngineProvider.cs index d39286fda8..ef06c6b92c 100644 --- a/src/Neo/SmartContract/IApplicationEngineProvider.cs +++ b/src/Neo/SmartContract/IApplicationEngineProvider.cs @@ -30,6 +30,6 @@ public interface IApplicationEngineProvider /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic); + ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic); } } diff --git a/src/Neo/SmartContract/IInteroperable.cs b/src/Neo/SmartContract/IInteroperable.cs index d9009625b1..5254898efe 100644 --- a/src/Neo/SmartContract/IInteroperable.cs +++ b/src/Neo/SmartContract/IInteroperable.cs @@ -31,7 +31,7 @@ public interface IInteroperable /// /// The used by the . /// The converted . - StackItem ToStackItem(ReferenceCounter? referenceCounter); + StackItem ToStackItem(ReferenceCounter referenceCounter); public IInteroperable Clone() { diff --git a/src/Neo/SmartContract/InteropDescriptor.cs b/src/Neo/SmartContract/InteropDescriptor.cs index f21ba88b49..29c88f46ed 100644 --- a/src/Neo/SmartContract/InteropDescriptor.cs +++ b/src/Neo/SmartContract/InteropDescriptor.cs @@ -26,7 +26,7 @@ public record InteropDescriptor /// /// The name of the interoperable service. /// - public string Name { get; init; } = null!; + public string Name { get; init; } private uint _hash; /// @@ -45,9 +45,9 @@ public uint Hash /// /// The used to handle the interoperable service. /// - public MethodInfo Handler { get; init; } = null!; + public MethodInfo Handler { get; init; } - private IReadOnlyList? _parameters; + private IReadOnlyList _parameters; /// /// The parameters of the interoperable service. /// diff --git a/src/Neo/SmartContract/InteropParameterDescriptor.cs b/src/Neo/SmartContract/InteropParameterDescriptor.cs index 603c91f3ad..6a65beb93f 100644 --- a/src/Neo/SmartContract/InteropParameterDescriptor.cs +++ b/src/Neo/SmartContract/InteropParameterDescriptor.cs @@ -24,12 +24,12 @@ namespace Neo.SmartContract /// public class InteropParameterDescriptor { - private readonly ValidatorAttribute[] validators = null!; + private readonly ValidatorAttribute[] validators; /// /// The name of the parameter. /// - public string Name { get; } = null!; + public string Name { get; } /// /// The type of the parameter. @@ -56,7 +56,7 @@ public class InteropParameterDescriptor /// public bool IsInterface { get; } - private static readonly Dictionary> converters = new() + private static readonly Dictionary> converters = new() { [typeof(StackItem)] = p => p, [typeof(VM.Types.Pointer)] = p => p, @@ -82,7 +82,7 @@ public class InteropParameterDescriptor internal InteropParameterDescriptor(ParameterInfo parameterInfo) : this(parameterInfo.ParameterType) { - this.Name = parameterInfo.Name!; + this.Name = parameterInfo.Name; this.validators = parameterInfo.GetCustomAttributes(true).ToArray(); } @@ -91,19 +91,19 @@ internal InteropParameterDescriptor(Type type) this.Type = type; if (IsEnum) { - Converter = converters[type.GetEnumUnderlyingType()]!; + Converter = converters[type.GetEnumUnderlyingType()]; } else if (IsArray) { - Converter = converters[type.GetElementType()!]!; + Converter = converters[type.GetElementType()]; } else { IsInterface = !converters.TryGetValue(type, out var converter); if (IsInterface) - Converter = converters[typeof(InteropInterface)]!; + Converter = converters[typeof(InteropInterface)]; else - Converter = converter!; + Converter = converter; } } diff --git a/src/Neo/SmartContract/JsonSerializer.cs b/src/Neo/SmartContract/JsonSerializer.cs index ca2d0eaffd..4d77104a6e 100644 --- a/src/Neo/SmartContract/JsonSerializer.cs +++ b/src/Neo/SmartContract/JsonSerializer.cs @@ -36,7 +36,7 @@ public static class JsonSerializer /// /// The to serialize. /// The serialized object. - public static JToken? Serialize(StackItem item) + public static JToken Serialize(StackItem item) { switch (item) { @@ -71,10 +71,7 @@ public static class JsonSerializer var key = entry.Key.GetString(); var value = Serialize(entry.Value); - if (key != null) - { - ret[key] = value; - } + ret[key] = value; } return ret; @@ -145,7 +142,7 @@ public static byte[] SerializeToByteArray(StackItem item, uint maxSize) writer.WriteEndObject(); break; case JsonTokenType.PropertyName: - writer.WritePropertyName(((StackItem)stack.Pop()!).GetString()!); + writer.WritePropertyName(((StackItem)stack.Pop()).GetString()); break; case Null _: writer.WriteNullValue(); @@ -168,13 +165,13 @@ public static byte[] SerializeToByteArray(StackItem item, uint maxSize) /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ApplicationEngine engine, JToken json, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) + public static StackItem Deserialize(ApplicationEngine engine, JToken json, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) { uint maxStackSize = limits.MaxStackSize; return Deserialize(engine, json, ref maxStackSize, referenceCounter); } - private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref uint maxStackSize, ReferenceCounter? referenceCounter) + private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref uint maxStackSize, ReferenceCounter referenceCounter) { if (maxStackSize-- == 0) throw new FormatException(); switch (json) @@ -186,7 +183,7 @@ private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref case JArray array: { List list = new(array.Count); - foreach (JToken obj in array.Select(p => p != null)) + foreach (JToken obj in array) list.Add(Deserialize(engine, obj, ref maxStackSize, referenceCounter)); return new Array(referenceCounter, list); } @@ -216,7 +213,7 @@ private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref if (maxStackSize-- == 0) throw new FormatException(); var key = entry.Key; - var value = Deserialize(engine, entry.Value!, ref maxStackSize, referenceCounter); + var value = Deserialize(engine, entry.Value, ref maxStackSize, referenceCounter); item[key] = value; } diff --git a/src/Neo/SmartContract/Manifest/ContractAbi.cs b/src/Neo/SmartContract/Manifest/ContractAbi.cs index b9df716799..3660d1a99e 100644 --- a/src/Neo/SmartContract/Manifest/ContractAbi.cs +++ b/src/Neo/SmartContract/Manifest/ContractAbi.cs @@ -25,17 +25,17 @@ namespace Neo.SmartContract.Manifest /// For more details, see NEP-14. public class ContractAbi : IInteroperable { - private IReadOnlyDictionary<(string, int), ContractMethodDescriptor>? methodDictionary; + private IReadOnlyDictionary<(string, int), ContractMethodDescriptor> methodDictionary; /// /// Gets the methods in the ABI. /// - public ContractMethodDescriptor[] Methods { get; set; } = null!; + public ContractMethodDescriptor[] Methods { get; set; } /// /// Gets the events in the ABI. /// - public ContractEventDescriptor[] Events { get; set; } = null!; + public ContractEventDescriptor[] Events { get; set; } void IInteroperable.FromStackItem(StackItem stackItem) { @@ -44,7 +44,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) Events = ((Array)@struct[1]).Select(p => p.ToInteroperable()).ToArray(); } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { @@ -62,8 +62,8 @@ public static ContractAbi FromJson(JObject json) { ContractAbi abi = new() { - Methods = json["methods"].NullExceptionOr().Select(u => ContractMethodDescriptor.FromJson(u.NullExceptionOr())).ToArray(), - Events = json["events"].NullExceptionOr().Select(u => ContractEventDescriptor.FromJson(u.NullExceptionOr())).ToArray() + Methods = ((JArray)json["methods"]).Select(u => ContractMethodDescriptor.FromJson((JObject)u)).ToArray(), + Events = ((JArray)json["events"]).Select(u => ContractEventDescriptor.FromJson((JObject)u)).ToArray() }; if (abi.Methods.Length == 0) throw new FormatException(); return abi; @@ -75,7 +75,7 @@ public static ContractAbi FromJson(JObject json) /// The name of the method. /// The number of parameters of the method. It can be set to -1 to search for the method with the specified name and any number of parameters. /// The method that matches the specified name and number of parameters. If is set to -1, the first method with the specified name will be returned. - public ContractMethodDescriptor? GetMethod(string name, int pcount) + public ContractMethodDescriptor GetMethod(string name, int pcount) { if (pcount < -1 || pcount > ushort.MaxValue) throw new ArgumentOutOfRangeException(nameof(pcount)); if (pcount >= 0) diff --git a/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs index 7a637c12cc..90227dd78d 100644 --- a/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs @@ -9,7 +9,6 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo.IO; using Neo.Json; using Neo.VM; using Neo.VM.Types; @@ -27,21 +26,21 @@ public class ContractEventDescriptor : IInteroperable /// /// The name of the event or method. /// - public string Name { get; set; } = null!; + public string Name { get; set; } /// /// The parameters of the event or method. /// - public ContractParameterDefinition[] Parameters { get; set; } = null!; + public ContractParameterDefinition[] Parameters { get; set; } public virtual void FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; - Name = @struct[0].GetString()!; + Name = @struct[0].GetString(); Parameters = ((Array)@struct[1]).Select(p => p.ToInteroperable()).ToArray(); } - public virtual StackItem ToStackItem(ReferenceCounter? referenceCounter) + public virtual StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { @@ -59,8 +58,8 @@ public static ContractEventDescriptor FromJson(JObject json) { ContractEventDescriptor descriptor = new() { - Name = json["name"]!.GetString(), - Parameters = json["parameters"].NullExceptionOr().Select(u => ContractParameterDefinition.FromJson(u.NullExceptionOr())).ToArray(), + Name = json["name"].GetString(), + Parameters = ((JArray)json["parameters"]).Select(u => ContractParameterDefinition.FromJson((JObject)u)).ToArray(), }; if (string.IsNullOrEmpty(descriptor.Name)) throw new FormatException(); _ = descriptor.Parameters.ToDictionary(p => p.Name); diff --git a/src/Neo/SmartContract/Manifest/ContractGroup.cs b/src/Neo/SmartContract/Manifest/ContractGroup.cs index b24ba00613..231354327c 100644 --- a/src/Neo/SmartContract/Manifest/ContractGroup.cs +++ b/src/Neo/SmartContract/Manifest/ContractGroup.cs @@ -29,12 +29,12 @@ public class ContractGroup : IInteroperable /// /// The public key of the group. /// - public ECPoint PubKey { get; set; } = null!; + public ECPoint PubKey { get; set; } /// /// The signature of the contract hash which can be verified by . /// - public byte[] Signature { get; set; } = null!; + public byte[] Signature { get; set; } void IInteroperable.FromStackItem(StackItem stackItem) { @@ -43,7 +43,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) Signature = @struct[1].GetSpan().ToArray(); } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { PubKey.ToArray(), Signature }; } @@ -57,8 +57,8 @@ public static ContractGroup FromJson(JObject json) { ContractGroup group = new() { - PubKey = ECPoint.Parse(json["pubkey"]!.GetString(), ECCurve.Secp256r1), - Signature = Convert.FromBase64String(json["signature"]!.GetString()), + PubKey = ECPoint.Parse(json["pubkey"].GetString(), ECCurve.Secp256r1), + Signature = Convert.FromBase64String(json["signature"].GetString()), }; if (group.Signature.Length != 64) throw new FormatException(); return group; diff --git a/src/Neo/SmartContract/Manifest/ContractManifest.cs b/src/Neo/SmartContract/Manifest/ContractManifest.cs index 7bdb4575aa..078e8fd35e 100644 --- a/src/Neo/SmartContract/Manifest/ContractManifest.cs +++ b/src/Neo/SmartContract/Manifest/ContractManifest.cs @@ -35,47 +35,47 @@ public class ContractManifest : IInteroperable /// /// The name of the contract. /// - public string Name { get; set; } = null!; + public string Name { get; set; } /// /// The groups of the contract. /// - public ContractGroup[] Groups { get; set; } = null!; + public ContractGroup[] Groups { get; set; } /// /// Indicates which standards the contract supports. It can be a list of NEPs. /// - public string[] SupportedStandards { get; set; } = null!; + public string[] SupportedStandards { get; set; } /// /// The ABI of the contract. /// - public ContractAbi Abi { get; set; } = null!; + public ContractAbi Abi { get; set; } /// /// The permissions of the contract. /// - public ContractPermission[] Permissions { get; set; } = null!; + public ContractPermission[] Permissions { get; set; } /// /// The trusted contracts and groups of the contract. /// If a contract is trusted, the user interface will not give any warnings when called by the contract. /// - public WildcardContainer Trusts { get; set; } = null!; + public WildcardContainer Trusts { get; set; } /// /// Custom user data. /// - public JObject? Extra { get; set; } + public JObject Extra { get; set; } void IInteroperable.FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; - Name = @struct[0].GetString().NullExceptionOr(); + Name = @struct[0].GetString(); Groups = ((Array)@struct[1]).Select(p => p.ToInteroperable()).ToArray(); if (((Map)@struct[2]).Count != 0) throw new ArgumentException(null, nameof(stackItem)); - SupportedStandards = @struct[3].NullExceptionOr().Select(p => p.GetString()).ToArray()!; + SupportedStandards = ((Array)@struct[3]).Select(p => p.GetString()).ToArray(); Abi = @struct[4].ToInteroperable(); Permissions = ((Array)@struct[5]).Select(p => p.ToInteroperable()).ToArray(); Trusts = @struct[6] switch @@ -85,10 +85,10 @@ void IInteroperable.FromStackItem(StackItem stackItem) Array array => WildcardContainer.Create(array.Select(ContractPermissionDescriptor.Create).ToArray()), _ => throw new ArgumentException(null, nameof(stackItem)) }; - Extra = (JObject)JToken.Parse(@struct[7].GetSpan())!; + Extra = (JObject)JToken.Parse(@struct[7].GetSpan()); } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { @@ -112,13 +112,13 @@ public static ContractManifest FromJson(JObject json) { ContractManifest manifest = new() { - Name = json["name"]!.GetString(), - Groups = json["groups"].NullExceptionOr().Select(u => ContractGroup.FromJson(u.NullExceptionOr())).ToArray(), - SupportedStandards = json["supportedstandards"].NullExceptionOr().Select(u => u!.GetString()).ToArray(), - Abi = ContractAbi.FromJson(json["abi"].NullExceptionOr()), - Permissions = json["permissions"].NullExceptionOr().Select(u => ContractPermission.FromJson(u.NullExceptionOr())).ToArray(), - Trusts = WildcardContainer.FromJson(json["trusts"]!, u => ContractPermissionDescriptor.FromJson((JString)u)), - Extra = json["extra"].NullExceptionOr() + Name = json["name"].GetString(), + Groups = ((JArray)json["groups"]).Select(u => ContractGroup.FromJson((JObject)u)).ToArray(), + SupportedStandards = ((JArray)json["supportedstandards"]).Select(u => u.GetString()).ToArray(), + Abi = ContractAbi.FromJson((JObject)json["abi"]), + Permissions = ((JArray)json["permissions"]).Select(u => ContractPermission.FromJson((JObject)u)).ToArray(), + Trusts = WildcardContainer.FromJson(json["trusts"], u => ContractPermissionDescriptor.FromJson((JString)u)), + Extra = (JObject)json["extra"] }; if (string.IsNullOrEmpty(manifest.Name)) throw new FormatException(); @@ -141,7 +141,7 @@ public static ContractManifest FromJson(JObject json) public static ContractManifest Parse(ReadOnlySpan json) { if (json.Length > MaxLength) throw new ArgumentException(null, nameof(json)); - return FromJson(JToken.Parse(json).NullExceptionOr()); + return FromJson((JObject)JToken.Parse(json)); } /// diff --git a/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs index 84ee8b2963..cc8d0a16d5 100644 --- a/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs @@ -9,7 +9,6 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo.IO; using Neo.Json; using Neo.VM; using Neo.VM.Types; @@ -48,7 +47,7 @@ public override void FromStackItem(StackItem stackItem) Safe = @struct[4].GetBoolean(); } - public override StackItem ToStackItem(ReferenceCounter? referenceCounter) + public override StackItem ToStackItem(ReferenceCounter referenceCounter) { Struct @struct = (Struct)base.ToStackItem(referenceCounter); @struct.Add((byte)ReturnType); @@ -66,11 +65,11 @@ public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { ContractMethodDescriptor descriptor = new() { - Name = json["name"]!.GetString(), - Parameters = json["parameters"].NullExceptionOr().Select(u => ContractParameterDefinition.FromJson(u.NullExceptionOr())).ToArray(), - ReturnType = Enum.Parse(json["returntype"]!.GetString()), - Offset = json["offset"]!.GetInt32(), - Safe = json["safe"]!.GetBoolean() + Name = json["name"].GetString(), + Parameters = ((JArray)json["parameters"]).Select(u => ContractParameterDefinition.FromJson((JObject)u)).ToArray(), + ReturnType = Enum.Parse(json["returntype"].GetString()), + Offset = json["offset"].GetInt32(), + Safe = json["safe"].GetBoolean() }; if (string.IsNullOrEmpty(descriptor.Name)) throw new FormatException(); _ = descriptor.Parameters.ToDictionary(p => p.Name); diff --git a/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs b/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs index fd7292e345..61906558d0 100644 --- a/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs +++ b/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs @@ -24,7 +24,7 @@ public class ContractParameterDefinition : IInteroperable /// /// The name of the parameter. /// - public string Name { get; set; } = null!; + public string Name { get; set; } /// /// The type of the parameter. It can be any value of except . @@ -34,11 +34,11 @@ public class ContractParameterDefinition : IInteroperable void IInteroperable.FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; - Name = @struct[0].GetString()!; + Name = @struct[0].GetString(); Type = (ContractParameterType)(byte)@struct[1].GetInteger(); } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { Name, (byte)Type }; } @@ -52,8 +52,8 @@ public static ContractParameterDefinition FromJson(JObject json) { ContractParameterDefinition parameter = new() { - Name = json["name"]!.GetString(), - Type = Enum.Parse(json["type"]!.GetString()) + Name = json["name"].GetString(), + Type = Enum.Parse(json["type"].GetString()) }; if (string.IsNullOrEmpty(parameter.Name)) throw new FormatException(); diff --git a/src/Neo/SmartContract/Manifest/ContractPermission.cs b/src/Neo/SmartContract/Manifest/ContractPermission.cs index d9c9d910ed..44c67fd9a1 100644 --- a/src/Neo/SmartContract/Manifest/ContractPermission.cs +++ b/src/Neo/SmartContract/Manifest/ContractPermission.cs @@ -34,14 +34,14 @@ public class ContractPermission : IInteroperable /// If it specifies a public key of a group, then any contract in this group /// may be invoked; If it specifies a wildcard *, then any contract may be invoked. /// - public ContractPermissionDescriptor Contract { get; set; } = null!; + public ContractPermissionDescriptor Contract { get; set; } /// /// Indicates which methods to be called. /// It can also be assigned with a wildcard *. If it is a wildcard *, /// then it means that any method can be called. /// - public WildcardContainer Methods { get; set; } = null!; + public WildcardContainer Methods { get; set; } /// /// A default permission that both and fields are set to wildcard *. @@ -63,16 +63,16 @@ void IInteroperable.FromStackItem(StackItem stackItem) Methods = @struct[1] switch { Null => WildcardContainer.CreateWildcard(), - Array array => WildcardContainer.Create(array.Select(p => p.GetString()!).ToArray()), + Array array => WildcardContainer.Create(array.Select(p => p.GetString()).ToArray()), _ => throw new ArgumentException(null, nameof(stackItem)) }; } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { - Contract.IsWildcard ? StackItem.Null : Contract.IsHash ? Contract.Hash!.ToArray() : Contract.Group!.ToArray(), + Contract.IsWildcard ? StackItem.Null : Contract.IsHash ? Contract.Hash.ToArray() : Contract.Group.ToArray(), Methods.IsWildcard ? StackItem.Null : new Array(referenceCounter, Methods.Select(p => (StackItem)p)), }; } @@ -86,10 +86,10 @@ public static ContractPermission FromJson(JObject json) { ContractPermission permission = new() { - Contract = ContractPermissionDescriptor.FromJson(json["contract"].NullExceptionOr()), - Methods = WildcardContainer.FromJson(json["methods"]!, u => u.GetString()), + Contract = ContractPermissionDescriptor.FromJson((JString)json["contract"]), + Methods = WildcardContainer.FromJson(json["methods"], u => u.GetString()), }; - if (permission.Methods.Any(string.IsNullOrEmpty)) + if (permission.Methods.Any(p => string.IsNullOrEmpty(p))) throw new FormatException(); _ = permission.Methods.ToDictionary(p => p); return permission; @@ -103,7 +103,7 @@ public JObject ToJson() { var json = new JObject(); json["contract"] = Contract.ToJson(); - json["methods"] = Methods.ToJson(p => p!); + json["methods"] = Methods.ToJson(p => p); return json; } @@ -117,7 +117,7 @@ public bool IsAllowed(ContractState targetContract, string targetMethod) { if (Contract.IsHash) { - if (!Contract.Hash!.Equals(targetContract.Hash)) return false; + if (!Contract.Hash.Equals(targetContract.Hash)) return false; } else if (Contract.IsGroup) { diff --git a/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs index 60b642f07c..ce85889423 100644 --- a/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs @@ -25,12 +25,12 @@ public class ContractPermissionDescriptor : IEquatable /// The hash of the contract. It can't be set with . /// - public UInt160? Hash { get; } + public UInt160 Hash { get; } /// /// The group of the contracts. It can't be set with . /// - public ECPoint? Group { get; } + public ECPoint Group { get; } /// /// Indicates whether is set. @@ -47,7 +47,7 @@ public class ContractPermissionDescriptor : IEquatable public bool IsWildcard => Hash is null && Group is null; - private ContractPermissionDescriptor(UInt160? hash, ECPoint? group) + private ContractPermissionDescriptor(UInt160 hash, ECPoint group) { this.Hash = hash; this.Group = group; @@ -102,19 +102,19 @@ public static ContractPermissionDescriptor CreateWildcard() return new ContractPermissionDescriptor(null, null); } - public override bool Equals(object? obj) + public override bool Equals(object obj) { if (obj is not ContractPermissionDescriptor other) return false; return Equals(other); } - public bool Equals(ContractPermissionDescriptor? other) + public bool Equals(ContractPermissionDescriptor other) { if (other is null) return false; - if (this.Equals(other)) return true; + if (this == other) return true; if (IsWildcard == other.IsWildcard) return true; - if (IsHash) return Hash!.Equals(other.Hash); - return IsGroup && Group!.Equals(other.Group); + if (IsHash) return Hash.Equals(other.Hash); + else return Group.Equals(other.Group); } public override int GetHashCode() @@ -145,16 +145,16 @@ public static ContractPermissionDescriptor FromJson(JString json) /// The permission descriptor represented by a JSON object. public JString ToJson() { - if (IsHash) return Hash!.ToString()!; - if (IsGroup) return Group!.ToString()!; - return "*"!; + if (IsHash) return Hash.ToString(); + if (IsGroup) return Group.ToString(); + return "*"; } /// /// Converts the permission descriptor to byte array. /// /// The converted byte array. Or if it is a wildcard. - public byte[]? ToArray() + public byte[] ToArray() { return Hash?.ToArray() ?? Group?.EncodePoint(true); } diff --git a/src/Neo/SmartContract/Manifest/WildCardContainer.cs b/src/Neo/SmartContract/Manifest/WildCardContainer.cs index 56a4df55e8..3002042d04 100644 --- a/src/Neo/SmartContract/Manifest/WildCardContainer.cs +++ b/src/Neo/SmartContract/Manifest/WildCardContainer.cs @@ -23,9 +23,9 @@ namespace Neo.SmartContract.Manifest /// The type of the elements. public class WildcardContainer : IReadOnlyList { - private readonly T[]? _data; + private readonly T[] _data; - public T this[int index] => _data![index]; + public T this[int index] => _data[index]; public int Count => _data?.Length ?? 0; @@ -34,7 +34,7 @@ public class WildcardContainer : IReadOnlyList /// public bool IsWildcard => _data is null; - private WildcardContainer(T[]? data) + private WildcardContainer(T[] data) { _data = data; } @@ -66,7 +66,7 @@ public static WildcardContainer FromJson(JToken json, Func element if (str.Value != "*") throw new FormatException(); return CreateWildcard(); case JArray array: - return Create(array.Select(p => elementSelector(p!)).ToArray()); + return Create(array.Select(p => elementSelector(p)).ToArray()); default: throw new FormatException(); } @@ -87,8 +87,8 @@ public IEnumerator GetEnumerator() /// The list represented by a JSON object. public JToken ToJson(Func elementSelector) { - if (IsWildcard) return "*"!; - return _data!.Select(p => elementSelector(p)).ToArray(); + if (IsWildcard) return "*"; + return _data.Select(p => elementSelector(p)).ToArray(); } } } diff --git a/src/Neo/SmartContract/MethodToken.cs b/src/Neo/SmartContract/MethodToken.cs index 3812c1c742..1b391edd32 100644 --- a/src/Neo/SmartContract/MethodToken.cs +++ b/src/Neo/SmartContract/MethodToken.cs @@ -24,12 +24,12 @@ public class MethodToken : ISerializable /// /// The hash of the contract to be called. /// - public UInt160 Hash = null!; + public UInt160 Hash; /// /// The name of the method to be called. /// - public string Method = null!; + public string Method; /// /// The number of parameters of the method to be called. diff --git a/src/Neo/SmartContract/Native/AccountState.cs b/src/Neo/SmartContract/Native/AccountState.cs index cc0d0b056a..031b37f8eb 100644 --- a/src/Neo/SmartContract/Native/AccountState.cs +++ b/src/Neo/SmartContract/Native/AccountState.cs @@ -30,7 +30,7 @@ public virtual void FromStackItem(StackItem stackItem) Balance = ((Struct)stackItem)[0].GetInteger(); } - public virtual StackItem ToStackItem(ReferenceCounter? referenceCounter) + public virtual StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { Balance }; } diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 13030a8a8e..0f846a37cc 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -39,10 +39,10 @@ internal ContractManagement() { var events = new List(Manifest.Abi.Events) { - new() + new ContractEventDescriptor { Name = "Deploy", - Parameters = new[] + Parameters = new ContractParameterDefinition[] { new ContractParameterDefinition() { @@ -51,10 +51,10 @@ internal ContractManagement() } } }, - new() + new ContractEventDescriptor { Name = "Update", - Parameters = new[] + Parameters = new ContractParameterDefinition[] { new ContractParameterDefinition() { @@ -63,10 +63,10 @@ internal ContractManagement() } } }, - new() + new ContractEventDescriptor { Name = "Destroy", - Parameters = new[] + Parameters = new ContractParameterDefinition[] { new ContractParameterDefinition() { @@ -82,7 +82,7 @@ internal ContractManagement() private int GetNextAvailableId(DataCache snapshot) { - StorageItem item = snapshot.GetAndChange(CreateStorageKey(Prefix_NextAvailableId))!; + StorageItem item = snapshot.GetAndChange(CreateStorageKey(Prefix_NextAvailableId)); int value = (int)(BigInteger)item; item.Add(1); return value; @@ -97,7 +97,7 @@ internal override ContractTask Initialize(ApplicationEngine engine) private async ContractTask OnDeploy(ApplicationEngine engine, ContractState contract, StackItem data, bool update) { - ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod("_deploy", 2); + ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2); if (md is not null) await engine.CallFromNativeContract(Hash, contract.Hash, md.Name, data, update); engine.SendNotification(Hash, update ? "Update" : "Deploy", new VM.Types.Array(engine.ReferenceCounter) { contract.Hash.ToArray() }); @@ -107,7 +107,7 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) { foreach (NativeContract contract in Contracts) { - if (contract.IsInitializeBlock(engine.ProtocolSettings!, engine.PersistingBlock!.Index)) + if (contract.IsInitializeBlock(engine.ProtocolSettings, engine.PersistingBlock.Index)) { engine.Snapshot.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(new ContractState { @@ -125,7 +125,7 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private long GetMinimumDeploymentFee(DataCache snapshot) { - return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_MinimumDeploymentFee)]!; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_MinimumDeploymentFee)]; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -133,7 +133,7 @@ private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) { if (value < 0) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_MinimumDeploymentFee))!.Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_MinimumDeploymentFee)).Set(value); } /// @@ -143,7 +143,7 @@ private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) /// The hash of the deployed contract. /// The deployed contract. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - public ContractState? GetContract(DataCache snapshot, UInt160 hash) + public ContractState GetContract(DataCache snapshot, UInt160 hash) { return snapshot.TryGet(CreateStorageKey(Prefix_Contract).Add(hash))?.GetInteroperable(); } @@ -155,9 +155,9 @@ private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) /// Contract ID. /// The deployed contract. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - public ContractState? GetContractById(DataCache snapshot, int id) + public ContractState GetContractById(DataCache snapshot, int id) { - StorageItem? item = snapshot.TryGet(CreateStorageKey(Prefix_ContractHash).AddBigEndian(id)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_ContractHash).AddBigEndian(id)); if (item is null) return null; var hash = new UInt160(item.Value.Span); return GetContract(snapshot, hash); @@ -273,7 +273,7 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); - var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash!))?.GetInteroperable(); + var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable(); if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}"); if (contract.UpdateCounter == ushort.MaxValue) throw new InvalidOperationException($"The contract reached the maximum number of updates."); @@ -304,9 +304,9 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private void Destroy(ApplicationEngine engine) { - UInt160 hash = engine.CallingScriptHash!; + UInt160 hash = engine.CallingScriptHash; StorageKey ckey = CreateStorageKey(Prefix_Contract).Add(hash); - ContractState? contract = engine.Snapshot.TryGet(ckey)?.GetInteroperable(); + ContractState contract = engine.Snapshot.TryGet(ckey)?.GetInteroperable(); if (contract is null) return; engine.Snapshot.Delete(ckey); engine.Snapshot.Delete(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id)); diff --git a/src/Neo/SmartContract/Native/ContractMethodAttribute.cs b/src/Neo/SmartContract/Native/ContractMethodAttribute.cs index ce0e545f0a..55940f2eb3 100644 --- a/src/Neo/SmartContract/Native/ContractMethodAttribute.cs +++ b/src/Neo/SmartContract/Native/ContractMethodAttribute.cs @@ -16,7 +16,7 @@ namespace Neo.SmartContract.Native [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false)] internal class ContractMethodAttribute : Attribute { - public string? Name { get; init; } + public string Name { get; init; } public CallFlags RequiredCallFlags { get; init; } public long CpuFee { get; init; } public long StorageFee { get; init; } diff --git a/src/Neo/SmartContract/Native/ContractMethodMetadata.cs b/src/Neo/SmartContract/Native/ContractMethodMetadata.cs index 8e90d6e401..83c24191fd 100644 --- a/src/Neo/SmartContract/Native/ContractMethodMetadata.cs +++ b/src/Neo/SmartContract/Native/ContractMethodMetadata.cs @@ -42,7 +42,7 @@ public ContractMethodMetadata(MemberInfo member, ContractMethodAttribute attribu MethodInfo m => m, PropertyInfo p => p.GetMethod, _ => throw new ArgumentException(null, nameof(member)) - } ?? throw new NullReferenceException("Method not found"); + }; ParameterInfo[] parameterInfos = this.Handler.GetParameters(); if (parameterInfos.Length > 0) { diff --git a/src/Neo/SmartContract/Native/FungibleToken.cs b/src/Neo/SmartContract/Native/FungibleToken.cs index bcec1f98c1..1a3a2ac532 100644 --- a/src/Neo/SmartContract/Native/FungibleToken.cs +++ b/src/Neo/SmartContract/Native/FungibleToken.cs @@ -96,11 +96,11 @@ internal async ContractTask Mint(ApplicationEngine engine, UInt160 account, BigI { if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); if (amount.IsZero) return; - StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account), () => new StorageItem(new TState())).NullExceptionOr(); + StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account), () => new StorageItem(new TState())); TState state = storage.GetInteroperable(); OnBalanceChanging(engine, account, state, amount); state.Balance += amount; - storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)).NullExceptionOr(); + storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)); storage.Add(amount); await PostTransfer(engine, null, account, amount, StackItem.Null, callOnPayment); } @@ -110,7 +110,7 @@ internal async ContractTask Burn(ApplicationEngine engine, UInt160 account, BigI if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); if (amount.IsZero) return; StorageKey key = CreateStorageKey(Prefix_Account).Add(account); - StorageItem storage = engine.Snapshot.GetAndChange(key).NullExceptionOr(); + StorageItem storage = engine.Snapshot.GetAndChange(key); TState state = storage.GetInteroperable(); if (state.Balance < amount) throw new InvalidOperationException(); OnBalanceChanging(engine, account, state, -amount); @@ -118,7 +118,7 @@ internal async ContractTask Burn(ApplicationEngine engine, UInt160 account, BigI engine.Snapshot.Delete(key); else state.Balance -= amount; - storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply)).NullExceptionOr(); + storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply)); storage.Add(-amount); await PostTransfer(engine, account, null, amount, StackItem.Null, false); } @@ -131,7 +131,7 @@ internal async ContractTask Burn(ApplicationEngine engine, UInt160 account, BigI [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public virtual BigInteger TotalSupply(DataCache snapshot) { - StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_TotalSupply)); + StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_TotalSupply)); if (storage is null) return BigInteger.Zero; return storage; } @@ -145,7 +145,7 @@ public virtual BigInteger TotalSupply(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public virtual BigInteger BalanceOf(DataCache snapshot, UInt160 account) { - StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); + StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); if (storage is null) return BigInteger.Zero; return storage.GetInteroperable().Balance; } @@ -159,7 +159,7 @@ private protected async ContractTask Transfer(ApplicationEngine engine, UI if (!from.Equals(engine.CallingScriptHash) && !engine.CheckWitnessInternal(from)) return false; StorageKey key_from = CreateStorageKey(Prefix_Account).Add(from); - StorageItem? storage_from = engine.Snapshot.GetAndChange(key_from); + StorageItem storage_from = engine.Snapshot.GetAndChange(key_from); if (amount.IsZero) { if (storage_from != null) @@ -185,7 +185,7 @@ private protected async ContractTask Transfer(ApplicationEngine engine, UI else state_from.Balance -= amount; StorageKey key_to = CreateStorageKey(Prefix_Account).Add(to); - StorageItem storage_to = engine.Snapshot.GetAndChange(key_to, () => new StorageItem(new TState())).NullExceptionOr(); + StorageItem storage_to = engine.Snapshot.GetAndChange(key_to, () => new StorageItem(new TState())); TState state_to = storage_to.GetInteroperable(); OnBalanceChanging(engine, to, state_to, amount); state_to.Balance += amount; @@ -199,7 +199,7 @@ internal virtual void OnBalanceChanging(ApplicationEngine engine, UInt160 accoun { } - private protected virtual async ContractTask PostTransfer(ApplicationEngine engine, UInt160? from, UInt160? to, BigInteger amount, StackItem data, bool callOnPayment) + private protected virtual async ContractTask PostTransfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount, StackItem data, bool callOnPayment) { // Send notification diff --git a/src/Neo/SmartContract/Native/GasToken.cs b/src/Neo/SmartContract/Native/GasToken.cs index df991342ef..0c5a721edc 100644 --- a/src/Neo/SmartContract/Native/GasToken.cs +++ b/src/Neo/SmartContract/Native/GasToken.cs @@ -28,20 +28,19 @@ internal GasToken() internal override ContractTask Initialize(ApplicationEngine engine) { - UInt160 account = Contract.GetBFTAddress(engine.ProtocolSettings!.StandbyValidators); - return Mint(engine, account, engine.ProtocolSettings!.InitialGasDistribution, false); + UInt160 account = Contract.GetBFTAddress(engine.ProtocolSettings.StandbyValidators); + return Mint(engine, account, engine.ProtocolSettings.InitialGasDistribution, false); } internal override async ContractTask OnPersist(ApplicationEngine engine) { long totalNetworkFee = 0; - foreach (Transaction? tx in engine.PersistingBlock!.Transactions) + foreach (Transaction tx in engine.PersistingBlock.Transactions) { - if (tx == null) continue; await Burn(engine, tx.Sender, tx.SystemFee + tx.NetworkFee); totalNetworkFee += tx.NetworkFee; } - ECPoint[] validators = NEO.GetNextBlockValidators(engine.Snapshot, engine.ProtocolSettings!.ValidatorsCount); + ECPoint[] validators = NEO.GetNextBlockValidators(engine.Snapshot, engine.ProtocolSettings.ValidatorsCount); UInt160 primary = Contract.CreateSignatureRedeemScript(validators[engine.PersistingBlock.PrimaryIndex]).ToScriptHash(); await Mint(engine, primary, totalNetworkFee, false); } diff --git a/src/Neo/SmartContract/Native/HashIndexState.cs b/src/Neo/SmartContract/Native/HashIndexState.cs index 0302117cf1..229458ffdd 100644 --- a/src/Neo/SmartContract/Native/HashIndexState.cs +++ b/src/Neo/SmartContract/Native/HashIndexState.cs @@ -17,7 +17,7 @@ namespace Neo.SmartContract.Native { class HashIndexState : IInteroperable { - public UInt256 Hash = null!; + public UInt256 Hash; public uint Index; void IInteroperable.FromStackItem(StackItem stackItem) @@ -27,7 +27,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) Index = (uint)@struct[1].GetInteger(); } - StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) + StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { Hash.ToArray(), Index }; } diff --git a/src/Neo/SmartContract/Native/InteroperableList.cs b/src/Neo/SmartContract/Native/InteroperableList.cs index 178c6be236..e118db7621 100644 --- a/src/Neo/SmartContract/Native/InteroperableList.cs +++ b/src/Neo/SmartContract/Native/InteroperableList.cs @@ -19,7 +19,7 @@ namespace Neo.SmartContract.Native { abstract class InteroperableList : IList, IInteroperable { - private List? list; + private List list; private List List => list ??= new(); public T this[int index] { get => List[index]; set => List[index] = value; } @@ -40,7 +40,7 @@ abstract class InteroperableList : IList, IInteroperable public void Sort() => List.Sort(); protected abstract T ElementFromStackItem(StackItem item); - protected abstract StackItem ElementToStackItem(T element, ReferenceCounter? referenceCounter); + protected abstract StackItem ElementToStackItem(T element, ReferenceCounter referenceCounter); public void FromStackItem(StackItem stackItem) { @@ -51,7 +51,7 @@ public void FromStackItem(StackItem stackItem) } } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Array(referenceCounter, this.Select(p => ElementToStackItem(p, referenceCounter))); } diff --git a/src/Neo/SmartContract/Native/LedgerContract.cs b/src/Neo/SmartContract/Native/LedgerContract.cs index d7c6578fa9..3bb7568adf 100644 --- a/src/Neo/SmartContract/Native/LedgerContract.cs +++ b/src/Neo/SmartContract/Native/LedgerContract.cs @@ -38,8 +38,6 @@ internal LedgerContract() internal override ContractTask OnPersist(ApplicationEngine engine) { - if (engine.PersistingBlock == null) throw new NullReferenceException("engine.PersistingBlock"); - TransactionState[] transactions = engine.PersistingBlock.Transactions.Select(p => new TransactionState { BlockIndex = engine.PersistingBlock.Index, @@ -52,16 +50,16 @@ internal override ContractTask OnPersist(ApplicationEngine engine) { // It's possible that there are previously saved malicious conflict records for this transaction. // If so, then remove it and store the relevant transaction itself. - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(tx.Transaction!.Hash), () => new StorageItem(new TransactionState()))?.FromReplica(new StorageItem(tx)); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(tx.Transaction.Hash), () => new StorageItem(new TransactionState())).FromReplica(new StorageItem(tx)); // Store transaction's conflicits. - var conflictingSigners = tx.Transaction.Signers.Select(s => s.Account).ToArray(); + var conflictingSigners = tx.Transaction.Signers.Select(s => s.Account); foreach (var attr in tx.Transaction.GetAttributes()) { - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash), () => new StorageItem(new TransactionState()))?.FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash), () => new StorageItem(new TransactionState())).FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); foreach (var signer in conflictingSigners) { - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash).Add(signer), () => new StorageItem(new TransactionState()))?.FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash).Add(signer), () => new StorageItem(new TransactionState())).FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); } } } @@ -71,13 +69,9 @@ internal override ContractTask OnPersist(ApplicationEngine engine) internal override ContractTask PostPersist(ApplicationEngine engine) { - HashIndexState state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_CurrentBlock), () => new StorageItem(new HashIndexState()))?.GetInteroperable()!; - if (engine.PersistingBlock != null) - { - state.Hash = engine.PersistingBlock.Hash; - state.Index = engine.PersistingBlock.Index; - } - + HashIndexState state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_CurrentBlock), () => new StorageItem(new HashIndexState())).GetInteroperable(); + state.Hash = engine.PersistingBlock.Hash; + state.Index = engine.PersistingBlock.Index; return ContractTask.CompletedTask; } @@ -99,9 +93,9 @@ private bool IsTraceableBlock(DataCache snapshot, uint index, uint maxTraceableB /// The snapshot used to read data. /// The index of the block. /// The hash of the block. - public UInt256? GetBlockHash(DataCache snapshot, uint index) + public UInt256 GetBlockHash(DataCache snapshot, uint index) { - StorageItem? item = snapshot.TryGet(CreateStorageKey(Prefix_BlockHash).AddBigEndian(index)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_BlockHash).AddBigEndian(index)); if (item is null) return null; return new UInt256(item.Value.Span); } @@ -114,7 +108,7 @@ private bool IsTraceableBlock(DataCache snapshot, uint index, uint maxTraceableB [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public UInt256 CurrentHash(DataCache snapshot) { - return snapshot[CreateStorageKey(Prefix_CurrentBlock)]!.GetInteroperable().Hash; + return snapshot[CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable().Hash; } /// @@ -125,7 +119,7 @@ public UInt256 CurrentHash(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public uint CurrentIndex(DataCache snapshot) { - return snapshot[CreateStorageKey(Prefix_CurrentBlock)]!.GetInteroperable().Index; + return snapshot[CreateStorageKey(Prefix_CurrentBlock)].GetInteroperable().Index; } /// @@ -184,17 +178,17 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerableThe snapshot used to read data. /// The hash of the block. /// The trimmed block. - public TrimmedBlock? GetTrimmedBlock(DataCache snapshot, UInt256 hash) + public TrimmedBlock GetTrimmedBlock(DataCache snapshot, UInt256 hash) { - StorageItem? item = snapshot.TryGet(CreateStorageKey(Prefix_Block).Add(hash)); + StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_Block).Add(hash)); if (item is null) return null; return item.Value.AsSerializable(); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - private TrimmedBlock? GetBlock(ApplicationEngine engine, byte[] indexOrHash) + private TrimmedBlock GetBlock(ApplicationEngine engine, byte[] indexOrHash) { - UInt256? hash; + UInt256 hash; if (indexOrHash.Length < UInt256.Length) hash = GetBlockHash(engine.Snapshot, (uint)new BigInteger(indexOrHash)); else if (indexOrHash.Length == UInt256.Length) @@ -202,8 +196,8 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerableThe snapshot used to read data. /// The hash of the block. /// The block with the specified hash. - public Block? GetBlock(DataCache snapshot, UInt256 hash) + public Block GetBlock(DataCache snapshot, UInt256 hash) { - TrimmedBlock? state = GetTrimmedBlock(snapshot, hash); + TrimmedBlock state = GetTrimmedBlock(snapshot, hash); if (state is null) return null; return new Block { Header = state.Header, - Transactions = state.Hashes.Select(p => GetTransaction(snapshot, p)!).ToArray() + Transactions = state.Hashes.Select(p => GetTransaction(snapshot, p)).ToArray() }; } @@ -230,9 +224,9 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerableThe snapshot used to read data. /// The index of the block. /// The block with the specified index. - public Block? GetBlock(DataCache snapshot, uint index) + public Block GetBlock(DataCache snapshot, uint index) { - UInt256? hash = GetBlockHash(snapshot, index); + UInt256 hash = GetBlockHash(snapshot, index); if (hash is null) return null; return GetBlock(snapshot, hash); } @@ -243,7 +237,7 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerableThe snapshot used to read data. /// The hash of the block. /// The block header with the specified hash. - public Header? GetHeader(DataCache snapshot, UInt256 hash) + public Header GetHeader(DataCache snapshot, UInt256 hash) { return GetTrimmedBlock(snapshot, hash)?.Header; } @@ -254,9 +248,9 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerableThe snapshot used to read data. /// The index of the block. /// The block header with the specified index. - public Header? GetHeader(DataCache snapshot, uint index) + public Header GetHeader(DataCache snapshot, uint index) { - UInt256? hash = GetBlockHash(snapshot, index); + UInt256 hash = GetBlockHash(snapshot, index); if (hash is null) return null; return GetHeader(snapshot, hash); } @@ -267,7 +261,7 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerableThe snapshot used to read data. /// The hash of the transaction. /// The with the specified hash. - public TransactionState? GetTransactionState(DataCache snapshot, UInt256 hash) + public TransactionState GetTransactionState(DataCache snapshot, UInt256 hash) { var state = snapshot.TryGet(CreateStorageKey(Prefix_Transaction).Add(hash))?.GetInteroperable(); if (state?.Transaction is null) return null; @@ -280,47 +274,47 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerableThe snapshot used to read data. /// The hash of the transaction. /// The transaction with the specified hash. - public Transaction? GetTransaction(DataCache snapshot, UInt256 hash) + public Transaction GetTransaction(DataCache snapshot, UInt256 hash) { return GetTransactionState(snapshot, hash)?.Transaction; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates, Name = "getTransaction")] - private Transaction? GetTransactionForContract(ApplicationEngine engine, UInt256 hash) + private Transaction GetTransactionForContract(ApplicationEngine engine, UInt256 hash) { - TransactionState? state = GetTransactionState(engine.Snapshot, hash); - if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings!.MaxTraceableBlocks)) return null; + TransactionState state = GetTransactionState(engine.Snapshot, hash); + if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return null; return state.Transaction; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - private Signer[]? GetTransactionSigners(ApplicationEngine engine, UInt256 hash) + private Signer[] GetTransactionSigners(ApplicationEngine engine, UInt256 hash) { - TransactionState? state = GetTransactionState(engine.Snapshot, hash); - if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings!.MaxTraceableBlocks)) return null; - return state.Transaction?.Signers; + TransactionState state = GetTransactionState(engine.Snapshot, hash); + if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return null; + return state.Transaction.Signers; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private VMState GetTransactionVMState(ApplicationEngine engine, UInt256 hash) { - TransactionState? state = GetTransactionState(engine.Snapshot, hash); - if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings!.MaxTraceableBlocks)) return VMState.NONE; + TransactionState state = GetTransactionState(engine.Snapshot, hash); + if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return VMState.NONE; return state.State; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private int GetTransactionHeight(ApplicationEngine engine, UInt256 hash) { - TransactionState? state = GetTransactionState(engine.Snapshot, hash); - if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings!.MaxTraceableBlocks)) return -1; + TransactionState state = GetTransactionState(engine.Snapshot, hash); + if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return -1; return (int)state.BlockIndex; } [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.ReadStates)] - private Transaction? GetTransactionFromBlock(ApplicationEngine engine, byte[] blockIndexOrHash, int txIndex) + private Transaction GetTransactionFromBlock(ApplicationEngine engine, byte[] blockIndexOrHash, int txIndex) { - UInt256? hash; + UInt256 hash; if (blockIndexOrHash.Length < UInt256.Length) hash = GetBlockHash(engine.Snapshot, (uint)new BigInteger(blockIndexOrHash)); else if (blockIndexOrHash.Length == UInt256.Length) @@ -328,8 +322,8 @@ private int GetTransactionHeight(ApplicationEngine engine, UInt256 hash) else throw new ArgumentException(null, nameof(blockIndexOrHash)); if (hash is null) return null; - TrimmedBlock? block = GetTrimmedBlock(engine.Snapshot, hash); - if (block is null || !IsTraceableBlock(engine.Snapshot, block.Index, engine.ProtocolSettings!.MaxTraceableBlocks)) return null; + TrimmedBlock block = GetTrimmedBlock(engine.Snapshot, hash); + if (block is null || !IsTraceableBlock(engine.Snapshot, block.Index, engine.ProtocolSettings.MaxTraceableBlocks)) return null; if (txIndex < 0 || txIndex >= block.Hashes.Length) throw new ArgumentOutOfRangeException(nameof(txIndex)); return GetTransaction(engine.Snapshot, block.Hashes[txIndex]); diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index a3d6193f21..0229582310 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -121,7 +121,7 @@ protected NativeContract() List descriptors = new(); foreach (MemberInfo member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { - ContractMethodAttribute? attribute = member.GetCustomAttribute(); + ContractMethodAttribute attribute = member.GetCustomAttribute(); if (attribute is null) continue; descriptors.Add(new ContractMethodMetadata(member, attribute)); } @@ -223,7 +223,7 @@ private protected KeyBuilder CreateStorageKey(byte prefix) /// /// The hash of the native contract. /// The native contract with the specified hash. - public static NativeContract? GetContract(UInt160 hash) + public static NativeContract GetContract(UInt160 hash) { contractsDictionary.TryGetValue(hash, out var contract); return contract; @@ -235,7 +235,7 @@ internal async void Invoke(ApplicationEngine engine, byte version) { if (version != 0) throw new InvalidOperationException($"The native contract of version {version} is not active."); - ExecutionContext context = engine.CurrentContext ?? throw new InvalidOperationException("No context available."); + ExecutionContext context = engine.CurrentContext; ContractMethodMetadata method = methods[context.InstructionPointer]; ExecutionContextState state = context.GetState(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) @@ -246,7 +246,7 @@ internal async void Invoke(ApplicationEngine engine, byte version) if (method.NeedSnapshot) parameters.Add(engine.Snapshot); for (int i = 0; i < method.Parameters.Length; i++) parameters.Add(engine.Convert(context.EvaluationStack.Peek(i), method.Parameters[i])); - object? returnValue = method.Handler.Invoke(this, parameters.ToArray()); + object returnValue = method.Handler.Invoke(this, parameters.ToArray()); if (returnValue is ContractTask task) { await task; @@ -256,7 +256,7 @@ internal async void Invoke(ApplicationEngine engine, byte version) { context.EvaluationStack.Pop(); } - if (returnValue != null && method.Handler.ReturnType != typeof(void) && method.Handler.ReturnType != typeof(ContractTask)) + if (method.Handler.ReturnType != typeof(void) && method.Handler.ReturnType != typeof(ContractTask)) { context.EvaluationStack.Push(engine.Convert(returnValue)); } diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 8917e9dde9..2fd26d04a7 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -61,10 +61,10 @@ internal NeoToken() var events = new List(Manifest.Abi.Events) { - new() + new ContractEventDescriptor { Name = "CandidateStateChanged", - Parameters = new[] + Parameters = new ContractParameterDefinition[] { new ContractParameterDefinition() { @@ -83,10 +83,10 @@ internal NeoToken() } } }, - new() + new ContractEventDescriptor { Name = "Vote", - Parameters = new[] + Parameters = new ContractParameterDefinition[] { new ContractParameterDefinition() { @@ -122,33 +122,30 @@ public override BigInteger TotalSupply(DataCache snapshot) internal override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { - GasDistribution? distribution = DistributeGas(engine, account, state); + GasDistribution distribution = DistributeGas(engine, account, state); if (distribution is not null) { - var list = engine.CurrentContext?.GetState>(); - list?.Add(distribution); + var list = engine.CurrentContext.GetState>(); + list.Add(distribution); } if (amount.IsZero) return; if (state.VoteTo is null) return; - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount))?.Add(amount); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)).Add(amount); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state.VoteTo); - CandidateState? candidate = engine.Snapshot.GetAndChange(key)?.GetInteroperable(); - if (candidate != null) - { - candidate.Votes += amount; - CheckCandidate(engine.Snapshot, state.VoteTo, candidate); - } + CandidateState candidate = engine.Snapshot.GetAndChange(key).GetInteroperable(); + candidate.Votes += amount; + CheckCandidate(engine.Snapshot, state.VoteTo, candidate); } - private protected override async ContractTask PostTransfer(ApplicationEngine engine, UInt160? from, UInt160? to, BigInteger amount, StackItem data, bool callOnPayment) + private protected override async ContractTask PostTransfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount, StackItem data, bool callOnPayment) { await base.PostTransfer(engine, from, to, amount, data, callOnPayment); - var list = engine.CurrentContext?.GetState>(); - foreach (var distribution in list ?? Enumerable.Empty()) + var list = engine.CurrentContext.GetState>(); + foreach (var distribution in list) await GAS.Mint(engine, distribution.Account, distribution.Amount, callOnPayment); } - private GasDistribution? DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state) + private GasDistribution DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state) { // PersistingBlock is null when running under the debugger if (engine.PersistingBlock is null) return null; @@ -225,23 +222,23 @@ private void CheckCandidate(DataCache snapshot, ECPoint pubkey, CandidateState c internal override ContractTask Initialize(ApplicationEngine engine) { - var cachedCommittee = new CachedCommittee(engine.ProtocolSettings!.StandbyCommittee.Select(p => (p, BigInteger.Zero))); + var cachedCommittee = new CachedCommittee(engine.ProtocolSettings.StandbyCommittee.Select(p => (p, BigInteger.Zero))); engine.Snapshot.Add(CreateStorageKey(Prefix_Committee), new StorageItem(cachedCommittee)); engine.Snapshot.Add(CreateStorageKey(Prefix_VotersCount), new StorageItem(System.Array.Empty())); engine.Snapshot.Add(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(0u), new StorageItem(5 * GAS.Factor)); engine.Snapshot.Add(CreateStorageKey(Prefix_RegisterPrice), new StorageItem(1000 * GAS.Factor)); - return Mint(engine, Contract.GetBFTAddress(engine.ProtocolSettings!.StandbyValidators), TotalAmount, false); + return Mint(engine, Contract.GetBFTAddress(engine.ProtocolSettings.StandbyValidators), TotalAmount, false); } internal override ContractTask OnPersist(ApplicationEngine engine) { // Set next committee - if (engine.PersistingBlock != null && ShouldRefreshCommittee(engine.PersistingBlock.Index, engine.ProtocolSettings!.CommitteeMembersCount)) + if (ShouldRefreshCommittee(engine.PersistingBlock.Index, engine.ProtocolSettings.CommitteeMembersCount)) { - StorageItem? storageItem = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Committee)); - var cachedCommittee = storageItem?.GetInteroperable(); - cachedCommittee?.Clear(); - cachedCommittee?.AddRange(ComputeCommitteeMembers(engine.Snapshot, engine.ProtocolSettings)); + StorageItem storageItem = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Committee)); + var cachedCommittee = storageItem.GetInteroperable(); + cachedCommittee.Clear(); + cachedCommittee.AddRange(ComputeCommitteeMembers(engine.Snapshot, engine.ProtocolSettings)); } return ContractTask.CompletedTask; } @@ -250,9 +247,9 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) { // Distribute GAS for committee - int m = engine.ProtocolSettings!.CommitteeMembersCount; - int n = engine.ProtocolSettings!.ValidatorsCount; - int index = (int)(engine.PersistingBlock!.Index % (uint)m); + int m = engine.ProtocolSettings.CommitteeMembersCount; + int n = engine.ProtocolSettings.ValidatorsCount; + int index = (int)(engine.PersistingBlock.Index % (uint)m); var gasPerBlock = GetGasPerBlock(engine.Snapshot); var committee = GetCommitteeFromCache(engine.Snapshot); var pubkey = committee[index].PublicKey; @@ -272,8 +269,8 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) { BigInteger voterSumRewardPerNEO = factor * voterRewardOfEachCommittee / Votes; StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(PublicKey); - StorageItem? lastRewardPerNeo = engine.Snapshot.GetAndChange(voterRewardKey, () => new StorageItem(BigInteger.Zero)); - lastRewardPerNeo?.Add(voterSumRewardPerNEO); + StorageItem lastRewardPerNeo = engine.Snapshot.GetAndChange(voterRewardKey, () => new StorageItem(BigInteger.Zero)); + lastRewardPerNeo.Add(voterSumRewardPerNEO); } } } @@ -286,9 +283,9 @@ private void SetGasPerBlock(ApplicationEngine engine, BigInteger gasPerBlock) throw new ArgumentOutOfRangeException(nameof(gasPerBlock)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - uint index = engine.PersistingBlock!.Index + 1; - StorageItem? entry = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(index), () => new StorageItem(gasPerBlock)); - entry?.Set(gasPerBlock); + uint index = engine.PersistingBlock.Index + 1; + StorageItem entry = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(index), () => new StorageItem(gasPerBlock)); + entry.Set(gasPerBlock); } /// @@ -308,7 +305,7 @@ private void SetRegisterPrice(ApplicationEngine engine, long registerPrice) if (registerPrice <= 0) throw new ArgumentOutOfRangeException(nameof(registerPrice)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RegisterPrice))?.Set(registerPrice); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RegisterPrice)).Set(registerPrice); } /// @@ -319,7 +316,7 @@ private void SetRegisterPrice(ApplicationEngine engine, long registerPrice) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public long GetRegisterPrice(DataCache snapshot) { - return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_RegisterPrice)]!; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_RegisterPrice)]; } private IEnumerable<(uint Index, BigInteger GasPerBlock)> GetSortedGasRecords(DataCache snapshot, uint end) @@ -340,7 +337,7 @@ public long GetRegisterPrice(DataCache snapshot) [ContractMethod(CpuFee = 1 << 17, RequiredCallFlags = CallFlags.ReadStates)] public BigInteger UnclaimedGas(DataCache snapshot, UInt160 account, uint end) { - StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); + StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); if (storage is null) return BigInteger.Zero; NeoAccountState state = storage.GetInteroperable(); return CalculateBonus(snapshot, state, end); @@ -353,7 +350,7 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) return false; engine.AddGas(GetRegisterPrice(engine.Snapshot)); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); - StorageItem item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState()))!; + StorageItem item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState())); CandidateState state = item.GetInteroperable(); if (state.Registered) return true; state.Registered = true; @@ -369,7 +366,7 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) return false; StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); if (engine.Snapshot.TryGet(key) is null) return true; - StorageItem item = engine.Snapshot.GetAndChange(key)!; + StorageItem item = engine.Snapshot.GetAndChange(key); CandidateState state = item.GetInteroperable(); if (!state.Registered) return true; state.Registered = false; @@ -380,13 +377,13 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) } [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] - private async ContractTask Vote(ApplicationEngine engine, UInt160 account, ECPoint? voteTo) + private async ContractTask Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) { if (!engine.CheckWitnessInternal(account)) return false; - NeoAccountState? state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); + NeoAccountState state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); if (state_account is null) return false; if (state_account.Balance == 0) return false; - CandidateState? validator_new = null; + CandidateState validator_new = null; if (voteTo != null) { validator_new = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(voteTo))?.GetInteroperable(); @@ -395,28 +392,28 @@ private async ContractTask Vote(ApplicationEngine engine, UInt160 account, } if (state_account.VoteTo is null ^ voteTo is null) { - StorageItem item = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount))!; + StorageItem item = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)); if (state_account.VoteTo is null) item.Add(state_account.Balance); else item.Add(-state_account.Balance); } - GasDistribution? gasDistribution = DistributeGas(engine, account, state_account); + GasDistribution gasDistribution = DistributeGas(engine, account, state_account); if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state_account.VoteTo); - StorageItem storage_validator = engine.Snapshot.GetAndChange(key)!; + StorageItem storage_validator = engine.Snapshot.GetAndChange(key); CandidateState state_validator = storage_validator.GetInteroperable(); state_validator.Votes -= state_account.Balance; CheckCandidate(engine.Snapshot, state_account.VoteTo, state_validator); } - if (voteTo != null && voteTo.Equals(state_account.VoteTo)) + if (voteTo != null && voteTo != state_account.VoteTo) { StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(voteTo); var latestGasPerVote = engine.Snapshot.TryGet(voterRewardKey) ?? BigInteger.Zero; state_account.LastGasPerVote = latestGasPerVote; } - ECPoint? from = state_account.VoteTo; + ECPoint from = state_account.VoteTo; state_account.VoteTo = voteTo; if (validator_new != null) @@ -477,8 +474,8 @@ private IIterator GetAllCandidates(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public BigInteger GetCandidateVote(DataCache snapshot, ECPoint pubKey) { - StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubKey)); - CandidateState? state = storage?.GetInteroperable(); + StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubKey)); + CandidateState state = storage?.GetInteroperable(); return state?.Registered == true ? state.Votes : -1; } @@ -500,7 +497,7 @@ public ECPoint[] GetCommittee(DataCache snapshot) /// account /// The state of the account. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - public NeoAccountState? GetAccountState(DataCache snapshot, UInt160 account) + public NeoAccountState GetAccountState(DataCache snapshot, UInt160 account) { return snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); } @@ -518,7 +515,7 @@ public UInt160 GetCommitteeAddress(DataCache snapshot) private CachedCommittee GetCommitteeFromCache(DataCache snapshot) { - return snapshot[CreateStorageKey(Prefix_Committee)]!.GetInteroperable(); + return snapshot[CreateStorageKey(Prefix_Committee)].GetInteroperable(); } /// @@ -534,7 +531,7 @@ public ECPoint[] ComputeNextBlockValidators(DataCache snapshot, ProtocolSettings private IEnumerable<(ECPoint PublicKey, BigInteger Votes)> ComputeCommitteeMembers(DataCache snapshot, ProtocolSettings settings) { - decimal votersCount = (decimal)(BigInteger)snapshot[CreateStorageKey(Prefix_VotersCount)].NullExceptionOr(); + decimal votersCount = (decimal)(BigInteger)snapshot[CreateStorageKey(Prefix_VotersCount)]; decimal voterTurnout = votersCount / (decimal)TotalAmount; var candidates = GetCandidatesInternal(snapshot) .Select(p => (p.PublicKey, p.State.Votes)) @@ -550,7 +547,7 @@ public ECPoint[] ComputeNextBlockValidators(DataCache snapshot, ProtocolSettings [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.ReadStates)] private ECPoint[] GetNextBlockValidators(ApplicationEngine engine) { - return GetNextBlockValidators(engine.Snapshot, engine.ProtocolSettings!.ValidatorsCount); + return GetNextBlockValidators(engine.Snapshot, engine.ProtocolSettings.ValidatorsCount); } /// @@ -581,7 +578,7 @@ public class NeoAccountState : AccountState /// /// The voting target of the account. This field can be . /// - public ECPoint? VoteTo; + public ECPoint VoteTo; public BigInteger LastGasPerVote; @@ -594,7 +591,7 @@ public override void FromStackItem(StackItem stackItem) LastGasPerVote = @struct[3].GetInteger(); } - public override StackItem ToStackItem(ReferenceCounter? referenceCounter) + public override StackItem ToStackItem(ReferenceCounter referenceCounter) { Struct @struct = (Struct)base.ToStackItem(referenceCounter); @struct.Add(BalanceHeight); @@ -616,7 +613,7 @@ public void FromStackItem(StackItem stackItem) Votes = @struct[1].GetInteger(); } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { Registered, Votes }; } @@ -633,7 +630,7 @@ protected override (ECPoint, BigInteger) ElementFromStackItem(StackItem item) return (ECPoint.DecodePoint(@struct[0].GetSpan(), ECCurve.Secp256r1), @struct[1].GetInteger()); } - protected override StackItem ElementToStackItem((ECPoint PublicKey, BigInteger Votes) element, ReferenceCounter? referenceCounter) + protected override StackItem ElementToStackItem((ECPoint PublicKey, BigInteger Votes) element, ReferenceCounter referenceCounter) { return new Struct(referenceCounter) { element.PublicKey.ToArray(), element.Votes }; } @@ -641,7 +638,7 @@ protected override StackItem ElementToStackItem((ECPoint PublicKey, BigInteger V private record GasDistribution { - public UInt160 Account { get; init; } = null!; + public UInt160 Account { get; init; } public BigInteger Amount { get; init; } } } diff --git a/src/Neo/SmartContract/Native/OracleContract.cs b/src/Neo/SmartContract/Native/OracleContract.cs index f21c6262f7..42f41f5720 100644 --- a/src/Neo/SmartContract/Native/OracleContract.cs +++ b/src/Neo/SmartContract/Native/OracleContract.cs @@ -23,7 +23,6 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; -using Array = System.Array; namespace Neo.SmartContract.Native { @@ -46,10 +45,10 @@ internal OracleContract() { var events = new List(Manifest.Abi.Events) { - new() + new ContractEventDescriptor { Name = "OracleRequest", - Parameters = new[] + Parameters = new ContractParameterDefinition[] { new ContractParameterDefinition() { @@ -73,10 +72,10 @@ internal OracleContract() } } }, - new() + new ContractEventDescriptor { Name = "OracleResponse", - Parameters = new[] + Parameters = new ContractParameterDefinition[] { new ContractParameterDefinition() { @@ -101,7 +100,7 @@ private void SetPrice(ApplicationEngine engine, long price) if (price <= 0) throw new ArgumentOutOfRangeException(nameof(price)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Price))?.Set(price); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Price)).Set(price); } /// @@ -112,7 +111,7 @@ private void SetPrice(ApplicationEngine engine, long price) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public long GetPrice(DataCache snapshot) { - return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_Price)]!; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_Price)]; } [ContractMethod(RequiredCallFlags = CallFlags.States | CallFlags.AllowCall | CallFlags.AllowNotify)] @@ -120,23 +119,23 @@ private ContractTask Finish(ApplicationEngine engine) { if (engine.InvocationStack.Count != 2) throw new InvalidOperationException(); if (engine.GetInvocationCounter() != 1) throw new InvalidOperationException(); - Transaction tx = (Transaction)engine.ScriptContainer!; - OracleResponse? response = tx.GetAttribute(); + Transaction tx = (Transaction)engine.ScriptContainer; + OracleResponse response = tx.GetAttribute(); if (response == null) throw new ArgumentException("Oracle response was not found"); - OracleRequest? request = GetRequest(engine.Snapshot, response.Id); + OracleRequest request = GetRequest(engine.Snapshot, response.Id); if (request == null) throw new ArgumentException("Oracle request was not found"); engine.SendNotification(Hash, "OracleResponse", new VM.Types.Array(engine.ReferenceCounter) { response.Id, request.OriginalTxid.ToArray() }); StackItem userData = BinarySerializer.Deserialize(request.UserData, engine.Limits, engine.ReferenceCounter); return engine.CallFromNativeContract(Hash, request.CallbackContract, request.CallbackMethod, request.Url, userData, (int)response.Code, response.Result); } - private UInt256? GetOriginalTxid(ApplicationEngine engine) + private UInt256 GetOriginalTxid(ApplicationEngine engine) { - Transaction tx = (Transaction)engine.ScriptContainer!; - OracleResponse? response = tx.GetAttribute(); + Transaction tx = (Transaction)engine.ScriptContainer; + OracleResponse response = tx.GetAttribute(); if (response is null) return tx.Hash; - OracleRequest? request = GetRequest(engine.Snapshot, response.Id); - return request?.OriginalTxid; + OracleRequest request = GetRequest(engine.Snapshot, response.Id); + return request.OriginalTxid; } /// @@ -145,7 +144,7 @@ private ContractTask Finish(ApplicationEngine engine) /// The snapshot used to read data. /// The id of the request. /// The pending request. Or if no request with the specified id is found. - public OracleRequest? GetRequest(DataCache snapshot, ulong id) + public OracleRequest GetRequest(DataCache snapshot, ulong id) { return snapshot.TryGet(CreateStorageKey(Prefix_Request).AddBigEndian(id))?.GetInteroperable(); } @@ -166,12 +165,12 @@ private ContractTask Finish(ApplicationEngine engine) /// The snapshot used to read data. /// The url of the requests. /// All the requests with the specified url. - public IEnumerable<(ulong, OracleRequest?)> GetRequestsByUrl(DataCache snapshot, string url) + public IEnumerable<(ulong, OracleRequest)> GetRequestsByUrl(DataCache snapshot, string url) { - IdList? list = snapshot.TryGet(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)))?.GetInteroperable(); + IdList list = snapshot.TryGet(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)))?.GetInteroperable(); if (list is null) yield break; foreach (ulong id in list) - yield return (id, snapshot[CreateStorageKey(Prefix_Request).AddBigEndian(id)]?.GetInteroperable()); + yield return (id, snapshot[CreateStorageKey(Prefix_Request).AddBigEndian(id)].GetInteroperable()); } private static byte[] GetUrlHash(string url) @@ -188,27 +187,27 @@ internal override ContractTask Initialize(ApplicationEngine engine) internal override async ContractTask PostPersist(ApplicationEngine engine) { - (UInt160 Account, BigInteger GAS)[]? nodes = null; - foreach (Transaction? tx in engine.PersistingBlock?.Transactions ?? Array.Empty()) + (UInt160 Account, BigInteger GAS)[] nodes = null; + foreach (Transaction tx in engine.PersistingBlock.Transactions) { //Filter the response transactions - OracleResponse? response = tx.GetAttribute(); + OracleResponse response = tx.GetAttribute(); if (response is null) continue; //Remove the request from storage StorageKey key = CreateStorageKey(Prefix_Request).AddBigEndian(response.Id); - OracleRequest? request = engine.Snapshot.TryGet(key)?.GetInteroperable(); + OracleRequest request = engine.Snapshot.TryGet(key)?.GetInteroperable(); if (request == null) continue; engine.Snapshot.Delete(key); //Remove the id from IdList key = CreateStorageKey(Prefix_IdList).Add(GetUrlHash(request.Url)); - IdList? list = engine.Snapshot.GetAndChange(key)?.GetInteroperable(); - if (list != null && !list.Remove(response.Id)) throw new InvalidOperationException(); - if (list != null && list.Count == 0) engine.Snapshot.Delete(key); + IdList list = engine.Snapshot.GetAndChange(key).GetInteroperable(); + if (!list.Remove(response.Id)) throw new InvalidOperationException(); + if (list.Count == 0) engine.Snapshot.Delete(key); //Mint GAS for oracle nodes - nodes ??= RoleManagement.GetDesignatedByRole(engine.Snapshot, Role.Oracle, engine.PersistingBlock!.Index).Select(p => (Contract.CreateSignatureRedeemScript(p).ToScriptHash(), BigInteger.Zero)).ToArray(); + nodes ??= RoleManagement.GetDesignatedByRole(engine.Snapshot, Role.Oracle, engine.PersistingBlock.Index).Select(p => (Contract.CreateSignatureRedeemScript(p).ToScriptHash(), BigInteger.Zero)).ToArray(); if (nodes.Length > 0) { int index = (int)(response.Id % (ulong)nodes.Length); @@ -226,7 +225,7 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) } [ContractMethod(RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] - private async ContractTask Request(ApplicationEngine engine, string url, string? filter, string callback, StackItem userData, long gasForResponse) + private async ContractTask Request(ApplicationEngine engine, string url, string filter, string callback, StackItem userData, long gasForResponse) { //Check the arguments if (Utility.StrictUTF8.GetByteCount(url) > MaxUrlLength @@ -242,37 +241,37 @@ private async ContractTask Request(ApplicationEngine engine, string url, string? await GAS.Mint(engine, Hash, gasForResponse, false); //Increase the request id - StorageItem item_id = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RequestId)).NullExceptionOr(); + StorageItem item_id = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RequestId)); ulong id = (ulong)(BigInteger)item_id; item_id.Add(1); //Put the request to storage - if (ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash.NotNull()) is null) + if (ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash) is null) throw new InvalidOperationException(); engine.Snapshot.Add(CreateStorageKey(Prefix_Request).AddBigEndian(id), new StorageItem(new OracleRequest { - OriginalTxid = GetOriginalTxid(engine)!, + OriginalTxid = GetOriginalTxid(engine), GasForResponse = gasForResponse, Url = url, Filter = filter, - CallbackContract = engine.CallingScriptHash!, + CallbackContract = engine.CallingScriptHash, CallbackMethod = callback, UserData = BinarySerializer.Serialize(userData, MaxUserDataLength, engine.Limits.MaxStackSize) })); //Add the id to the IdList - var list = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)), () => new StorageItem(new IdList()))?.GetInteroperable(); - if (list?.Count >= 256) + var list = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)), () => new StorageItem(new IdList())).GetInteroperable(); + if (list.Count >= 256) throw new InvalidOperationException("There are too many pending responses for this url"); - list?.Add(id); + list.Add(id); - engine.SendNotification(Hash, "OracleRequest", new VM.Types.Array(engine.ReferenceCounter) { id, engine.CallingScriptHash!.ToArray(), url, filter ?? StackItem.Null }); + engine.SendNotification(Hash, "OracleRequest", new VM.Types.Array(engine.ReferenceCounter) { id, engine.CallingScriptHash.ToArray(), url, filter ?? StackItem.Null }); } [ContractMethod(CpuFee = 1 << 15)] private bool Verify(ApplicationEngine engine) { - Transaction tx = (Transaction)engine.ScriptContainer!; + Transaction tx = (Transaction)engine.ScriptContainer; return tx?.GetAttribute() != null; } @@ -283,7 +282,7 @@ protected override ulong ElementFromStackItem(StackItem item) return (ulong)item.GetInteger(); } - protected override StackItem ElementToStackItem(ulong element, ReferenceCounter? referenceCounter) + protected override StackItem ElementToStackItem(ulong element, ReferenceCounter referenceCounter) { return element; } diff --git a/src/Neo/SmartContract/Native/OracleRequest.cs b/src/Neo/SmartContract/Native/OracleRequest.cs index b8d04cd1c6..d18968ef00 100644 --- a/src/Neo/SmartContract/Native/OracleRequest.cs +++ b/src/Neo/SmartContract/Native/OracleRequest.cs @@ -24,7 +24,7 @@ public class OracleRequest : IInteroperable /// /// The original transaction that sent the related request. /// - public UInt256 OriginalTxid = null!; + public UInt256 OriginalTxid; /// /// The maximum amount of GAS that can be used when executing response callback. @@ -34,41 +34,41 @@ public class OracleRequest : IInteroperable /// /// The url of the request. /// - public string Url = null!; + public string Url; /// /// The filter for the response. /// - public string? Filter; + public string Filter; /// /// The hash of the callback contract. /// - public UInt160 CallbackContract = null!; + public UInt160 CallbackContract; /// /// The name of the callback method. /// - public string CallbackMethod = null!; + public string CallbackMethod; /// /// The user-defined object that will be passed to the callback. /// - public byte[] UserData = null!; + public byte[] UserData; public void FromStackItem(StackItem stackItem) { Array array = (Array)stackItem; OriginalTxid = new UInt256(array[0].GetSpan()); GasForResponse = (long)array[1].GetInteger(); - Url = array[2].GetString()!; + Url = array[2].GetString(); Filter = array[3].GetString(); CallbackContract = new UInt160(array[4].GetSpan()); - CallbackMethod = array[5].GetString()!; + CallbackMethod = array[5].GetString(); UserData = array[6].GetSpan().ToArray(); } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Array(referenceCounter) { diff --git a/src/Neo/SmartContract/Native/PolicyContract.cs b/src/Neo/SmartContract/Native/PolicyContract.cs index e83c969f6f..c633cb7309 100644 --- a/src/Neo/SmartContract/Native/PolicyContract.cs +++ b/src/Neo/SmartContract/Native/PolicyContract.cs @@ -84,7 +84,7 @@ internal override ContractTask Initialize(ApplicationEngine engine) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public long GetFeePerByte(DataCache snapshot) { - return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_FeePerByte)]!; + return (long)(BigInteger)snapshot[CreateStorageKey(Prefix_FeePerByte)]; } /// @@ -95,7 +95,7 @@ public long GetFeePerByte(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public uint GetExecFeeFactor(DataCache snapshot) { - return (uint)(BigInteger)snapshot[CreateStorageKey(Prefix_ExecFeeFactor)]!; + return (uint)(BigInteger)snapshot[CreateStorageKey(Prefix_ExecFeeFactor)]; } /// @@ -106,7 +106,7 @@ public uint GetExecFeeFactor(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public uint GetStoragePrice(DataCache snapshot) { - return (uint)(BigInteger)snapshot[CreateStorageKey(Prefix_StoragePrice)]!; + return (uint)(BigInteger)snapshot[CreateStorageKey(Prefix_StoragePrice)]; } /// @@ -119,7 +119,7 @@ public uint GetStoragePrice(DataCache snapshot) public uint GetAttributeFee(DataCache snapshot, byte attributeType) { if (!Enum.IsDefined(typeof(TransactionAttributeType), attributeType)) throw new InvalidOperationException(); - StorageItem? entry = snapshot.TryGet(CreateStorageKey(Prefix_AttributeFee).Add(attributeType)); + StorageItem entry = snapshot.TryGet(CreateStorageKey(Prefix_AttributeFee).Add(attributeType)); if (entry == null) return DefaultAttributeFee; return (uint)(BigInteger)entry; @@ -144,7 +144,7 @@ private void SetAttributeFee(ApplicationEngine engine, byte attributeType, uint if (value > MaxAttributeFee) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_AttributeFee).Add(attributeType), () => new StorageItem(DefaultAttributeFee))!.Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_AttributeFee).Add(attributeType), () => new StorageItem(DefaultAttributeFee)).Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -152,7 +152,7 @@ private void SetFeePerByte(ApplicationEngine engine, long value) { if (value < 0 || value > 1_00000000) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_FeePerByte))!.Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_FeePerByte)).Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -160,7 +160,7 @@ private void SetExecFeeFactor(ApplicationEngine engine, uint value) { if (value == 0 || value > MaxExecFeeFactor) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_ExecFeeFactor))!.Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_ExecFeeFactor)).Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -168,7 +168,7 @@ private void SetStoragePrice(ApplicationEngine engine, uint value) { if (value == 0 || value > MaxStoragePrice) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_StoragePrice))!.Set(value); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_StoragePrice)).Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] diff --git a/src/Neo/SmartContract/Native/RoleManagement.cs b/src/Neo/SmartContract/Native/RoleManagement.cs index ead9224400..1c2fa0a299 100644 --- a/src/Neo/SmartContract/Native/RoleManagement.cs +++ b/src/Neo/SmartContract/Native/RoleManagement.cs @@ -102,7 +102,7 @@ protected override ECPoint ElementFromStackItem(StackItem item) return ECPoint.DecodePoint(item.GetSpan(), ECCurve.Secp256r1); } - protected override StackItem ElementToStackItem(ECPoint element, ReferenceCounter? referenceCounter) + protected override StackItem ElementToStackItem(ECPoint element, ReferenceCounter referenceCounter) { return element.ToArray(); } diff --git a/src/Neo/SmartContract/Native/StdLib.cs b/src/Neo/SmartContract/Native/StdLib.cs index ba04e9b0d0..3ca836a3ec 100644 --- a/src/Neo/SmartContract/Native/StdLib.cs +++ b/src/Neo/SmartContract/Native/StdLib.cs @@ -50,7 +50,7 @@ private static byte[] JsonSerialize(ApplicationEngine engine, StackItem item) [ContractMethod(CpuFee = 1 << 14)] private static StackItem JsonDeserialize(ApplicationEngine engine, byte[] json) { - return JsonSerializer.Deserialize(engine, JToken.Parse(json, 10)!, engine.Limits, engine.ReferenceCounter); + return JsonSerializer.Deserialize(engine, JToken.Parse(json, 10), engine.Limits, engine.ReferenceCounter); } /// diff --git a/src/Neo/SmartContract/Native/TransactionState.cs b/src/Neo/SmartContract/Native/TransactionState.cs index 1dce060702..b17296b42d 100644 --- a/src/Neo/SmartContract/Native/TransactionState.cs +++ b/src/Neo/SmartContract/Native/TransactionState.cs @@ -31,7 +31,7 @@ public class TransactionState : IInteroperable /// /// The transaction, if the transaction is trimmed this value will be null /// - public Transaction? Transaction; + public Transaction Transaction; /// /// The execution state @@ -75,7 +75,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) State = (VMState)(byte)@struct[2].GetInteger(); } - StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) + StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) { if (Transaction is null) return new Struct(referenceCounter) { BlockIndex }; diff --git a/src/Neo/SmartContract/Native/TrimmedBlock.cs b/src/Neo/SmartContract/Native/TrimmedBlock.cs index 64e6d4f2d8..4cc4c39c0f 100644 --- a/src/Neo/SmartContract/Native/TrimmedBlock.cs +++ b/src/Neo/SmartContract/Native/TrimmedBlock.cs @@ -15,6 +15,7 @@ using Neo.VM.Types; using System; using System.IO; +using System.Linq; namespace Neo.SmartContract.Native { @@ -26,12 +27,12 @@ public class TrimmedBlock : IInteroperable, ISerializable /// /// The header of the block. /// - public Header Header = null!; + public Header Header; /// /// The hashes of the transactions of the block. /// - public UInt256[] Hashes = null!; + public UInt256[] Hashes; /// /// The hash of the block. @@ -78,7 +79,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) throw new NotSupportedException(); } - StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) + StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) { return new VM.Types.Array(referenceCounter, new StackItem[] { diff --git a/src/Neo/SmartContract/NefFile.cs b/src/Neo/SmartContract/NefFile.cs index ed818b0052..1ffa7baf20 100644 --- a/src/Neo/SmartContract/NefFile.cs +++ b/src/Neo/SmartContract/NefFile.cs @@ -51,17 +51,17 @@ public class NefFile : ISerializable /// /// The name and version of the compiler that generated this nef file. /// - public string Compiler { get; set; } = null!; + public string Compiler { get; set; } /// /// The url of the source files. /// - public string Source { get; set; } = null!; + public string Source { get; set; } /// /// The methods that to be called statically. /// - public MethodToken[] Tokens { get; set; } = null!; + public MethodToken[] Tokens { get; set; } /// /// The script of the contract. diff --git a/src/Neo/SmartContract/NotifyEventArgs.cs b/src/Neo/SmartContract/NotifyEventArgs.cs index e4860113b7..0a509101c1 100644 --- a/src/Neo/SmartContract/NotifyEventArgs.cs +++ b/src/Neo/SmartContract/NotifyEventArgs.cs @@ -63,7 +63,7 @@ public void FromStackItem(StackItem stackItem) throw new NotSupportedException(); } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { return new Array(referenceCounter) { diff --git a/src/Neo/SmartContract/StorageItem.cs b/src/Neo/SmartContract/StorageItem.cs index 0383a2303c..0f13c3c1f0 100644 --- a/src/Neo/SmartContract/StorageItem.cs +++ b/src/Neo/SmartContract/StorageItem.cs @@ -23,7 +23,7 @@ namespace Neo.SmartContract public class StorageItem : ISerializable { private ReadOnlyMemory value; - private object? cache; + private object cache; public int Size => Value.GetVarSize(); diff --git a/src/Neo/SmartContract/StorageKey.cs b/src/Neo/SmartContract/StorageKey.cs index 08c5396504..a0136e4456 100644 --- a/src/Neo/SmartContract/StorageKey.cs +++ b/src/Neo/SmartContract/StorageKey.cs @@ -30,7 +30,7 @@ public sealed record StorageKey /// public ReadOnlyMemory Key { get; init; } - private byte[]? cache = null; + private byte[] cache = null; public StorageKey() { } @@ -55,7 +55,7 @@ public static byte[] CreateSearchPrefix(int id, ReadOnlySpan prefix) return buffer; } - public bool Equals(StorageKey? other) + public bool Equals(StorageKey other) { if (other is null) return false; From d91a92c09a7a6e00e5806d4e7451e4ac0835b78f Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 10:16:20 +0800 Subject: [PATCH 07/36] Revert "use nullable crypto" This reverts commit 8145c4dae7e344ad4c50abf3d391f4333cdd974d. --- src/Neo/Cryptography/Crypto.cs | 4 +- src/Neo/Cryptography/ECC/ECFieldElement.cs | 12 ++--- src/Neo/Cryptography/ECC/ECPoint.cs | 58 +++++++++++----------- src/Neo/Cryptography/Helper.cs | 4 +- src/Neo/Cryptography/MerkleTree.cs | 14 +++--- src/Neo/Cryptography/MerkleTreeNode.cs | 8 +-- 6 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/Neo/Cryptography/Crypto.cs b/src/Neo/Cryptography/Crypto.cs index 723fabc8f1..e09b556d82 100644 --- a/src/Neo/Cryptography/Crypto.cs +++ b/src/Neo/Cryptography/Crypto.cs @@ -80,8 +80,8 @@ public static bool VerifySignature(ReadOnlySpan message, ReadOnlySpan public class ECPoint : IComparable, IEquatable, ISerializable { - internal ECFieldElement? X, Y; + internal ECFieldElement X, Y; internal readonly ECCurve Curve; - private byte[]? _compressedPoint, _uncompressedPoint; + private byte[] _compressedPoint, _uncompressedPoint; /// /// Indicates whether it is a point at infinity. @@ -37,15 +37,15 @@ public bool IsInfinity public int Size => IsInfinity ? 1 : 33; - private static ECPointCache pointCacheK1 { get; } = new(1000); - private static ECPointCache pointCacheR1 { get; } = new(1000); + private static IO.Caching.ECPointCache pointCacheK1 { get; } = new(1000); + private static IO.Caching.ECPointCache pointCacheR1 { get; } = new(1000); /// /// Initializes a new instance of the class with the secp256r1 curve. /// public ECPoint() : this(null, null, ECCurve.Secp256r1) { } - internal ECPoint(ECFieldElement? x, ECFieldElement? y, ECCurve curve) + internal ECPoint(ECFieldElement x, ECFieldElement y, ECCurve curve) { if ((x is null ^ y is null) || (curve is null)) throw new ArgumentException("Exactly one of the field elements is null"); @@ -54,13 +54,13 @@ internal ECPoint(ECFieldElement? x, ECFieldElement? y, ECCurve curve) this.Curve = curve; } - public int CompareTo(ECPoint? other) + public int CompareTo(ECPoint other) { - if (!Curve.Equals(other?.Curve)) throw new InvalidOperationException("Invalid comparision for points with different curves"); + if (!Curve.Equals(other.Curve)) throw new InvalidOperationException("Invalid comparision for points with different curves"); if (ReferenceEquals(this, other)) return 0; - int result = X!.CompareTo(other.X); + int result = X.CompareTo(other.X); if (result != 0) return result; - return Y!.CompareTo(other.Y); + return Y.CompareTo(other.Y); } /// @@ -71,7 +71,7 @@ public int CompareTo(ECPoint? other) /// The decoded point. public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve) { - ECPoint? p = null; + ECPoint p = null; switch (encoded[0]) { case 0x02: // compressed @@ -102,7 +102,7 @@ public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve) private static ECPoint DecompressPoint(ReadOnlySpan encoded, ECCurve curve) { - ECPointCache? pointCache; + ECPointCache pointCache = null; if (curve == ECCurve.Secp256k1) pointCache = pointCacheK1; else if (curve == ECCurve.Secp256r1) pointCache = pointCacheR1; else throw new FormatException("Invalid curve " + curve); @@ -123,7 +123,7 @@ private static ECPoint DecompressPoint(int yTilde, BigInteger X1, ECCurve curve) { ECFieldElement x = new(X1, curve); ECFieldElement alpha = x * (x.Square() + curve.A) + curve.B; - ECFieldElement? beta = alpha.Sqrt(); + ECFieldElement beta = alpha.Sqrt(); // // if we can't find a sqrt we haven't got a point on the @@ -187,27 +187,27 @@ public byte[] EncodePoint(bool commpressed) { if (_uncompressedPoint != null) return _uncompressedPoint; data = new byte[65]; - byte[] yBytes = Y!.Value.ToByteArray(isUnsigned: true, isBigEndian: true); + byte[] yBytes = Y.Value.ToByteArray(isUnsigned: true, isBigEndian: true); Buffer.BlockCopy(yBytes, 0, data, 65 - yBytes.Length, yBytes.Length); } - byte[] xBytes = X!.Value.ToByteArray(isUnsigned: true, isBigEndian: true); + byte[] xBytes = X.Value.ToByteArray(isUnsigned: true, isBigEndian: true); Buffer.BlockCopy(xBytes, 0, data, 33 - xBytes.Length, xBytes.Length); - data[0] = commpressed ? Y!.Value.IsEven ? (byte)0x02 : (byte)0x03 : (byte)0x04; + data[0] = commpressed ? Y.Value.IsEven ? (byte)0x02 : (byte)0x03 : (byte)0x04; if (commpressed) _compressedPoint = data; else _uncompressedPoint = data; return data; } - public bool Equals(ECPoint? other) + public bool Equals(ECPoint other) { if (ReferenceEquals(this, other)) return true; if (other is null) return false; if (IsInfinity && other.IsInfinity) return true; if (IsInfinity || other.IsInfinity) return false; - return X!.Equals(other.X) && Y!.Equals(other.Y); + return X.Equals(other.X) && Y.Equals(other.Y); } - public override bool Equals(object? obj) + public override bool Equals(object obj) { return Equals(obj as ECPoint); } @@ -231,7 +231,7 @@ public static ECPoint FromBytes(byte[] bytes, ECCurve curve) public override int GetHashCode() { - return X!.GetHashCode() + Y!.GetHashCode(); + return X.GetHashCode() + Y.GetHashCode(); } internal static ECPoint Multiply(ECPoint p, BigInteger k) @@ -361,7 +361,7 @@ public override string ToString() /// The object used to construct the . /// The parsed point. /// if was converted successfully; otherwise, . - public static bool TryParse(string value, ECCurve curve, out ECPoint? point) + public static bool TryParse(string value, ECCurve curve, out ECPoint point) { try { @@ -379,13 +379,13 @@ internal ECPoint Twice() { if (this.IsInfinity) return this; - if (this.Y?.Value.Sign == 0) + if (this.Y.Value.Sign == 0) return Curve.Infinity; ECFieldElement TWO = new(2, Curve); ECFieldElement THREE = new(3, Curve); - ECFieldElement gamma = (this.X!.Square() * THREE + Curve.A) / (Y! * TWO); + ECFieldElement gamma = (this.X.Square() * THREE + Curve.A) / (Y * TWO); ECFieldElement x3 = gamma.Square() - this.X * TWO; - ECFieldElement y3 = gamma * (this.X - x3) - this.Y!; + ECFieldElement y3 = gamma * (this.X - x3) - this.Y; return new ECPoint(x3, y3, Curve); } @@ -426,7 +426,7 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k) public static ECPoint operator -(ECPoint x) { - return new ECPoint(x.X, -x.Y!, x.Curve); + return new ECPoint(x.X, -x.Y, x.Curve); } public static ECPoint operator *(ECPoint p, byte[] n) @@ -449,15 +449,15 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k) return y; if (y.IsInfinity) return x; - if (x.X!.Equals(y.X)) + if (x.X.Equals(y.X)) { - if (x.Y!.Equals(y.Y)) + if (x.Y.Equals(y.Y)) return x.Twice(); return x.Curve.Infinity; } - ECFieldElement gamma = (y.Y! - x.Y!) / (y.X! - x.X); - ECFieldElement x3 = gamma.Square() - x.X - y.X!; - ECFieldElement y3 = gamma * (x.X - x3) - x.Y!; + ECFieldElement gamma = (y.Y - x.Y) / (y.X - x.X); + ECFieldElement x3 = gamma.Square() - x.X - y.X; + ECFieldElement y3 = gamma * (x.X - x3) - x.Y; return new ECPoint(x3, y3, x.Curve); } diff --git a/src/Neo/Cryptography/Helper.cs b/src/Neo/Cryptography/Helper.cs index c74aff27c9..840b6ebb7b 100644 --- a/src/Neo/Cryptography/Helper.cs +++ b/src/Neo/Cryptography/Helper.cs @@ -153,7 +153,7 @@ public static byte[] Sha256(this Span value) return Sha256((ReadOnlySpan)value); } - public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] nonce, byte[]? associatedData = null) + public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] nonce, byte[] associatedData = null) { if (nonce.Length != 12) throw new ArgumentOutOfRangeException(nameof(nonce)); var tag = new byte[16]; @@ -179,7 +179,7 @@ public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] non return Concat(nonce, cipherBytes, tag); } - public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[]? associatedData = null) + public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[] associatedData = null) { ReadOnlySpan encrypted = encryptedData; var nonce = encrypted[..12]; diff --git a/src/Neo/Cryptography/MerkleTree.cs b/src/Neo/Cryptography/MerkleTree.cs index e2ce925d0e..58d3856b2c 100644 --- a/src/Neo/Cryptography/MerkleTree.cs +++ b/src/Neo/Cryptography/MerkleTree.cs @@ -23,7 +23,7 @@ namespace Neo.Cryptography /// public class MerkleTree { - private readonly MerkleTreeNode? root; + private readonly MerkleTreeNode root; /// /// The depth of the tree. @@ -40,7 +40,7 @@ internal MerkleTree(UInt256[] hashes) this.Depth = depth; } - private static MerkleTreeNode? Build(MerkleTreeNode[] leaves) + private static MerkleTreeNode Build(MerkleTreeNode[] leaves) { if (leaves.Length == 0) return null; if (leaves.Length == 1) return leaves[0]; @@ -63,7 +63,7 @@ internal MerkleTree(UInt256[] hashes) parents[i].RightChild = leaves[i * 2 + 1]; leaves[i * 2 + 1].Parent = parents[i]; } - parents[i].Hash = Concat(buffer, parents[i].LeftChild!.Hash, parents[i].RightChild!.Hash); + parents[i].Hash = Concat(buffer, parents[i].LeftChild.Hash, parents[i].RightChild.Hash); } return Build(parents); //TailCall } @@ -87,7 +87,7 @@ public static UInt256 ComputeRoot(UInt256[] hashes) if (hashes.Length == 0) return UInt256.Zero; if (hashes.Length == 1) return hashes[0]; MerkleTree tree = new(hashes); - return tree.root!.Hash; + return tree.root.Hash; } private static void DepthFirstSearch(MerkleTreeNode node, IList hashes) @@ -100,7 +100,7 @@ private static void DepthFirstSearch(MerkleTreeNode node, IList hashes) else { DepthFirstSearch(node.LeftChild, hashes); - DepthFirstSearch(node.RightChild!, hashes); + DepthFirstSearch(node.RightChild, hashes); } } @@ -145,8 +145,8 @@ private static void Trim(MerkleTreeNode node, int index, int depth, BitArray fla else { Trim(node.LeftChild, index * 2, depth - 1, flags); - Trim(node.RightChild!, index * 2 + 1, depth - 1, flags); - if (node.LeftChild.LeftChild == null && node.RightChild!.RightChild == null) + Trim(node.RightChild, index * 2 + 1, depth - 1, flags); + if (node.LeftChild.LeftChild == null && node.RightChild.RightChild == null) { node.LeftChild = null; node.RightChild = null; diff --git a/src/Neo/Cryptography/MerkleTreeNode.cs b/src/Neo/Cryptography/MerkleTreeNode.cs index 3eb3b84cd4..8fcc2dd5ce 100644 --- a/src/Neo/Cryptography/MerkleTreeNode.cs +++ b/src/Neo/Cryptography/MerkleTreeNode.cs @@ -13,10 +13,10 @@ namespace Neo.Cryptography { internal class MerkleTreeNode { - public UInt256 Hash = null!; - public MerkleTreeNode? Parent; - public MerkleTreeNode? LeftChild; - public MerkleTreeNode? RightChild; + public UInt256 Hash; + public MerkleTreeNode Parent; + public MerkleTreeNode LeftChild; + public MerkleTreeNode RightChild; public bool IsLeaf => LeftChild == null && RightChild == null; From 3db49dc989a692138838a53b97f45d1a6fb78201 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 10:35:13 +0800 Subject: [PATCH 08/36] Revert "Revert "use nullable crypto"" This reverts commit d91a92c09a7a6e00e5806d4e7451e4ac0835b78f. --- src/Neo/Cryptography/Crypto.cs | 4 +- src/Neo/Cryptography/ECC/ECFieldElement.cs | 12 ++--- src/Neo/Cryptography/ECC/ECPoint.cs | 58 +++++++++++----------- src/Neo/Cryptography/Helper.cs | 4 +- src/Neo/Cryptography/MerkleTree.cs | 14 +++--- src/Neo/Cryptography/MerkleTreeNode.cs | 8 +-- 6 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/Neo/Cryptography/Crypto.cs b/src/Neo/Cryptography/Crypto.cs index e09b556d82..723fabc8f1 100644 --- a/src/Neo/Cryptography/Crypto.cs +++ b/src/Neo/Cryptography/Crypto.cs @@ -80,8 +80,8 @@ public static bool VerifySignature(ReadOnlySpan message, ReadOnlySpan public class ECPoint : IComparable, IEquatable, ISerializable { - internal ECFieldElement X, Y; + internal ECFieldElement? X, Y; internal readonly ECCurve Curve; - private byte[] _compressedPoint, _uncompressedPoint; + private byte[]? _compressedPoint, _uncompressedPoint; /// /// Indicates whether it is a point at infinity. @@ -37,15 +37,15 @@ public bool IsInfinity public int Size => IsInfinity ? 1 : 33; - private static IO.Caching.ECPointCache pointCacheK1 { get; } = new(1000); - private static IO.Caching.ECPointCache pointCacheR1 { get; } = new(1000); + private static ECPointCache pointCacheK1 { get; } = new(1000); + private static ECPointCache pointCacheR1 { get; } = new(1000); /// /// Initializes a new instance of the class with the secp256r1 curve. /// public ECPoint() : this(null, null, ECCurve.Secp256r1) { } - internal ECPoint(ECFieldElement x, ECFieldElement y, ECCurve curve) + internal ECPoint(ECFieldElement? x, ECFieldElement? y, ECCurve curve) { if ((x is null ^ y is null) || (curve is null)) throw new ArgumentException("Exactly one of the field elements is null"); @@ -54,13 +54,13 @@ internal ECPoint(ECFieldElement x, ECFieldElement y, ECCurve curve) this.Curve = curve; } - public int CompareTo(ECPoint other) + public int CompareTo(ECPoint? other) { - if (!Curve.Equals(other.Curve)) throw new InvalidOperationException("Invalid comparision for points with different curves"); + if (!Curve.Equals(other?.Curve)) throw new InvalidOperationException("Invalid comparision for points with different curves"); if (ReferenceEquals(this, other)) return 0; - int result = X.CompareTo(other.X); + int result = X!.CompareTo(other.X); if (result != 0) return result; - return Y.CompareTo(other.Y); + return Y!.CompareTo(other.Y); } /// @@ -71,7 +71,7 @@ public int CompareTo(ECPoint other) /// The decoded point. public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve) { - ECPoint p = null; + ECPoint? p = null; switch (encoded[0]) { case 0x02: // compressed @@ -102,7 +102,7 @@ public static ECPoint DecodePoint(ReadOnlySpan encoded, ECCurve curve) private static ECPoint DecompressPoint(ReadOnlySpan encoded, ECCurve curve) { - ECPointCache pointCache = null; + ECPointCache? pointCache; if (curve == ECCurve.Secp256k1) pointCache = pointCacheK1; else if (curve == ECCurve.Secp256r1) pointCache = pointCacheR1; else throw new FormatException("Invalid curve " + curve); @@ -123,7 +123,7 @@ private static ECPoint DecompressPoint(int yTilde, BigInteger X1, ECCurve curve) { ECFieldElement x = new(X1, curve); ECFieldElement alpha = x * (x.Square() + curve.A) + curve.B; - ECFieldElement beta = alpha.Sqrt(); + ECFieldElement? beta = alpha.Sqrt(); // // if we can't find a sqrt we haven't got a point on the @@ -187,27 +187,27 @@ public byte[] EncodePoint(bool commpressed) { if (_uncompressedPoint != null) return _uncompressedPoint; data = new byte[65]; - byte[] yBytes = Y.Value.ToByteArray(isUnsigned: true, isBigEndian: true); + byte[] yBytes = Y!.Value.ToByteArray(isUnsigned: true, isBigEndian: true); Buffer.BlockCopy(yBytes, 0, data, 65 - yBytes.Length, yBytes.Length); } - byte[] xBytes = X.Value.ToByteArray(isUnsigned: true, isBigEndian: true); + byte[] xBytes = X!.Value.ToByteArray(isUnsigned: true, isBigEndian: true); Buffer.BlockCopy(xBytes, 0, data, 33 - xBytes.Length, xBytes.Length); - data[0] = commpressed ? Y.Value.IsEven ? (byte)0x02 : (byte)0x03 : (byte)0x04; + data[0] = commpressed ? Y!.Value.IsEven ? (byte)0x02 : (byte)0x03 : (byte)0x04; if (commpressed) _compressedPoint = data; else _uncompressedPoint = data; return data; } - public bool Equals(ECPoint other) + public bool Equals(ECPoint? other) { if (ReferenceEquals(this, other)) return true; if (other is null) return false; if (IsInfinity && other.IsInfinity) return true; if (IsInfinity || other.IsInfinity) return false; - return X.Equals(other.X) && Y.Equals(other.Y); + return X!.Equals(other.X) && Y!.Equals(other.Y); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as ECPoint); } @@ -231,7 +231,7 @@ public static ECPoint FromBytes(byte[] bytes, ECCurve curve) public override int GetHashCode() { - return X.GetHashCode() + Y.GetHashCode(); + return X!.GetHashCode() + Y!.GetHashCode(); } internal static ECPoint Multiply(ECPoint p, BigInteger k) @@ -361,7 +361,7 @@ public override string ToString() /// The object used to construct the . /// The parsed point. /// if was converted successfully; otherwise, . - public static bool TryParse(string value, ECCurve curve, out ECPoint point) + public static bool TryParse(string value, ECCurve curve, out ECPoint? point) { try { @@ -379,13 +379,13 @@ internal ECPoint Twice() { if (this.IsInfinity) return this; - if (this.Y.Value.Sign == 0) + if (this.Y?.Value.Sign == 0) return Curve.Infinity; ECFieldElement TWO = new(2, Curve); ECFieldElement THREE = new(3, Curve); - ECFieldElement gamma = (this.X.Square() * THREE + Curve.A) / (Y * TWO); + ECFieldElement gamma = (this.X!.Square() * THREE + Curve.A) / (Y! * TWO); ECFieldElement x3 = gamma.Square() - this.X * TWO; - ECFieldElement y3 = gamma * (this.X - x3) - this.Y; + ECFieldElement y3 = gamma * (this.X - x3) - this.Y!; return new ECPoint(x3, y3, Curve); } @@ -426,7 +426,7 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k) public static ECPoint operator -(ECPoint x) { - return new ECPoint(x.X, -x.Y, x.Curve); + return new ECPoint(x.X, -x.Y!, x.Curve); } public static ECPoint operator *(ECPoint p, byte[] n) @@ -449,15 +449,15 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k) return y; if (y.IsInfinity) return x; - if (x.X.Equals(y.X)) + if (x.X!.Equals(y.X)) { - if (x.Y.Equals(y.Y)) + if (x.Y!.Equals(y.Y)) return x.Twice(); return x.Curve.Infinity; } - ECFieldElement gamma = (y.Y - x.Y) / (y.X - x.X); - ECFieldElement x3 = gamma.Square() - x.X - y.X; - ECFieldElement y3 = gamma * (x.X - x3) - x.Y; + ECFieldElement gamma = (y.Y! - x.Y!) / (y.X! - x.X); + ECFieldElement x3 = gamma.Square() - x.X - y.X!; + ECFieldElement y3 = gamma * (x.X - x3) - x.Y!; return new ECPoint(x3, y3, x.Curve); } diff --git a/src/Neo/Cryptography/Helper.cs b/src/Neo/Cryptography/Helper.cs index 840b6ebb7b..c74aff27c9 100644 --- a/src/Neo/Cryptography/Helper.cs +++ b/src/Neo/Cryptography/Helper.cs @@ -153,7 +153,7 @@ public static byte[] Sha256(this Span value) return Sha256((ReadOnlySpan)value); } - public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] nonce, byte[] associatedData = null) + public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] nonce, byte[]? associatedData = null) { if (nonce.Length != 12) throw new ArgumentOutOfRangeException(nameof(nonce)); var tag = new byte[16]; @@ -179,7 +179,7 @@ public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] non return Concat(nonce, cipherBytes, tag); } - public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[] associatedData = null) + public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[]? associatedData = null) { ReadOnlySpan encrypted = encryptedData; var nonce = encrypted[..12]; diff --git a/src/Neo/Cryptography/MerkleTree.cs b/src/Neo/Cryptography/MerkleTree.cs index 58d3856b2c..e2ce925d0e 100644 --- a/src/Neo/Cryptography/MerkleTree.cs +++ b/src/Neo/Cryptography/MerkleTree.cs @@ -23,7 +23,7 @@ namespace Neo.Cryptography /// public class MerkleTree { - private readonly MerkleTreeNode root; + private readonly MerkleTreeNode? root; /// /// The depth of the tree. @@ -40,7 +40,7 @@ internal MerkleTree(UInt256[] hashes) this.Depth = depth; } - private static MerkleTreeNode Build(MerkleTreeNode[] leaves) + private static MerkleTreeNode? Build(MerkleTreeNode[] leaves) { if (leaves.Length == 0) return null; if (leaves.Length == 1) return leaves[0]; @@ -63,7 +63,7 @@ private static MerkleTreeNode Build(MerkleTreeNode[] leaves) parents[i].RightChild = leaves[i * 2 + 1]; leaves[i * 2 + 1].Parent = parents[i]; } - parents[i].Hash = Concat(buffer, parents[i].LeftChild.Hash, parents[i].RightChild.Hash); + parents[i].Hash = Concat(buffer, parents[i].LeftChild!.Hash, parents[i].RightChild!.Hash); } return Build(parents); //TailCall } @@ -87,7 +87,7 @@ public static UInt256 ComputeRoot(UInt256[] hashes) if (hashes.Length == 0) return UInt256.Zero; if (hashes.Length == 1) return hashes[0]; MerkleTree tree = new(hashes); - return tree.root.Hash; + return tree.root!.Hash; } private static void DepthFirstSearch(MerkleTreeNode node, IList hashes) @@ -100,7 +100,7 @@ private static void DepthFirstSearch(MerkleTreeNode node, IList hashes) else { DepthFirstSearch(node.LeftChild, hashes); - DepthFirstSearch(node.RightChild, hashes); + DepthFirstSearch(node.RightChild!, hashes); } } @@ -145,8 +145,8 @@ private static void Trim(MerkleTreeNode node, int index, int depth, BitArray fla else { Trim(node.LeftChild, index * 2, depth - 1, flags); - Trim(node.RightChild, index * 2 + 1, depth - 1, flags); - if (node.LeftChild.LeftChild == null && node.RightChild.RightChild == null) + Trim(node.RightChild!, index * 2 + 1, depth - 1, flags); + if (node.LeftChild.LeftChild == null && node.RightChild!.RightChild == null) { node.LeftChild = null; node.RightChild = null; diff --git a/src/Neo/Cryptography/MerkleTreeNode.cs b/src/Neo/Cryptography/MerkleTreeNode.cs index 8fcc2dd5ce..3eb3b84cd4 100644 --- a/src/Neo/Cryptography/MerkleTreeNode.cs +++ b/src/Neo/Cryptography/MerkleTreeNode.cs @@ -13,10 +13,10 @@ namespace Neo.Cryptography { internal class MerkleTreeNode { - public UInt256 Hash; - public MerkleTreeNode Parent; - public MerkleTreeNode LeftChild; - public MerkleTreeNode RightChild; + public UInt256 Hash = null!; + public MerkleTreeNode? Parent; + public MerkleTreeNode? LeftChild; + public MerkleTreeNode? RightChild; public bool IsLeaf => LeftChild == null && RightChild == null; From 119cc80a0d33e8090e0da3a91ce1babfc0cf4780 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 10:42:48 +0800 Subject: [PATCH 09/36] use nullable ledger --- .../Ledger/Blockchain.ApplicationExecuted.cs | 2 +- src/Neo/Ledger/Blockchain.cs | 34 +++++++------- src/Neo/Ledger/HeaderCache.cs | 6 +-- src/Neo/Ledger/MemoryPool.cs | 45 ++++++++++--------- src/Neo/Ledger/PoolItem.cs | 4 +- src/Neo/Ledger/TransactionRemovedEventArgs.cs | 2 +- 6 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs b/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs index 211ac14117..f55596a267 100644 --- a/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs +++ b/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs @@ -59,7 +59,7 @@ partial class ApplicationExecuted internal ApplicationExecuted(ApplicationEngine engine) { - Transaction = engine.ScriptContainer as Transaction; + Transaction = (engine.ScriptContainer as Transaction)!; Trigger = engine.Trigger; VMState = engine.State; GasConsumed = engine.GasConsumed; diff --git a/src/Neo/Ledger/Blockchain.cs b/src/Neo/Ledger/Blockchain.cs index ff9c8e29d8..1927ae8dd6 100644 --- a/src/Neo/Ledger/Blockchain.cs +++ b/src/Neo/Ledger/Blockchain.cs @@ -48,7 +48,7 @@ public class PersistCompleted /// /// The that is persisted. /// - public Block Block { get; init; } + public Block Block { get; init; } = null!; } /// @@ -59,7 +59,7 @@ public class Import /// /// The blocks to be imported. /// - public IEnumerable Blocks { get; init; } + public IEnumerable Blocks { get; init; } = null!; /// /// Indicates whether the blocks need to be verified when importing. @@ -80,7 +80,7 @@ public class FillMemoryPool /// /// The transactions to be sent. /// - public IEnumerable Transactions { get; init; } + public IEnumerable Transactions { get; init; } = null!; } /// @@ -96,7 +96,7 @@ public class Reverify /// /// The inventories to be re-verified. /// - public IReadOnlyList Inventories { get; init; } + public IReadOnlyList Inventories { get; init; } = null!; } /// @@ -107,7 +107,7 @@ public class RelayResult /// /// The that is relayed. /// - public IInventory Inventory { get; init; } + public IInventory Inventory { get; init; } = null!; /// /// The result. /// @@ -115,17 +115,21 @@ public class RelayResult } internal class Initialize { } - private class UnverifiedBlocksList { public LinkedList Blocks = new(); public HashSet Nodes = new(); } + private class UnverifiedBlocksList + { + public LinkedList Blocks = new(); + public HashSet Nodes = new(); + } - public static event CommittingHandler Committing; - public static event CommittedHandler Committed; + public static event CommittingHandler Committing = null!; + public static event CommittedHandler Committed = null!; private readonly static Script onPersistScript, postPersistScript; private const int MaxTxToReverifyPerIdle = 10; private readonly NeoSystem system; private readonly Dictionary block_cache = new(); private readonly Dictionary block_cache_unverified = new(); - private ImmutableHashSet extensibleWitnessWhiteList; + private ImmutableHashSet? extensibleWitnessWhiteList; static Blockchain() { @@ -261,19 +265,19 @@ private VerifyResult OnNewBlock(Block block) } else { - if (!block.Hash.Equals(system.HeaderCache[block.Index].Hash)) + if (!block.Hash.Equals(system.HeaderCache[block.Index]!.Hash)) return VerifyResult.Invalid; } block_cache.TryAdd(block.Hash, block); if (block.Index == currentHeight + 1) { - Block block_persist = block; + Block? block_persist = block; List blocksToPersistList = new(); while (true) { blocksToPersistList.Add(block_persist); if (block_persist.Index + 1 > headerHeight) break; - UInt256 hash = system.HeaderCache[block_persist.Index + 1].Hash; + UInt256 hash = system.HeaderCache[block_persist.Index + 1]!.Hash; if (!block_cache.TryGetValue(hash, out block_persist)) break; } @@ -439,7 +443,7 @@ private void Persist(Block block) // Warning: Do not write into variable snapshot directly. Write into variable clonedSnapshot and commit instead. foreach (TransactionState transactionState in transactionStates) { - Transaction tx = transactionState.Transaction; + Transaction tx = transactionState.Transaction!; using ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Application, tx, clonedSnapshot, block, system.Settings, tx.SystemFee); engine.LoadScript(tx.Script); transactionState.State = engine.Execute(); @@ -476,8 +480,8 @@ private void Persist(Block block) extensibleWitnessWhiteList = null; block_cache.Remove(block.PrevHash); Context.System.EventStream.Publish(new PersistCompleted { Block = block }); - if (system.HeaderCache.TryRemoveFirst(out Header header)) - Debug.Assert(header.Index == block.Index); + if (system.HeaderCache.TryRemoveFirst(out Header? header)) + Debug.Assert(header?.Index == block.Index); } /// diff --git a/src/Neo/Ledger/HeaderCache.cs b/src/Neo/Ledger/HeaderCache.cs index ac2208011f..ab4140f3e8 100644 --- a/src/Neo/Ledger/HeaderCache.cs +++ b/src/Neo/Ledger/HeaderCache.cs @@ -31,7 +31,7 @@ public sealed class HeaderCache : IDisposable, IEnumerable
///
/// The zero-based index of the to get. /// The at the specified index in the cache. - public Header this[uint index] + public Header? this[uint index] { get { @@ -65,7 +65,7 @@ public Header this[uint index] /// /// Gets the last in the cache. Or if the cache is empty. /// - public Header Last + public Header? Last { get { @@ -100,7 +100,7 @@ internal void Add(Header header) } } - internal bool TryRemoveFirst(out Header header) + internal bool TryRemoveFirst(out Header? header) { readerWriterLock.EnterWriteLock(); try diff --git a/src/Neo/Ledger/MemoryPool.cs b/src/Neo/Ledger/MemoryPool.cs index 23eb711e87..c87a10ae8f 100644 --- a/src/Neo/Ledger/MemoryPool.cs +++ b/src/Neo/Ledger/MemoryPool.cs @@ -16,6 +16,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; @@ -27,8 +28,8 @@ namespace Neo.Ledger ///
public class MemoryPool : IReadOnlyCollection { - public event EventHandler TransactionAdded; - public event EventHandler TransactionRemoved; + public event EventHandler TransactionAdded = null!; + public event EventHandler TransactionRemoved = null!; // Allow a reverified transaction to be rebroadcast if it has been this many block times since last broadcast. private const int BlocksTillRebroadcast = 10; @@ -157,14 +158,14 @@ public bool ContainsKey(UInt256 hash) /// The hash of the to get. /// When this method returns, contains the associated with the specified hash, if the hash is found; otherwise, . /// if the contains a with the specified hash; otherwise, . - public bool TryGetValue(UInt256 hash, out Transaction tx) + public bool TryGetValue(UInt256 hash, out Transaction? tx) { _txRwLock.EnterReadLock(); try { - bool ret = _unsortedTransactions.TryGetValue(hash, out PoolItem item) + bool ret = _unsortedTransactions.TryGetValue(hash, out PoolItem? item) || _unverifiedTransactions.TryGetValue(hash, out item); - tx = ret ? item.Tx : null; + tx = ret ? item!.Tx : null; return ret; } finally @@ -247,13 +248,13 @@ public IEnumerable GetSortedVerifiedTransactions() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static PoolItem GetLowestFeeTransaction(SortedSet verifiedTxSorted, - SortedSet unverifiedTxSorted, out SortedSet sortedPool) + private static PoolItem? GetLowestFeeTransaction(SortedSet verifiedTxSorted, + SortedSet unverifiedTxSorted, out SortedSet? sortedPool) { - PoolItem minItem = unverifiedTxSorted.Min; + PoolItem? minItem = unverifiedTxSorted.Min; sortedPool = minItem != null ? unverifiedTxSorted : null; - PoolItem verifiedMin = verifiedTxSorted.Min; + PoolItem? verifiedMin = verifiedTxSorted.Min; if (verifiedMin == null) return minItem; if (minItem != null && verifiedMin.CompareTo(minItem) >= 0) @@ -265,7 +266,7 @@ private static PoolItem GetLowestFeeTransaction(SortedSet verifiedTxSo return minItem; } - private PoolItem GetLowestFeeTransaction(out Dictionary unsortedTxPool, out SortedSet sortedPool) + private PoolItem? GetLowestFeeTransaction(out Dictionary unsortedTxPool, out SortedSet? sortedPool) { sortedPool = null; @@ -286,7 +287,7 @@ internal bool CanTransactionFitInPool(Transaction tx) { if (Count < Capacity) return true; - return GetLowestFeeTransaction(out _, out _).CompareTo(tx) <= 0; + return GetLowestFeeTransaction(out _, out _)?.CompareTo(tx) <= 0; } internal VerifyResult TryAdd(Transaction tx, DataCache snapshot) @@ -295,7 +296,7 @@ internal VerifyResult TryAdd(Transaction tx, DataCache snapshot) if (_unsortedTransactions.ContainsKey(tx.Hash)) return VerifyResult.AlreadyInPool; - List removedTransactions = null; + List? removedTransactions; _txRwLock.EnterWriteLock(); try { @@ -368,7 +369,7 @@ private bool CheckConflicts(Transaction tx, out List conflictsList) // Step 2: check if unsorted transactions were in `tx`'s Conflicts attributes. foreach (var hash in tx.GetAttributes().Select(p => p.Hash)) { - if (_unsortedTransactions.TryGetValue(hash, out PoolItem unsortedTx)) + if (_unsortedTransactions.TryGetValue(hash, out PoolItem? unsortedTx)) { if (!tx.Signers.Select(p => p.Account).Intersect(unsortedTx.Tx.Signers.Select(p => p.Account)).Any()) return false; conflictsFeeSum += unsortedTx.Tx.NetworkFee; @@ -390,10 +391,10 @@ private List RemoveOverCapacity() List removedTransactions = new(); do { - PoolItem minItem = GetLowestFeeTransaction(out var unsortedPool, out var sortedPool); - + PoolItem? minItem = GetLowestFeeTransaction(out var unsortedPool, out var sortedPool); + if (minItem == null) continue; unsortedPool.Remove(minItem.Tx.Hash); - sortedPool.Remove(minItem); + sortedPool?.Remove(minItem); removedTransactions.Add(minItem.Tx); if (ReferenceEquals(sortedPool, _sortedTransactions)) @@ -407,7 +408,7 @@ private List RemoveOverCapacity() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool TryRemoveVerified(UInt256 hash, out PoolItem item) + private bool TryRemoveVerified(UInt256 hash, [MaybeNullWhen(false)] out PoolItem item) { if (!_unsortedTransactions.TryGetValue(hash, out item)) return false; @@ -425,10 +426,10 @@ private void RemoveConflictsOfVerified(PoolItem item) { foreach (var h in item.Tx.GetAttributes().Select(attr => attr.Hash)) { - if (_conflicts.TryGetValue(h, out HashSet conflicts)) + if (_conflicts.TryGetValue(h, out HashSet? conflicts)) { conflicts.Remove(item.Tx.Hash); - if (conflicts.Count() == 0) + if (!conflicts.Any()) { _conflicts.Remove(h); } @@ -437,7 +438,7 @@ private void RemoveConflictsOfVerified(PoolItem item) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal bool TryRemoveUnVerified(UInt256 hash, out PoolItem item) + internal bool TryRemoveUnVerified(UInt256 hash, out PoolItem? item) { if (!_unverifiedTransactions.TryGetValue(hash, out item)) return false; @@ -473,10 +474,10 @@ internal void UpdatePoolForBlockPersisted(Block block, DataCache snapshot) Dictionary> conflicts = new Dictionary>(); // First remove the transactions verified in the block. // No need to modify VerificationContext as it will be reset afterwards. - foreach (Transaction tx in block.Transactions) + foreach (Transaction? tx in block.Transactions) { if (!TryRemoveVerified(tx.Hash, out _)) TryRemoveUnVerified(tx.Hash, out _); - var conflictingSigners = tx.Signers.Select(s => s.Account); + var conflictingSigners = tx.Signers.Select(s => s.Account).ToArray(); foreach (var h in tx.GetAttributes().Select(a => a.Hash)) { if (conflicts.TryGetValue(h, out var signersList)) diff --git a/src/Neo/Ledger/PoolItem.cs b/src/Neo/Ledger/PoolItem.cs index f8451c1cd9..ee930627e4 100644 --- a/src/Neo/Ledger/PoolItem.cs +++ b/src/Neo/Ledger/PoolItem.cs @@ -44,7 +44,7 @@ internal PoolItem(Transaction tx) LastBroadcastTimestamp = Timestamp; } - public int CompareTo(Transaction otherTx) + public int CompareTo(Transaction? otherTx) { if (otherTx == null) return 1; int ret = (Tx.GetAttribute() != null).CompareTo(otherTx.GetAttribute() != null); @@ -58,7 +58,7 @@ public int CompareTo(Transaction otherTx) return otherTx.Hash.CompareTo(Tx.Hash); } - public int CompareTo(PoolItem otherItem) + public int CompareTo(PoolItem? otherItem) { if (otherItem == null) return 1; return CompareTo(otherItem.Tx); diff --git a/src/Neo/Ledger/TransactionRemovedEventArgs.cs b/src/Neo/Ledger/TransactionRemovedEventArgs.cs index 403b24a195..cc48df2847 100644 --- a/src/Neo/Ledger/TransactionRemovedEventArgs.cs +++ b/src/Neo/Ledger/TransactionRemovedEventArgs.cs @@ -22,7 +22,7 @@ public sealed class TransactionRemovedEventArgs /// /// The s that is being removed. /// - public IReadOnlyCollection Transactions { get; init; } + public IReadOnlyCollection Transactions { get; init; } = null!; /// /// The reason a transaction was removed. From 0143dd185b75c4862f1d54947929d870339a819f Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 11:06:05 +0800 Subject: [PATCH 10/36] update UInt 160 and 256 --- src/Neo/UInt160.cs | 20 ++++++++++---------- src/Neo/UInt256.cs | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Neo/UInt160.cs b/src/Neo/UInt160.cs index 8dfd6bf70c..7540fde946 100644 --- a/src/Neo/UInt160.cs +++ b/src/Neo/UInt160.cs @@ -60,13 +60,13 @@ public unsafe UInt160(ReadOnlySpan value) } } - public int CompareTo(UInt160 other) + public int CompareTo(UInt160? other) { - int result = value3.CompareTo(other.value3); + int result = value3.CompareTo(other?.value3); if (result != 0) return result; - result = value2.CompareTo(other.value2); + result = value2.CompareTo(other?.value2); if (result != 0) return result; - return value1.CompareTo(other.value1); + return value1.CompareTo(other?.value1); } public void Deserialize(ref MemoryReader reader) @@ -76,13 +76,13 @@ public void Deserialize(ref MemoryReader reader) value3 = reader.ReadUInt32(); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(obj, this)) return true; return Equals(obj as UInt160); } - public bool Equals(UInt160 other) + public bool Equals(UInt160? other) { if (other is null) return false; return value1 == other.value1 @@ -104,7 +104,7 @@ public override int GetHashCode() public static UInt160 Parse(string value) { if (!TryParse(value, out var result)) throw new FormatException(); - return result; + return result!; } public void Serialize(BinaryWriter writer) @@ -125,7 +125,7 @@ public override string ToString() /// An represented by a . /// The parsed . /// if an is successfully parsed; otherwise, . - public static bool TryParse(string s, out UInt160 result) + public static bool TryParse(string? s, out UInt160? result) { if (s == null) { @@ -150,14 +150,14 @@ public static bool TryParse(string s, out UInt160 result) return true; } - public static bool operator ==(UInt160 left, UInt160 right) + public static bool operator ==(UInt160? left, UInt160? right) { if (ReferenceEquals(left, right)) return true; if (left is null || right is null) return false; return left.Equals(right); } - public static bool operator !=(UInt160 left, UInt160 right) + public static bool operator !=(UInt160? left, UInt160? right) { return !(left == right); } diff --git a/src/Neo/UInt256.cs b/src/Neo/UInt256.cs index 7c4d996339..23caee74ac 100644 --- a/src/Neo/UInt256.cs +++ b/src/Neo/UInt256.cs @@ -61,15 +61,15 @@ public unsafe UInt256(ReadOnlySpan value) } } - public int CompareTo(UInt256 other) + public int CompareTo(UInt256? other) { - int result = value4.CompareTo(other.value4); + int result = value4.CompareTo(other?.value4); if (result != 0) return result; - result = value3.CompareTo(other.value3); + result = value3.CompareTo(other?.value3); if (result != 0) return result; - result = value2.CompareTo(other.value2); + result = value2.CompareTo(other?.value2); if (result != 0) return result; - return value1.CompareTo(other.value1); + return value1.CompareTo(other?.value1); } public void Deserialize(ref MemoryReader reader) @@ -80,13 +80,13 @@ public void Deserialize(ref MemoryReader reader) value4 = reader.ReadUInt64(); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(obj, this)) return true; return Equals(obj as UInt256); } - public bool Equals(UInt256 other) + public bool Equals(UInt256? other) { if (other is null) return false; return value1 == other.value1 @@ -106,7 +106,7 @@ public override int GetHashCode() /// An represented by a . /// The parsed . /// is not in the correct format. - public static UInt256 Parse(string value) + public static UInt256? Parse(string value) { if (!TryParse(value, out var result)) throw new FormatException(); return result; @@ -131,7 +131,7 @@ public override string ToString() /// An represented by a . /// The parsed . /// if an is successfully parsed; otherwise, . - public static bool TryParse(string s, out UInt256 result) + public static bool TryParse(string? s, out UInt256? result) { if (s == null) { @@ -156,14 +156,14 @@ public static bool TryParse(string s, out UInt256 result) return true; } - public static bool operator ==(UInt256 left, UInt256 right) + public static bool operator ==(UInt256? left, UInt256? right) { if (ReferenceEquals(left, right)) return true; if (left is null || right is null) return false; return left.Equals(right); } - public static bool operator !=(UInt256 left, UInt256 right) + public static bool operator !=(UInt256? left, UInt256? right) { return !(left == right); } From 23511bcc8a527c70f77d6915d395599fd7225833 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 11:09:19 +0800 Subject: [PATCH 11/36] use nullable wallet --- src/Neo/Wallets/AssetDescriptor.cs | 2 +- src/Neo/Wallets/KeyPair.cs | 4 +- src/Neo/Wallets/NEP6/NEP6Account.cs | 40 +++++------ src/Neo/Wallets/NEP6/NEP6Contract.cs | 14 ++-- src/Neo/Wallets/NEP6/NEP6Wallet.cs | 92 +++++++++++++----------- src/Neo/Wallets/NEP6/ScryptParameters.cs | 2 +- src/Neo/Wallets/TransferOutput.cs | 6 +- src/Neo/Wallets/Wallet.cs | 76 ++++++++++---------- src/Neo/Wallets/WalletAccount.cs | 8 +-- 9 files changed, 129 insertions(+), 115 deletions(-) diff --git a/src/Neo/Wallets/AssetDescriptor.cs b/src/Neo/Wallets/AssetDescriptor.cs index 4eb84e938d..dea481f54b 100644 --- a/src/Neo/Wallets/AssetDescriptor.cs +++ b/src/Neo/Wallets/AssetDescriptor.cs @@ -64,7 +64,7 @@ public AssetDescriptor(DataCache snapshot, ProtocolSettings settings, UInt160 as if (engine.State != VMState.HALT) throw new ArgumentException(null, nameof(asset_id)); this.AssetId = asset_id; this.AssetName = contract.Manifest.Name; - this.Symbol = engine.ResultStack.Pop().GetString(); + this.Symbol = engine.ResultStack.Pop().GetString()!; this.Decimals = (byte)engine.ResultStack.Pop().GetInteger(); } diff --git a/src/Neo/Wallets/KeyPair.cs b/src/Neo/Wallets/KeyPair.cs index d0842242d8..3ce758fbd1 100644 --- a/src/Neo/Wallets/KeyPair.cs +++ b/src/Neo/Wallets/KeyPair.cs @@ -59,14 +59,14 @@ public KeyPair(byte[] privateKey) } } - public bool Equals(KeyPair other) + public bool Equals(KeyPair? other) { if (ReferenceEquals(this, other)) return true; if (other is null) return false; return PublicKey.Equals(other.PublicKey); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as KeyPair); } diff --git a/src/Neo/Wallets/NEP6/NEP6Account.cs b/src/Neo/Wallets/NEP6/NEP6Account.cs index 7998b9ea29..f2208fd7f8 100644 --- a/src/Neo/Wallets/NEP6/NEP6Account.cs +++ b/src/Neo/Wallets/NEP6/NEP6Account.cs @@ -18,15 +18,15 @@ namespace Neo.Wallets.NEP6 sealed class NEP6Account : WalletAccount { private readonly NEP6Wallet wallet; - private string nep2key; - private string nep2KeyNew = null; - private KeyPair key; - public JToken Extra; + private string? nep2key; + private string? nep2KeyNew; + private KeyPair? key; + public JToken Extra = null!; public bool Decrypted => nep2key == null || key != null; public override bool HasKey => nep2key != null; - public NEP6Account(NEP6Wallet wallet, UInt160 scriptHash, string nep2key = null) + public NEP6Account(NEP6Wallet wallet, UInt160 scriptHash, string? nep2key = null) : base(scriptHash, wallet.ProtocolSettings) { this.wallet = wallet; @@ -41,17 +41,17 @@ public NEP6Account(NEP6Wallet wallet, UInt160 scriptHash, KeyPair key, string pa public static NEP6Account FromJson(JObject json, NEP6Wallet wallet) { - return new NEP6Account(wallet, json["address"].GetString().ToScriptHash(wallet.ProtocolSettings.AddressVersion), json["key"]?.GetString()) + return new NEP6Account(wallet, json["address"]!.GetString().ToScriptHash(wallet.ProtocolSettings.AddressVersion), json["key"]?.GetString()) { - Label = json["label"]?.GetString(), - IsDefault = json["isDefault"].GetBoolean(), - Lock = json["lock"].GetBoolean(), - Contract = NEP6Contract.FromJson((JObject)json["contract"]), - Extra = json["extra"] + Label = json["label"]!.GetString(), + IsDefault = json["isDefault"]!.GetBoolean(), + Lock = json["lock"]!.GetBoolean(), + Contract = NEP6Contract.FromJson(json["contract"].NullExceptionOr()), + Extra = json["extra"]! }; } - public override KeyPair GetKey() + public override KeyPair? GetKey() { if (nep2key == null) return null; if (key == null) @@ -61,12 +61,12 @@ public override KeyPair GetKey() return key; } - public KeyPair GetKey(string password) + public KeyPair? GetKey(string password) { if (nep2key == null) return null; if (key == null) { - key = new KeyPair(Wallet.GetPrivateKeyFromNEP2(nep2key, password, ProtocolSettings.AddressVersion, wallet.Scrypt.N, wallet.Scrypt.R, wallet.Scrypt.P)); + key = new KeyPair(Wallet.GetPrivateKeyFromNEP2(nep2key, password, ProtocolSettings!.AddressVersion, wallet.Scrypt.N, wallet.Scrypt.R, wallet.Scrypt.P)); } return key; } @@ -74,12 +74,12 @@ public KeyPair GetKey(string password) public JObject ToJson() { JObject account = new(); - account["address"] = ScriptHash.ToAddress(ProtocolSettings.AddressVersion); + account["address"] = ScriptHash.ToAddress(ProtocolSettings!.AddressVersion); account["label"] = Label; account["isDefault"] = IsDefault; account["lock"] = Lock; account["key"] = nep2key; - account["contract"] = ((NEP6Contract)Contract)?.ToJson(); + account["contract"] = Contract.NullExceptionOr().ToJson(); account["extra"] = Extra; return account; } @@ -88,7 +88,7 @@ public bool VerifyPassword(string password) { try { - Wallet.GetPrivateKeyFromNEP2(nep2key, password, ProtocolSettings.AddressVersion, wallet.Scrypt.N, wallet.Scrypt.R, wallet.Scrypt.P); + Wallet.GetPrivateKeyFromNEP2(nep2key.NullExceptionOr(), password, ProtocolSettings!.AddressVersion, wallet.Scrypt.N, wallet.Scrypt.R, wallet.Scrypt.P); return true; } catch (FormatException) @@ -103,7 +103,7 @@ public bool VerifyPassword(string password) internal bool ChangePasswordPrepare(string password_old, string password_new) { if (WatchOnly) return true; - KeyPair keyTemplate = key; + KeyPair? keyTemplate = key; if (nep2key == null) { if (keyTemplate == null) @@ -115,14 +115,14 @@ internal bool ChangePasswordPrepare(string password_old, string password_new) { try { - keyTemplate = new KeyPair(Wallet.GetPrivateKeyFromNEP2(nep2key, password_old, ProtocolSettings.AddressVersion, wallet.Scrypt.N, wallet.Scrypt.R, wallet.Scrypt.P)); + keyTemplate = new KeyPair(Wallet.GetPrivateKeyFromNEP2(nep2key, password_old, ProtocolSettings!.AddressVersion, wallet.Scrypt.N, wallet.Scrypt.R, wallet.Scrypt.P)); } catch { return false; } } - nep2KeyNew = keyTemplate.Export(password_new, ProtocolSettings.AddressVersion, wallet.Scrypt.N, wallet.Scrypt.R, wallet.Scrypt.P); + nep2KeyNew = keyTemplate.Export(password_new, ProtocolSettings!.AddressVersion, wallet.Scrypt.N, wallet.Scrypt.R, wallet.Scrypt.P); return true; } diff --git a/src/Neo/Wallets/NEP6/NEP6Contract.cs b/src/Neo/Wallets/NEP6/NEP6Contract.cs index cecc80be7e..88245adf28 100644 --- a/src/Neo/Wallets/NEP6/NEP6Contract.cs +++ b/src/Neo/Wallets/NEP6/NEP6Contract.cs @@ -18,25 +18,25 @@ namespace Neo.Wallets.NEP6 { internal class NEP6Contract : Contract { - public string[] ParameterNames; + public string[] ParameterNames = null!; public bool Deployed; - public static NEP6Contract FromJson(JObject json) + public static NEP6Contract? FromJson(JObject? json) { if (json == null) return null; return new NEP6Contract { - Script = Convert.FromBase64String(json["script"].AsString()), - ParameterList = ((JArray)json["parameters"]).Select(p => p["type"].GetEnum()).ToArray(), - ParameterNames = ((JArray)json["parameters"]).Select(p => p["name"].AsString()).ToArray(), - Deployed = json["deployed"].AsBoolean() + Script = Convert.FromBase64String(json["script"]!.AsString()), + ParameterList = json["parameters"].NullExceptionOr().SkipWhile(p => p == null).Select(p => p!["type"]!.GetEnum()).ToArray(), + ParameterNames = json["parameters"].NullExceptionOr().SkipWhile(p => p == null).Select(p => p!["name"]!.AsString()).ToArray(), + Deployed = json["deployed"]!.AsBoolean() }; } public JObject ToJson() { JObject contract = new(); - contract["script"] = Convert.ToBase64String(Script); + contract["script"] = Convert.ToBase64String(Script.NotNull()); contract["parameters"] = new JArray(ParameterList.Zip(ParameterNames, (type, name) => { JObject parameter = new(); diff --git a/src/Neo/Wallets/NEP6/NEP6Wallet.cs b/src/Neo/Wallets/NEP6/NEP6Wallet.cs index b600fe6dcd..74b15209cb 100644 --- a/src/Neo/Wallets/NEP6/NEP6Wallet.cs +++ b/src/Neo/Wallets/NEP6/NEP6Wallet.cs @@ -27,18 +27,18 @@ namespace Neo.Wallets.NEP6 /// https://github.com/neo-project/proposals/blob/master/nep-6.mediawiki public class NEP6Wallet : Wallet { - private string password; - private string name; - private Version version; + private string _password; + private string? name; + private Version version = null!; private readonly Dictionary accounts; - private readonly JToken extra; + private readonly JToken? extra; /// /// The parameters of the SCrypt algorithm used for encrypting and decrypting the private keys in the wallet. /// public readonly ScryptParameters Scrypt; - public override string Name => name; + public override string? Name => name; /// /// The version of the wallet standard. It is currently fixed at 1.0 and will be used for functional upgrades in the future. @@ -52,12 +52,12 @@ public class NEP6Wallet : Wallet /// The password of the wallet. /// The to be used by the wallet. /// The name of the wallet. If the wallet is loaded from an existing file, this parameter is ignored. - public NEP6Wallet(string path, string password, ProtocolSettings settings, string name = null) : base(path, settings) + public NEP6Wallet(string path, string password, ProtocolSettings settings, string? name = null) : base(path, settings) { - this.password = password; + this._password = password; if (File.Exists(path)) { - JObject wallet = (JObject)JToken.Parse(File.ReadAllBytes(path)); + JObject wallet = JToken.Parse(File.ReadAllBytes(path)).NullExceptionOr(); LoadFromJson(wallet, out Scrypt, out accounts, out extra); } else @@ -79,18 +79,18 @@ public NEP6Wallet(string path, string password, ProtocolSettings settings, strin /// The JSON object representing the wallet. public NEP6Wallet(string path, string password, ProtocolSettings settings, JObject json) : base(path, settings) { - this.password = password; + this._password = password; LoadFromJson(json, out Scrypt, out accounts, out extra); } - private void LoadFromJson(JObject wallet, out ScryptParameters scrypt, out Dictionary accounts, out JToken extra) + private void LoadFromJson(JObject wallet, out ScryptParameters scrypt, out Dictionary accounts, out JToken? extra) { - this.version = Version.Parse(wallet["version"].AsString()); + this.version = Version.Parse(wallet["version"]!.AsString()); this.name = wallet["name"]?.AsString(); - scrypt = ScryptParameters.FromJson((JObject)wallet["scrypt"]); - accounts = ((JArray)wallet["accounts"]).Select(p => NEP6Account.FromJson((JObject)p, this)).ToDictionary(p => p.ScriptHash); + scrypt = ScryptParameters.FromJson((JObject)wallet["scrypt"].NotNull()); + accounts = wallet["accounts"].NullExceptionOr().Select(p => NEP6Account.FromJson(p.NullExceptionOr(), this)).ToDictionary(p => p.ScriptHash); extra = wallet["extra"]; - if (!VerifyPasswordInternal(password)) + if (!VerifyPasswordInternal(_password)) throw new InvalidOperationException("Wrong password."); } @@ -98,7 +98,7 @@ private void AddAccount(NEP6Account account) { lock (accounts) { - if (accounts.TryGetValue(account.ScriptHash, out NEP6Account account_old)) + if (accounts.TryGetValue(account.ScriptHash, out NEP6Account? account_old)) { account.Label = account_old.Label; account.IsDefault = account_old.IsDefault; @@ -109,7 +109,7 @@ private void AddAccount(NEP6Account account) } else { - NEP6Contract contract_old = (NEP6Contract)account_old.Contract; + NEP6Contract? contract_old = (NEP6Contract?)account_old.Contract; if (contract_old != null) { NEP6Contract contract = (NEP6Contract)account.Contract; @@ -143,7 +143,7 @@ public override WalletAccount CreateAccount(byte[] privateKey) ParameterNames = new[] { "signature" }, Deployed = false }; - NEP6Account account = new(this, contract.ScriptHash, key, password) + NEP6Account account = new(this, contract.ScriptHash, key, _password) { Contract = contract }; @@ -151,7 +151,7 @@ public override WalletAccount CreateAccount(byte[] privateKey) return account; } - public override WalletAccount CreateAccount(Contract contract, KeyPair key = null) + public override WalletAccount CreateAccount(Contract contract, KeyPair? key = null) { if (contract is not NEP6Contract nep6contract) { @@ -167,7 +167,7 @@ public override WalletAccount CreateAccount(Contract contract, KeyPair key = nul if (key == null) account = new NEP6Account(this, nep6contract.ScriptHash); else - account = new NEP6Account(this, nep6contract.ScriptHash, key, password); + account = new NEP6Account(this, nep6contract.ScriptHash, key, _password); account.Contract = nep6contract; AddAccount(account); return account; @@ -187,7 +187,7 @@ public override WalletAccount CreateAccount(UInt160 scriptHash) /// The decrypted private key. internal KeyPair DecryptKey(string nep2key) { - return new KeyPair(GetPrivateKeyFromNEP2(nep2key, password, ProtocolSettings.AddressVersion, Scrypt.N, Scrypt.R, Scrypt.P)); + return new KeyPair(GetPrivateKeyFromNEP2(nep2key, _password, ProtocolSettings!.AddressVersion, Scrypt.N, Scrypt.R, Scrypt.P)); } public override void Delete() @@ -203,11 +203,11 @@ public override bool DeleteAccount(UInt160 scriptHash) } } - public override WalletAccount GetAccount(UInt160 scriptHash) + public override WalletAccount? GetAccount(UInt160 scriptHash) { lock (accounts) { - accounts.TryGetValue(scriptHash, out NEP6Account account); + accounts.TryGetValue(scriptHash, out NEP6Account? account); return account; } } @@ -224,9 +224,9 @@ public override IEnumerable GetAccounts() public override WalletAccount Import(X509Certificate2 cert) { KeyPair key; - using (ECDsa ecdsa = cert.GetECDsaPrivateKey()) + using (ECDsa ecdsa = cert.GetECDsaPrivateKey()!) { - key = new KeyPair(ecdsa.ExportParameters(true).D); + key = new KeyPair(ecdsa.ExportParameters(true).D!); } NEP6Contract contract = new() { @@ -235,7 +235,7 @@ public override WalletAccount Import(X509Certificate2 cert) ParameterNames = new[] { "signature" }, Deployed = false }; - NEP6Account account = new(this, contract.ScriptHash, key, password) + NEP6Account account = new(this, contract.ScriptHash, key, _password) { Contract = contract }; @@ -253,7 +253,7 @@ public override WalletAccount Import(string wif) ParameterNames = new[] { "signature" }, Deployed = false }; - NEP6Account account = new(this, contract.ScriptHash, key, password) + NEP6Account account = new(this, contract.ScriptHash, key, _password) { Contract = contract }; @@ -263,7 +263,7 @@ public override WalletAccount Import(string wif) public override WalletAccount Import(string nep2, string passphrase, int N = 16384, int r = 8, int p = 8) { - KeyPair key = new(GetPrivateKeyFromNEP2(nep2, passphrase, ProtocolSettings.AddressVersion, N, r, p)); + KeyPair key = new(GetPrivateKeyFromNEP2(nep2, passphrase, ProtocolSettings!.AddressVersion, N, r, p)); NEP6Contract contract = new() { Script = Contract.CreateSignatureRedeemScript(key.PublicKey), @@ -286,14 +286,17 @@ public override WalletAccount Import(string nep2, string passphrase, int N = 163 /// public JObject ToJson() { - return new() + lock (accounts) { - ["name"] = name, - ["version"] = version.ToString(), - ["scrypt"] = Scrypt.ToJson(), - ["accounts"] = accounts.Values.Select(p => p.ToJson()).ToArray(), - ["extra"] = extra - }; + return new() + { + ["name"] = name, + ["version"] = version.ToString(), + ["scrypt"] = Scrypt.ToJson(), + ["accounts"] = accounts.Values.Select(p => p.ToJson()).ToArray(), + ["extra"] = extra + }; + } } public override void Save() @@ -303,14 +306,14 @@ public override void Save() public override bool VerifyPassword(string password) { - return this.password == password; + return this._password == password; } private bool VerifyPasswordInternal(string password) { lock (accounts) { - NEP6Account account = accounts.Values.FirstOrDefault(p => !p.Decrypted); + NEP6Account? account = accounts.Values.FirstOrDefault(p => !p.Decrypted); if (account == null) { account = accounts.Values.FirstOrDefault(p => p.HasKey); @@ -351,14 +354,21 @@ public override bool ChangePassword(string oldPassword, string newPassword) } if (succeed) { - foreach (NEP6Account account in accounts.Values) - account.ChangePasswordCommit(); - password = newPassword; + lock (accounts) + { + foreach (NEP6Account account in accounts.Values) + account.ChangePasswordCommit(); + } + + _password = newPassword; } else { - foreach (NEP6Account account in accounts.Values) - account.ChangePasswordRoolback(); + lock (accounts) + { + foreach (NEP6Account account in accounts.Values) + account.ChangePasswordRoolback(); + } } return succeed; } diff --git a/src/Neo/Wallets/NEP6/ScryptParameters.cs b/src/Neo/Wallets/NEP6/ScryptParameters.cs index ab720b3a08..397aeb7aa1 100644 --- a/src/Neo/Wallets/NEP6/ScryptParameters.cs +++ b/src/Neo/Wallets/NEP6/ScryptParameters.cs @@ -58,7 +58,7 @@ public ScryptParameters(int n, int r, int p) /// The converted parameters. public static ScryptParameters FromJson(JObject json) { - return new ScryptParameters((int)json["n"].AsNumber(), (int)json["r"].AsNumber(), (int)json["p"].AsNumber()); + return new ScryptParameters((int)json["n"]!.AsNumber(), (int)json["r"]!.AsNumber(), (int)json["p"]!.AsNumber()); } /// diff --git a/src/Neo/Wallets/TransferOutput.cs b/src/Neo/Wallets/TransferOutput.cs index 7f7d7777a1..7f877b10ea 100644 --- a/src/Neo/Wallets/TransferOutput.cs +++ b/src/Neo/Wallets/TransferOutput.cs @@ -19,7 +19,7 @@ public class TransferOutput /// /// The id of the asset to transfer. /// - public UInt160 AssetId; + public UInt160 AssetId = null!; /// /// The amount of the asset to transfer. @@ -29,11 +29,11 @@ public class TransferOutput /// /// The account to transfer to. /// - public UInt160 ScriptHash; + public UInt160 ScriptHash = null!; /// /// The object to be passed to the transfer method of NEP-17. /// - public object Data; + public object Data = null!; } } diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index ecffe85366..3b2791ff41 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -46,7 +46,7 @@ public abstract class Wallet /// /// The name of the wallet. /// - public abstract string Name { get; } + public abstract string? Name { get; } /// /// The path of the wallet. @@ -86,7 +86,7 @@ public abstract class Wallet /// The contract of the account. /// The private key of the account. /// The created account. - public abstract WalletAccount CreateAccount(Contract contract, KeyPair key = null); + public abstract WalletAccount CreateAccount(Contract contract, KeyPair? key = null); /// /// Creates a watch-only account for the wallet. @@ -112,7 +112,7 @@ public abstract class Wallet /// /// The hash of the account. /// The account with the specified hash. - public abstract WalletAccount GetAccount(UInt160 scriptHash); + public abstract WalletAccount? GetAccount(UInt160 scriptHash); /// /// Gets all the accounts from the wallet. @@ -165,7 +165,7 @@ public WalletAccount CreateAccount() /// The contract of the account. /// The private key of the account. /// The created account. - public WalletAccount CreateAccount(Contract contract, byte[] privateKey) + public WalletAccount CreateAccount(Contract contract, byte[]? privateKey) { if (privateKey == null) return CreateAccount(contract); return CreateAccount(contract, new KeyPair(privateKey)); @@ -237,7 +237,7 @@ public WalletAccount CreateAccount(Contract contract, byte[] privateKey) /// /// The public key of the account. /// The account with the specified public key. - public WalletAccount GetAccount(ECPoint pubkey) + public WalletAccount? GetAccount(ECPoint pubkey) { return GetAccount(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash()); } @@ -246,9 +246,9 @@ public WalletAccount GetAccount(ECPoint pubkey) /// Gets the default account of the wallet. /// /// The default account of the wallet. - public virtual WalletAccount GetDefaultAccount() + public virtual WalletAccount? GetDefaultAccount() { - WalletAccount first = null; + WalletAccount? first = null; foreach (WalletAccount account in GetAccounts()) { if (account.IsDefault) return account; @@ -412,13 +412,13 @@ private static Signer[] GetSigners(UInt160 sender, Signer[] cosigners) /// The imported account. public virtual WalletAccount Import(X509Certificate2 cert) { - byte[] privateKey; - using (ECDsa ecdsa = cert.GetECDsaPrivateKey()) + byte[]? privateKey; + using (ECDsa? ecdsa = cert.GetECDsaPrivateKey()) { - privateKey = ecdsa.ExportParameters(true).D; + privateKey = ecdsa?.ExportParameters(true).D; } - WalletAccount account = CreateAccount(privateKey); - Array.Clear(privateKey, 0, privateKey.Length); + WalletAccount account = CreateAccount(privateKey.NotNull()); + Array.Clear(privateKey!, 0, privateKey!.Length); return account; } @@ -461,7 +461,7 @@ public virtual WalletAccount Import(string nep2, string passphrase, int N = 1638 /// The cosigners to be added to the transaction. /// The block environment to execute the transaction. If null, will be used. /// The created transaction. - public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, UInt160 from = null, Signer[] cosigners = null, Block persistingBlock = null) + public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, UInt160? from = null, Signer[]? cosigners = null, Block? persistingBlock = null) { UInt160[] accounts; if (from is null) @@ -474,10 +474,14 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, } Dictionary cosignerList = cosigners?.ToDictionary(p => p.Account) ?? new Dictionary(); byte[] script; - List<(UInt160 Account, BigInteger Value)> balances_gas = null; + List<(UInt160 Account, BigInteger Value)>? balances_gas = null; using (ScriptBuilder sb = new()) { - foreach (var (assetId, group, sum) in outputs.GroupBy(p => p.AssetId, (k, g) => (k, g, g.Select(p => p.Value.Value).Sum()))) + foreach (var (assetId, group, sum) in outputs.GroupBy(p => p.AssetId, (k, g) => + { + var transferOutputs = g as TransferOutput[] ?? g.ToArray(); + return (k, g: transferOutputs, transferOutputs.Select(p => p.Value.Value).Sum()); + })) { var balances = new List<(UInt160 Account, BigInteger Value)>(); foreach (UInt160 account in accounts) @@ -499,7 +503,7 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, var balances_used = FindPayingAccounts(balances, output.Value.Value); foreach (var (account, value) in balances_used) { - if (cosignerList.TryGetValue(account, out Signer signer)) + if (cosignerList.TryGetValue(account, out Signer? signer)) { if (signer.Scopes != WitnessScope.Global) signer.Scopes |= WitnessScope.CalledByEntry; @@ -538,7 +542,7 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, /// The maximum gas that can be spent to execute the script. /// The block environment to execute the transaction. If null, will be used. /// The created transaction. - public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, UInt160 sender = null, Signer[] cosigners = null, TransactionAttribute[] attributes = null, long maxGas = ApplicationEngine.TestModeGas, Block persistingBlock = null) + public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, UInt160? sender = null, Signer[]? cosigners = null, TransactionAttribute[]? attributes = null, long maxGas = ApplicationEngine.TestModeGas, Block? persistingBlock = null) { UInt160[] accounts; if (sender is null) @@ -553,7 +557,7 @@ public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory scri return MakeTransaction(snapshot, script, cosigners ?? Array.Empty(), attributes ?? Array.Empty(), balances_gas, maxGas, persistingBlock: persistingBlock); } - private Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, Signer[] cosigners, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas, long maxGas = ApplicationEngine.TestModeGas, Block persistingBlock = null) + private Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, Signer[] cosigners, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas, long maxGas = ApplicationEngine.TestModeGas, Block? persistingBlock = null) { Random rand = new(); foreach (var (account, value) in balances_gas) @@ -603,8 +607,8 @@ public long CalculateNetworkFee(DataCache snapshot, Transaction tx, long maxExec foreach (UInt160 hash in hashes) { index++; - byte[] witness_script = GetAccount(hash)?.Contract?.Script; - byte[] invocationScript = null; + byte[]? witness_script = GetAccount(hash)?.Contract?.Script; + byte[]? invocationScript = null; if (tx.Witnesses != null) { @@ -612,12 +616,12 @@ public long CalculateNetworkFee(DataCache snapshot, Transaction tx, long maxExec { // Try to find the script in the witnesses Witness witness = tx.Witnesses[index]; - witness_script = witness?.VerificationScript.ToArray(); + witness_script = witness.VerificationScript.ToArray(); - if (witness_script is null || witness_script.Length == 0) + if (witness_script.Length == 0) { // Then it's a contract-based witness, so try to get the corresponding invocation script for it - invocationScript = witness?.InvocationScript.ToArray(); + invocationScript = witness.InvocationScript.ToArray(); } } } @@ -682,22 +686,22 @@ public bool Sign(ContractParametersContext context) bool fSuccess = false; foreach (UInt160 scriptHash in context.ScriptHashes) { - WalletAccount account = GetAccount(scriptHash); + WalletAccount? account = GetAccount(scriptHash); if (account != null) { // Try to sign self-contained multiSig - Contract multiSigContract = account.Contract; + Contract? multiSigContract = account.Contract; if (multiSigContract != null && - IsMultiSigContract(multiSigContract.Script, out int m, out ECPoint[] points)) + IsMultiSigContract(multiSigContract.Script, out int m, out ECPoint[]? points)) { foreach (var point in points) { - account = GetAccount(point); - if (account?.HasKey != true) continue; - KeyPair key = account.GetKey(); + account = GetAccount(point)!; + if (account.HasKey != true) continue; + KeyPair key = account.GetKey()!; byte[] signature = context.Verifiable.Sign(key, context.Network); fSuccess |= context.AddSignature(multiSigContract, key.PublicKey, signature); if (fSuccess) m--; @@ -708,9 +712,9 @@ public bool Sign(ContractParametersContext context) else if (account.HasKey) { // Try to sign with regular accounts - KeyPair key = account.GetKey(); + KeyPair key = account.GetKey()!; byte[] signature = context.Verifiable.Sign(key, context.Network); - fSuccess |= context.AddSignature(account.Contract, key.PublicKey, signature); + fSuccess |= context.AddSignature(account.Contract!, key.PublicKey, signature); continue; } } @@ -749,12 +753,12 @@ public bool Sign(ContractParametersContext context) public static Wallet Create(string name, string path, string password, ProtocolSettings settings) { - return GetFactory(path)?.CreateWallet(name, path, password, settings); + return GetFactory(path).CreateWallet(name, path, password, settings); } public static Wallet Open(string path, string password, ProtocolSettings settings) { - return GetFactory(path)?.OpenWallet(path, password, settings); + return GetFactory(path).OpenWallet(path, password, settings); } /// @@ -775,18 +779,18 @@ public static Wallet Migrate(string path, string oldPath, string password, Proto throw new InvalidOperationException("The new wallet file format is not supported."); Wallet oldWallet = factoryOld.OpenWallet(oldPath, password, settings); - Wallet newWallet = factoryNew.CreateWallet(oldWallet.Name, path, password, settings); + Wallet newWallet = factoryNew.CreateWallet(oldWallet.Name!, path, password, settings); foreach (WalletAccount account in oldWallet.GetAccounts()) { - newWallet.CreateAccount(account.Contract, account.GetKey()); + newWallet.CreateAccount(account.Contract!, account.GetKey()); } return newWallet; } private static IWalletFactory GetFactory(string path) { - return factories.FirstOrDefault(p => p.Handle(path)); + return factories.FirstOrDefault(p => p.Handle(path))!; } public static void RegisterFactory(IWalletFactory factory) diff --git a/src/Neo/Wallets/WalletAccount.cs b/src/Neo/Wallets/WalletAccount.cs index 148f272bc1..4b44c8f554 100644 --- a/src/Neo/Wallets/WalletAccount.cs +++ b/src/Neo/Wallets/WalletAccount.cs @@ -31,7 +31,7 @@ public abstract class WalletAccount /// /// The label of the account. /// - public string Label; + public string Label = default!; /// /// Indicates whether the account is the default account in the wallet. @@ -46,12 +46,12 @@ public abstract class WalletAccount /// /// The contract of the account. /// - public Contract Contract; + public Contract? Contract; /// /// The address of the account. /// - public string Address => ScriptHash.ToAddress(ProtocolSettings.AddressVersion); + public string Address => ScriptHash.ToAddress(ProtocolSettings!.AddressVersion); /// /// Indicates whether the account contains a private key. @@ -67,7 +67,7 @@ public abstract class WalletAccount /// Gets the private key of the account. /// /// The private key of the account. Or if there is no private key in the account. - public abstract KeyPair GetKey(); + public abstract KeyPair? GetKey(); /// /// Initializes a new instance of the class. From 53f819634afb9fb29f0b2b1817b33691a338d3aa Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 15:30:09 +0800 Subject: [PATCH 12/36] revoke wallet --- src/Neo/Wallets/NEP6/NEP6Account.cs | 10 ++-- src/Neo/Wallets/Wallet.cs | 76 ++++++++++++++--------------- src/Neo/Wallets/WalletAccount.cs | 2 +- 3 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/Neo/Wallets/NEP6/NEP6Account.cs b/src/Neo/Wallets/NEP6/NEP6Account.cs index f2208fd7f8..9b5fa0eecc 100644 --- a/src/Neo/Wallets/NEP6/NEP6Account.cs +++ b/src/Neo/Wallets/NEP6/NEP6Account.cs @@ -21,7 +21,7 @@ sealed class NEP6Account : WalletAccount private string? nep2key; private string? nep2KeyNew; private KeyPair? key; - public JToken Extra = null!; + public JToken? Extra; public bool Decrypted => nep2key == null || key != null; public override bool HasKey => nep2key != null; @@ -43,11 +43,11 @@ public static NEP6Account FromJson(JObject json, NEP6Wallet wallet) { return new NEP6Account(wallet, json["address"]!.GetString().ToScriptHash(wallet.ProtocolSettings.AddressVersion), json["key"]?.GetString()) { - Label = json["label"]!.GetString(), + Label = json["label"]?.GetString(), IsDefault = json["isDefault"]!.GetBoolean(), Lock = json["lock"]!.GetBoolean(), - Contract = NEP6Contract.FromJson(json["contract"].NullExceptionOr()), - Extra = json["extra"]! + Contract = NEP6Contract.FromJson((JObject?)json["contract"]), + Extra = json["extra"] }; } @@ -79,7 +79,7 @@ public JObject ToJson() account["isDefault"] = IsDefault; account["lock"] = Lock; account["key"] = nep2key; - account["contract"] = Contract.NullExceptionOr().ToJson(); + account["contract"] = ((NEP6Contract?)Contract)?.ToJson(); account["extra"] = Extra; return account; } diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index 3b2791ff41..ecffe85366 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -46,7 +46,7 @@ public abstract class Wallet /// /// The name of the wallet. /// - public abstract string? Name { get; } + public abstract string Name { get; } /// /// The path of the wallet. @@ -86,7 +86,7 @@ public abstract class Wallet /// The contract of the account. /// The private key of the account. /// The created account. - public abstract WalletAccount CreateAccount(Contract contract, KeyPair? key = null); + public abstract WalletAccount CreateAccount(Contract contract, KeyPair key = null); /// /// Creates a watch-only account for the wallet. @@ -112,7 +112,7 @@ public abstract class Wallet /// /// The hash of the account. /// The account with the specified hash. - public abstract WalletAccount? GetAccount(UInt160 scriptHash); + public abstract WalletAccount GetAccount(UInt160 scriptHash); /// /// Gets all the accounts from the wallet. @@ -165,7 +165,7 @@ public WalletAccount CreateAccount() /// The contract of the account. /// The private key of the account. /// The created account. - public WalletAccount CreateAccount(Contract contract, byte[]? privateKey) + public WalletAccount CreateAccount(Contract contract, byte[] privateKey) { if (privateKey == null) return CreateAccount(contract); return CreateAccount(contract, new KeyPair(privateKey)); @@ -237,7 +237,7 @@ public WalletAccount CreateAccount(Contract contract, byte[]? privateKey) /// /// The public key of the account. /// The account with the specified public key. - public WalletAccount? GetAccount(ECPoint pubkey) + public WalletAccount GetAccount(ECPoint pubkey) { return GetAccount(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash()); } @@ -246,9 +246,9 @@ public WalletAccount CreateAccount(Contract contract, byte[]? privateKey) /// Gets the default account of the wallet. /// /// The default account of the wallet. - public virtual WalletAccount? GetDefaultAccount() + public virtual WalletAccount GetDefaultAccount() { - WalletAccount? first = null; + WalletAccount first = null; foreach (WalletAccount account in GetAccounts()) { if (account.IsDefault) return account; @@ -412,13 +412,13 @@ private static Signer[] GetSigners(UInt160 sender, Signer[] cosigners) /// The imported account. public virtual WalletAccount Import(X509Certificate2 cert) { - byte[]? privateKey; - using (ECDsa? ecdsa = cert.GetECDsaPrivateKey()) + byte[] privateKey; + using (ECDsa ecdsa = cert.GetECDsaPrivateKey()) { - privateKey = ecdsa?.ExportParameters(true).D; + privateKey = ecdsa.ExportParameters(true).D; } - WalletAccount account = CreateAccount(privateKey.NotNull()); - Array.Clear(privateKey!, 0, privateKey!.Length); + WalletAccount account = CreateAccount(privateKey); + Array.Clear(privateKey, 0, privateKey.Length); return account; } @@ -461,7 +461,7 @@ public virtual WalletAccount Import(string nep2, string passphrase, int N = 1638 /// The cosigners to be added to the transaction. /// The block environment to execute the transaction. If null, will be used. /// The created transaction. - public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, UInt160? from = null, Signer[]? cosigners = null, Block? persistingBlock = null) + public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, UInt160 from = null, Signer[] cosigners = null, Block persistingBlock = null) { UInt160[] accounts; if (from is null) @@ -474,14 +474,10 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, } Dictionary cosignerList = cosigners?.ToDictionary(p => p.Account) ?? new Dictionary(); byte[] script; - List<(UInt160 Account, BigInteger Value)>? balances_gas = null; + List<(UInt160 Account, BigInteger Value)> balances_gas = null; using (ScriptBuilder sb = new()) { - foreach (var (assetId, group, sum) in outputs.GroupBy(p => p.AssetId, (k, g) => - { - var transferOutputs = g as TransferOutput[] ?? g.ToArray(); - return (k, g: transferOutputs, transferOutputs.Select(p => p.Value.Value).Sum()); - })) + foreach (var (assetId, group, sum) in outputs.GroupBy(p => p.AssetId, (k, g) => (k, g, g.Select(p => p.Value.Value).Sum()))) { var balances = new List<(UInt160 Account, BigInteger Value)>(); foreach (UInt160 account in accounts) @@ -503,7 +499,7 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, var balances_used = FindPayingAccounts(balances, output.Value.Value); foreach (var (account, value) in balances_used) { - if (cosignerList.TryGetValue(account, out Signer? signer)) + if (cosignerList.TryGetValue(account, out Signer signer)) { if (signer.Scopes != WitnessScope.Global) signer.Scopes |= WitnessScope.CalledByEntry; @@ -542,7 +538,7 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, /// The maximum gas that can be spent to execute the script. /// The block environment to execute the transaction. If null, will be used. /// The created transaction. - public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, UInt160? sender = null, Signer[]? cosigners = null, TransactionAttribute[]? attributes = null, long maxGas = ApplicationEngine.TestModeGas, Block? persistingBlock = null) + public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, UInt160 sender = null, Signer[] cosigners = null, TransactionAttribute[] attributes = null, long maxGas = ApplicationEngine.TestModeGas, Block persistingBlock = null) { UInt160[] accounts; if (sender is null) @@ -557,7 +553,7 @@ public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory scri return MakeTransaction(snapshot, script, cosigners ?? Array.Empty(), attributes ?? Array.Empty(), balances_gas, maxGas, persistingBlock: persistingBlock); } - private Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, Signer[] cosigners, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas, long maxGas = ApplicationEngine.TestModeGas, Block? persistingBlock = null) + private Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, Signer[] cosigners, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas, long maxGas = ApplicationEngine.TestModeGas, Block persistingBlock = null) { Random rand = new(); foreach (var (account, value) in balances_gas) @@ -607,8 +603,8 @@ public long CalculateNetworkFee(DataCache snapshot, Transaction tx, long maxExec foreach (UInt160 hash in hashes) { index++; - byte[]? witness_script = GetAccount(hash)?.Contract?.Script; - byte[]? invocationScript = null; + byte[] witness_script = GetAccount(hash)?.Contract?.Script; + byte[] invocationScript = null; if (tx.Witnesses != null) { @@ -616,12 +612,12 @@ public long CalculateNetworkFee(DataCache snapshot, Transaction tx, long maxExec { // Try to find the script in the witnesses Witness witness = tx.Witnesses[index]; - witness_script = witness.VerificationScript.ToArray(); + witness_script = witness?.VerificationScript.ToArray(); - if (witness_script.Length == 0) + if (witness_script is null || witness_script.Length == 0) { // Then it's a contract-based witness, so try to get the corresponding invocation script for it - invocationScript = witness.InvocationScript.ToArray(); + invocationScript = witness?.InvocationScript.ToArray(); } } } @@ -686,22 +682,22 @@ public bool Sign(ContractParametersContext context) bool fSuccess = false; foreach (UInt160 scriptHash in context.ScriptHashes) { - WalletAccount? account = GetAccount(scriptHash); + WalletAccount account = GetAccount(scriptHash); if (account != null) { // Try to sign self-contained multiSig - Contract? multiSigContract = account.Contract; + Contract multiSigContract = account.Contract; if (multiSigContract != null && - IsMultiSigContract(multiSigContract.Script, out int m, out ECPoint[]? points)) + IsMultiSigContract(multiSigContract.Script, out int m, out ECPoint[] points)) { foreach (var point in points) { - account = GetAccount(point)!; - if (account.HasKey != true) continue; - KeyPair key = account.GetKey()!; + account = GetAccount(point); + if (account?.HasKey != true) continue; + KeyPair key = account.GetKey(); byte[] signature = context.Verifiable.Sign(key, context.Network); fSuccess |= context.AddSignature(multiSigContract, key.PublicKey, signature); if (fSuccess) m--; @@ -712,9 +708,9 @@ public bool Sign(ContractParametersContext context) else if (account.HasKey) { // Try to sign with regular accounts - KeyPair key = account.GetKey()!; + KeyPair key = account.GetKey(); byte[] signature = context.Verifiable.Sign(key, context.Network); - fSuccess |= context.AddSignature(account.Contract!, key.PublicKey, signature); + fSuccess |= context.AddSignature(account.Contract, key.PublicKey, signature); continue; } } @@ -753,12 +749,12 @@ public bool Sign(ContractParametersContext context) public static Wallet Create(string name, string path, string password, ProtocolSettings settings) { - return GetFactory(path).CreateWallet(name, path, password, settings); + return GetFactory(path)?.CreateWallet(name, path, password, settings); } public static Wallet Open(string path, string password, ProtocolSettings settings) { - return GetFactory(path).OpenWallet(path, password, settings); + return GetFactory(path)?.OpenWallet(path, password, settings); } /// @@ -779,18 +775,18 @@ public static Wallet Migrate(string path, string oldPath, string password, Proto throw new InvalidOperationException("The new wallet file format is not supported."); Wallet oldWallet = factoryOld.OpenWallet(oldPath, password, settings); - Wallet newWallet = factoryNew.CreateWallet(oldWallet.Name!, path, password, settings); + Wallet newWallet = factoryNew.CreateWallet(oldWallet.Name, path, password, settings); foreach (WalletAccount account in oldWallet.GetAccounts()) { - newWallet.CreateAccount(account.Contract!, account.GetKey()); + newWallet.CreateAccount(account.Contract, account.GetKey()); } return newWallet; } private static IWalletFactory GetFactory(string path) { - return factories.FirstOrDefault(p => p.Handle(path))!; + return factories.FirstOrDefault(p => p.Handle(path)); } public static void RegisterFactory(IWalletFactory factory) diff --git a/src/Neo/Wallets/WalletAccount.cs b/src/Neo/Wallets/WalletAccount.cs index 4b44c8f554..2984421e8b 100644 --- a/src/Neo/Wallets/WalletAccount.cs +++ b/src/Neo/Wallets/WalletAccount.cs @@ -31,7 +31,7 @@ public abstract class WalletAccount /// /// The label of the account. /// - public string Label = default!; + public string? Label; /// /// Indicates whether the account is the default account in the wallet. From fecb839fe6e6a2d13a1c0cc156a24f0fece46685 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 15:34:06 +0800 Subject: [PATCH 13/36] nullable IO --- src/Neo/IO/ByteArrayComparer.cs | 8 +++++++- src/Neo/IO/ByteArrayEqualityComparer.cs | 2 +- src/Neo/IO/Caching/Cache.cs | 21 +++++++++++---------- src/Neo/IO/Caching/FIFOCache.cs | 4 ++-- src/Neo/IO/Caching/HashSetCache.cs | 6 +++--- src/Neo/IO/Caching/IndexedQueue.cs | 4 ++-- src/Neo/IO/Caching/KeyedCollectionSlim.cs | 21 +++++++++++++++++---- src/Neo/IO/Caching/ReflectionCache.cs | 12 ++++++------ src/Neo/IO/Helper.cs | 10 +++++----- 9 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/Neo/IO/ByteArrayComparer.cs b/src/Neo/IO/ByteArrayComparer.cs index 872052095c..4ab543525e 100644 --- a/src/Neo/IO/ByteArrayComparer.cs +++ b/src/Neo/IO/ByteArrayComparer.cs @@ -27,8 +27,14 @@ private ByteArrayComparer(int direction) this.direction = direction; } - public int Compare(byte[] x, byte[] y) + public int Compare(byte[]? x, byte[]? y) { + if (x == null || y == null) + { + if (x == null && y == null) return 0; + return x == null ? -1 : 1; + } + return direction > 0 ? CompareInternal(x, y) : -CompareInternal(x, y); diff --git a/src/Neo/IO/ByteArrayEqualityComparer.cs b/src/Neo/IO/ByteArrayEqualityComparer.cs index ffb5ad0e63..a018fc1788 100644 --- a/src/Neo/IO/ByteArrayEqualityComparer.cs +++ b/src/Neo/IO/ByteArrayEqualityComparer.cs @@ -17,7 +17,7 @@ internal class ByteArrayEqualityComparer : IEqualityComparer { public static readonly ByteArrayEqualityComparer Default = new(); - public unsafe bool Equals(byte[] x, byte[] y) + public unsafe bool Equals(byte[]? x, byte[]? y) { if (ReferenceEquals(x, y)) return true; if (x is null || y is null) return false; diff --git a/src/Neo/IO/Caching/Cache.cs b/src/Neo/IO/Caching/Cache.cs index 5d89dd59b1..a4bd99192b 100644 --- a/src/Neo/IO/Caching/Cache.cs +++ b/src/Neo/IO/Caching/Cache.cs @@ -12,12 +12,13 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; namespace Neo.IO.Caching { - internal abstract class Cache : ICollection, IDisposable + internal abstract class Cache : ICollection, IDisposable where TKey : notnull { protected class CacheItem { @@ -44,7 +45,7 @@ public TValue this[TKey key] RwSyncRootLock.EnterReadLock(); try { - if (!InnerDictionary.TryGetValue(key, out CacheItem item)) throw new KeyNotFoundException(); + if (!InnerDictionary.TryGetValue(key, out CacheItem? item)) throw new KeyNotFoundException(); OnAccess(item); return item.Value; } @@ -73,7 +74,7 @@ public int Count public bool IsReadOnly => false; - public Cache(int max_capacity, IEqualityComparer comparer = null) + public Cache(int max_capacity, IEqualityComparer? comparer = null) { this.max_capacity = max_capacity; this.InnerDictionary = new Dictionary(comparer); @@ -95,7 +96,7 @@ public void Add(TValue item) private void AddInternal(TKey key, TValue item) { - if (InnerDictionary.TryGetValue(key, out CacheItem cacheItem)) + if (InnerDictionary.TryGetValue(key, out CacheItem? cacheItem)) { OnAccess(cacheItem); } @@ -151,7 +152,7 @@ public bool Contains(TKey key) RwSyncRootLock.EnterReadLock(); try { - if (!InnerDictionary.TryGetValue(key, out CacheItem cacheItem)) return false; + if (!InnerDictionary.TryGetValue(key, out CacheItem? cacheItem)) return false; OnAccess(cacheItem); return true; } @@ -211,7 +212,7 @@ public bool Remove(TKey key) RwSyncRootLock.EnterWriteLock(); try { - if (!InnerDictionary.TryGetValue(key, out CacheItem cacheItem)) return false; + if (!InnerDictionary.TryGetValue(key, out CacheItem? cacheItem)) return false; RemoveInternal(cacheItem); return true; } @@ -237,15 +238,15 @@ private void RemoveInternal(CacheItem item) } } - public bool TryGet(TKey key, out TValue item) + public bool TryGet(TKey key, [NotNullWhen(true)] out TValue item) { RwSyncRootLock.EnterReadLock(); try { - if (InnerDictionary.TryGetValue(key, out CacheItem cacheItem)) + if (InnerDictionary.TryGetValue(key, out CacheItem? cacheItem)) { OnAccess(cacheItem); - item = cacheItem.Value; + item = cacheItem.Value!; return true; } } @@ -253,7 +254,7 @@ public bool TryGet(TKey key, out TValue item) { RwSyncRootLock.ExitReadLock(); } - item = default; + item = default!; return false; } } diff --git a/src/Neo/IO/Caching/FIFOCache.cs b/src/Neo/IO/Caching/FIFOCache.cs index af3e5e469d..4563925e9e 100644 --- a/src/Neo/IO/Caching/FIFOCache.cs +++ b/src/Neo/IO/Caching/FIFOCache.cs @@ -13,9 +13,9 @@ namespace Neo.IO.Caching { - internal abstract class FIFOCache : Cache + internal abstract class FIFOCache : Cache where TKey : notnull { - public FIFOCache(int max_capacity, IEqualityComparer comparer = null) + public FIFOCache(int max_capacity, IEqualityComparer? comparer = null) : base(max_capacity, comparer) { } diff --git a/src/Neo/IO/Caching/HashSetCache.cs b/src/Neo/IO/Caching/HashSetCache.cs index 8870e0ecf0..69188bd07d 100644 --- a/src/Neo/IO/Caching/HashSetCache.cs +++ b/src/Neo/IO/Caching/HashSetCache.cs @@ -52,7 +52,7 @@ public bool Add(T item) { if (Contains(item)) return false; Count++; - if (sets.First.Value.Count < bucketCapacity) return sets.First.Value.Add(item); + if (sets.First?.Value.Count < bucketCapacity) return sets.First.Value.Add(item); var newSet = new HashSet { item @@ -60,7 +60,7 @@ public bool Add(T item) sets.AddFirst(newSet); if (sets.Count > maxBucketCount) { - Count -= sets.Last.Value.Count; + Count -= sets.Last!.Value.Count; sets.RemoveLast(); } return true; @@ -77,7 +77,7 @@ public bool Contains(T item) public void ExceptWith(IEnumerable items) { - List> removeList = null; + List>? removeList = null; foreach (var item in items) { foreach (var set in sets) diff --git a/src/Neo/IO/Caching/IndexedQueue.cs b/src/Neo/IO/Caching/IndexedQueue.cs index 54440a871b..52af61042a 100644 --- a/src/Neo/IO/Caching/IndexedQueue.cs +++ b/src/Neo/IO/Caching/IndexedQueue.cs @@ -123,7 +123,7 @@ public T Peek() /// /// The item /// True if the queue returned an item or false if the queue is empty - public bool TryPeek(out T item) + public bool TryPeek(out T? item) { if (_count == 0) { @@ -157,7 +157,7 @@ public T Dequeue() /// /// The item /// True if the queue returned an item or false if the queue is empty - public bool TryDequeue(out T item) + public bool TryDequeue(out T? item) { if (_count == 0) { diff --git a/src/Neo/IO/Caching/KeyedCollectionSlim.cs b/src/Neo/IO/Caching/KeyedCollectionSlim.cs index a24dd87e4c..994d60776a 100644 --- a/src/Neo/IO/Caching/KeyedCollectionSlim.cs +++ b/src/Neo/IO/Caching/KeyedCollectionSlim.cs @@ -20,7 +20,17 @@ abstract class KeyedCollectionSlim where TKey : notnull private readonly Dictionary> dict = new(); public int Count => dict.Count; - public TItem First => _items.First.Value; + public TItem? First + { + get + { + if (_items.First != null) + { + return _items.First.Value; + } + return default; + } + } protected abstract TKey GetKeyForItem(TItem item); @@ -45,8 +55,11 @@ public void Remove(TKey key) public void RemoveFirst() { - var key = GetKeyForItem(_items.First.Value); - dict.Remove(key); - _items.RemoveFirst(); + if (_items.First != null) + { + var key = GetKeyForItem(_items.First.Value); + dict.Remove(key); + _items.RemoveFirst(); + } } } diff --git a/src/Neo/IO/Caching/ReflectionCache.cs b/src/Neo/IO/Caching/ReflectionCache.cs index 2fd8f5fceb..57ca50e9f5 100644 --- a/src/Neo/IO/Caching/ReflectionCache.cs +++ b/src/Neo/IO/Caching/ReflectionCache.cs @@ -26,27 +26,27 @@ static ReflectionCache() foreach (FieldInfo field in typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static)) { // Get attribute - ReflectionCacheAttribute attribute = field.GetCustomAttribute(); + ReflectionCacheAttribute? attribute = field.GetCustomAttribute(); if (attribute == null) continue; // Append to cache - dictionary.Add((T)field.GetValue(null), attribute.Type); + dictionary.Add((T)field.GetValue(null)!, attribute.Type); } } - public static object CreateInstance(T key, object def = null) + public static object? CreateInstance(T key, object? def = null) { // Get Type from cache - if (dictionary.TryGetValue(key, out Type t)) + if (dictionary.TryGetValue(key, out Type? t)) return Activator.CreateInstance(t); // return null return def; } - public static ISerializable CreateSerializable(T key, ReadOnlyMemory data) + public static ISerializable? CreateSerializable(T key, ReadOnlyMemory data) { - if (dictionary.TryGetValue(key, out Type t)) + if (dictionary.TryGetValue(key, out Type? t)) return data.AsSerializable(t); return null; } diff --git a/src/Neo/IO/Helper.cs b/src/Neo/IO/Helper.cs index 2e6d362ee1..fd98519811 100644 --- a/src/Neo/IO/Helper.cs +++ b/src/Neo/IO/Helper.cs @@ -61,7 +61,7 @@ public static ISerializable AsSerializable(this ReadOnlyMemory value, Type { if (!typeof(ISerializable).GetTypeInfo().IsAssignableFrom(type)) throw new InvalidCastException(); - ISerializable serializable = (ISerializable)Activator.CreateInstance(type); + ISerializable serializable = (ISerializable)Activator.CreateInstance(type)!; MemoryReader reader = new(value); serializable.Deserialize(ref reader); return serializable; @@ -229,9 +229,9 @@ public static byte[] ReadFixedBytes(this BinaryReader reader, int size) /// The for reading data. /// The maximum number of elements in the array. /// The array read from the . - public static T[] ReadNullableArray(this ref MemoryReader reader, int max = 0x1000000) where T : class, ISerializable, new() + public static T?[] ReadNullableArray(this ref MemoryReader reader, int max = 0x1000000) where T : class, ISerializable, new() { - T[] array = new T[reader.ReadVarInt((ulong)max)]; + T?[] array = new T[reader.ReadVarInt((ulong)max)]; for (int i = 0; i < array.Length; i++) array[i] = reader.ReadBoolean() ? reader.ReadSerializable() : null; return array; @@ -381,7 +381,7 @@ public static void WriteFixedString(this BinaryWriter writer, string value, int /// The type of the array element. /// The for writing data. /// The array to be written. - public static void WriteNullableArray(this BinaryWriter writer, T[] value) where T : class, ISerializable + public static void WriteNullableArray(this BinaryWriter writer, T?[] value) where T : class, ISerializable { writer.WriteVarInt(value.Length); foreach (var item in value) @@ -389,7 +389,7 @@ public static void WriteNullableArray(this BinaryWriter writer, T[] value) wh bool isNull = item is null; writer.Write(!isNull); if (isNull) continue; - item.Serialize(writer); + item!.Serialize(writer); } } From 6240fca09d0594e69e0653019970c17310b486c0 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 15:39:20 +0800 Subject: [PATCH 14/36] use part of contract nullable --- .../ApplicationEngine.Contract.cs | 14 +-- .../SmartContract/ApplicationEngine.Crypto.cs | 4 +- .../ApplicationEngine.Runtime.cs | 64 ++++++----- .../ApplicationEngine.Storage.cs | 7 +- src/Neo/SmartContract/ApplicationEngine.cs | 103 +++++++++--------- src/Neo/SmartContract/BinarySerializer.cs | 8 +- src/Neo/SmartContract/Contract.cs | 10 +- src/Neo/SmartContract/ContractParameter.cs | 32 +++--- .../ContractParametersContext.cs | 77 ++++++------- src/Neo/SmartContract/ContractState.cs | 10 +- src/Neo/SmartContract/ContractTask.cs | 4 +- src/Neo/SmartContract/ContractTaskAwaiter.cs | 20 ++-- .../ContractTaskMethodBuilder.cs | 4 +- src/Neo/SmartContract/DeployedContract.cs | 2 +- .../SmartContract/ExecutionContextState.cs | 10 +- src/Neo/SmartContract/Helper.cs | 13 ++- .../IApplicationEngineProvider.cs | 2 +- src/Neo/SmartContract/IInteroperable.cs | 2 +- src/Neo/SmartContract/InteropDescriptor.cs | 6 +- .../InteropParameterDescriptor.cs | 16 +-- 20 files changed, 212 insertions(+), 196 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.Contract.cs b/src/Neo/SmartContract/ApplicationEngine.Contract.cs index 5e45ba4645..dc6c17d036 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Contract.cs @@ -76,9 +76,9 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl if ((callFlags & ~CallFlags.All) != 0) throw new ArgumentOutOfRangeException(nameof(callFlags)); - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Count); + ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Count); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Count} parameter(s) doesn't exist in the contract {contractHash}."); bool hasReturnValue = md.ReturnType != ContractParameterType.Void; @@ -93,10 +93,10 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl /// The version of the native contract to be called. protected internal void CallNativeContract(byte version) { - NativeContract contract = NativeContract.GetContract(CurrentScriptHash); + NativeContract? contract = NativeContract.GetContract(CurrentScriptHash!); if (contract is null) throw new InvalidOperationException("It is not allowed to use \"System.Contract.CallNative\" directly."); - if (!contract.IsActive(ProtocolSettings, NativeContract.Ledger.CurrentIndex(Snapshot))) + if (!contract.IsActive(ProtocolSettings!, NativeContract.Ledger.CurrentIndex(Snapshot))) throw new InvalidOperationException($"The native contract {contract.Name} is not active."); contract.Invoke(this, version); } @@ -108,7 +108,7 @@ protected internal void CallNativeContract(byte version) /// The of the current context. protected internal CallFlags GetCallFlags() { - var state = CurrentContext.GetState(); + var state = CurrentContext!.GetState(); return state.CallFlags; } @@ -155,7 +155,7 @@ protected internal async void NativeOnPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) + if (contract.IsActive(ProtocolSettings!, PersistingBlock!.Index)) await contract.OnPersist(this); } } @@ -177,7 +177,7 @@ protected internal async void NativePostPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) + if (contract.IsActive(ProtocolSettings!, PersistingBlock!.Index)) await contract.PostPersist(this); } } diff --git a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs index 1a8b2c7d6d..7c151e6f2e 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs @@ -46,7 +46,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) { try { - return Crypto.VerifySignature(ScriptContainer.GetSignData(ProtocolSettings.Network), signature, pubkey, ECCurve.Secp256r1); + return Crypto.VerifySignature(ScriptContainer!.GetSignData(ProtocolSettings!.Network), signature, pubkey, ECCurve.Secp256r1); } catch (ArgumentException) { @@ -63,7 +63,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) /// if the signatures are valid; otherwise, . protected internal bool CheckMultisig(byte[][] pubkeys, byte[][] signatures) { - byte[] message = ScriptContainer.GetSignData(ProtocolSettings.Network); + byte[] message = ScriptContainer!.GetSignData(ProtocolSettings!.Network); int m = signatures.Length, n = pubkeys.Length; if (n == 0 || m == 0 || m > n) throw new ArgumentException(); AddGas(CheckSigPrice * n * ExecFeeFactor); diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index 293b245bd7..6d7b9d1f9b 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -10,7 +10,6 @@ // modifications are permitted. using Neo.Cryptography.ECC; -using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.SmartContract.Native; using Neo.VM; @@ -36,7 +35,7 @@ partial class ApplicationEngine /// public const int MaxNotificationSize = 1024; - private uint random_times = 0; + private uint random_times; /// /// The of System.Runtime.Platform. @@ -169,7 +168,7 @@ internal protected static string GetPlatform() /// The magic number of the current network. internal protected uint GetNetwork() { - return ProtocolSettings.Network; + return ProtocolSettings!.Network; } /// @@ -179,7 +178,7 @@ internal protected uint GetNetwork() /// The address version of the current network. internal protected byte GetAddressVersion() { - return ProtocolSettings.AddressVersion; + return ProtocolSettings!.AddressVersion; } /// @@ -189,7 +188,7 @@ internal protected byte GetAddressVersion() /// The timestamp of the current block. protected internal ulong GetTime() { - return PersistingBlock.Timestamp; + return PersistingBlock!.Timestamp; } /// @@ -212,7 +211,7 @@ protected internal void RuntimeLoadScript(byte[] script, CallFlags callFlags, Ar if ((callFlags & ~CallFlags.All) != 0) throw new ArgumentOutOfRangeException(nameof(callFlags)); - ExecutionContextState state = CurrentContext.GetState(); + ExecutionContextState state = CurrentContext!.GetState(); ExecutionContext context = LoadScript(new Script(script, true), configureState: p => { p.CallingContext = CurrentContext; @@ -253,17 +252,17 @@ protected internal bool CheckWitnessInternal(UInt160 hash) if (ScriptContainer is Transaction tx) { Signer[] signers; - OracleResponse response = tx.GetAttribute(); + OracleResponse? response = tx.GetAttribute(); if (response is null) { signers = tx.Signers; } else { - OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id); - signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid).Signers; + OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id).NotNull(); + signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid)!.Signers; } - Signer signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); + Signer? signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); if (signer is null) return false; foreach (WitnessRule rule in signer.GetAllRules()) { @@ -290,9 +289,9 @@ protected internal bool CheckWitnessInternal(UInt160 hash) /// The number of times the current contract has been called during the execution. protected internal int GetInvocationCounter() { - if (!invocationCounter.TryGetValue(CurrentScriptHash, out var counter)) + if (!invocationCounter.TryGetValue(CurrentScriptHash!, out var counter)) { - invocationCounter[CurrentScriptHash] = counter = 1; + invocationCounter[CurrentScriptHash!] = counter = 1; } return counter; } @@ -308,12 +307,12 @@ protected internal BigInteger GetRandom() long price; if (IsHardforkEnabled(Hardfork.HF_Aspidochelone)) { - buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network + random_times++); + buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings!.Network + random_times++); price = 1 << 13; } else { - buffer = nonceData = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network); + buffer = nonceData = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings!.Network); price = 1 << 4; } AddGas(price * ExecFeeFactor); @@ -331,7 +330,7 @@ protected internal void RuntimeLog(byte[] state) try { string message = Utility.StrictUTF8.GetString(state); - Log?.Invoke(this, new LogEventArgs(ScriptContainer, CurrentScriptHash, message)); + Log?.Invoke(this, new LogEventArgs(ScriptContainer!, CurrentScriptHash!, message)); } catch { @@ -354,7 +353,7 @@ protected internal void RuntimeNotify(byte[] eventName, Array state) } if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); string name = Utility.StrictUTF8.GetString(eventName); - ContractState contract = CurrentContext.GetState().Contract; + ContractState? contract = CurrentContext?.GetState().Contract; if (contract is null) throw new InvalidOperationException("Notifications are not allowed in dynamic scripts."); var @event = contract.Manifest.Abi.Events.FirstOrDefault(p => string.Equals(p.Name, name, StringComparison.Ordinal)); @@ -371,18 +370,21 @@ protected internal void RuntimeNotify(byte[] eventName, Array state) using MemoryStream ms = new(MaxNotificationSize); using BinaryWriter writer = new(ms, Utility.StrictUTF8, true); BinarySerializer.Serialize(writer, state, MaxNotificationSize, Limits.MaxStackSize); - SendNotification(CurrentScriptHash, name, state); + if (CurrentScriptHash != null) + { + SendNotification(CurrentScriptHash, name, state); + } } protected internal void RuntimeNotifyV1(byte[] eventName, Array state) { if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); - if (CurrentContext.GetState().Contract is null) + if (CurrentContext?.GetState().Contract is null) throw new InvalidOperationException("Notifications are not allowed in dynamic scripts."); using MemoryStream ms = new(MaxNotificationSize); using BinaryWriter writer = new(ms, Utility.StrictUTF8, true); BinarySerializer.Serialize(writer, state, MaxNotificationSize, Limits.MaxStackSize); - SendNotification(CurrentScriptHash, Utility.StrictUTF8.GetString(eventName), state); + SendNotification(CurrentScriptHash!, Utility.StrictUTF8.GetString(eventName), state); } /// @@ -393,11 +395,14 @@ protected internal void RuntimeNotifyV1(byte[] eventName, Array state) /// The arguments of the event. protected internal void SendNotification(UInt160 hash, string eventName, Array state) { - NotifyEventArgs notification = new(ScriptContainer, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); - Notify?.Invoke(this, notification); + NotifyEventArgs notification = new(ScriptContainer!, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); + Notify.Invoke(this, notification); notifications ??= new List(); notifications.Add(notification); - CurrentContext.GetState().NotificationCount++; + if (CurrentContext != null) + { + CurrentContext.GetState().NotificationCount++; + } } /// @@ -406,12 +411,12 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s /// /// The hash of the specified contract. It can be set to to get all notifications. /// The notifications sent during the execution. - protected internal NotifyEventArgs[] GetNotifications(UInt160 hash) + protected internal NotifyEventArgs[] GetNotifications(UInt160? hash) { - IEnumerable notifications = Notifications; + IEnumerable notifyEventArgsEnumerable = Notifications; if (hash != null) // must filter by scriptHash - notifications = notifications.Where(p => p.ScriptHash == hash); - NotifyEventArgs[] array = notifications.ToArray(); + notifyEventArgsEnumerable = notifyEventArgsEnumerable.Where(p => p.ScriptHash == hash); + NotifyEventArgs[] array = notifyEventArgsEnumerable.ToArray(); if (array.Length > Limits.MaxStackSize) throw new InvalidOperationException(); return array; } @@ -432,7 +437,7 @@ protected internal void BurnGas(long gas) /// Get the Signers of the current transaction. /// /// The signers of the current transaction, or null if is not related to a transaction execution. - protected internal Signer[] GetCurrentSigners() + protected internal Signer[]? GetCurrentSigners() { if (ScriptContainer is Transaction tx) return tx.Signers; @@ -463,7 +468,10 @@ private static bool CheckItemType(StackItem item, ContractParameterType type) _ = Utility.StrictUTF8.GetString(item.GetSpan()); // Prevent any non-UTF8 string return true; } - catch { } + catch + { + // ignored + } } return false; } diff --git a/src/Neo/SmartContract/ApplicationEngine.Storage.cs b/src/Neo/SmartContract/ApplicationEngine.Storage.cs index 3a8bb9d122..557e1f73bc 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Storage.cs @@ -9,6 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.IO; using Neo.Persistence; using Neo.SmartContract.Iterators; using Neo.SmartContract.Native; @@ -77,7 +78,7 @@ partial class ApplicationEngine /// The storage context for the current contract. protected internal StorageContext GetStorageContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!)!; return new StorageContext { Id = contract.Id, @@ -92,7 +93,7 @@ protected internal StorageContext GetStorageContext() /// The storage context for the current contract. protected internal StorageContext GetReadOnlyContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!)!; return new StorageContext { Id = contract.Id, @@ -177,7 +178,7 @@ protected internal void Put(StorageContext context, byte[] key, byte[] value) Id = context.Id, Key = key }; - StorageItem item = Snapshot.GetAndChange(skey); + StorageItem? item = Snapshot.GetAndChange(skey); if (item is null) { newDataSize = key.Length + value.Length; diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index ba161e6951..8d99880871 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -40,20 +40,20 @@ public partial class ApplicationEngine : ExecutionEngine /// /// Triggered when a contract calls System.Runtime.Notify. /// - public static event EventHandler Notify; + public static event EventHandler Notify = null!; /// /// Triggered when a contract calls System.Runtime.Log. /// - public static event EventHandler Log; + public static event EventHandler Log = null!; private static readonly IList AllHardforks = Enum.GetValues(typeof(Hardfork)).Cast().ToArray(); - private static Dictionary services; + private static Dictionary? services; private readonly long gas_amount; - private Dictionary states; - private readonly DataCache originalSnapshot; - private List notifications; - private List disposables; + private Dictionary? states; + private readonly DataCache? originalSnapshot; + private List? notifications; + private List? disposables; private readonly Dictionary invocationCounter = new(); private readonly Dictionary contractTasks = new(); internal readonly uint ExecFeeFactor; @@ -63,17 +63,17 @@ public partial class ApplicationEngine : ExecutionEngine /// /// Gets or sets the provider used to create the . /// - public static IApplicationEngineProvider Provider { get; set; } + public static IApplicationEngineProvider? Provider { get; set; } /// /// Gets the descriptors of all interoperable services available in NEO. /// - public static IReadOnlyDictionary Services => services; + public static IReadOnlyDictionary Services => services!; /// /// The diagnostic used by the engine. This property can be . /// - public IDiagnostic Diagnostic { get; } + public IDiagnostic? Diagnostic { get; } private List Disposables => disposables ??= new List(); @@ -85,27 +85,27 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The container that containing the executed script. This field could be if the contract is invoked by system. /// - public IVerifiable ScriptContainer { get; } + public IVerifiable? ScriptContainer { get; } /// /// The snapshot used to read or write data. /// - public DataCache Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot; + public DataCache Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot ?? throw new InvalidOperationException("No snapshot available."); /// /// The block being persisted. This field could be if the is . /// - public Block PersistingBlock { get; } + public Block? PersistingBlock { get; } /// /// The used by the engine. /// - public ProtocolSettings ProtocolSettings { get; } + public ProtocolSettings? ProtocolSettings { get; } /// /// GAS spent to execute. /// - public long GasConsumed { get; private set; } = 0; + public long GasConsumed { get; private set; } /// /// The remaining GAS that can be spent in order to complete the execution. @@ -115,30 +115,30 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The exception that caused the execution to terminate abnormally. This field could be if no exception is thrown. /// - public Exception FaultException { get; private set; } + public Exception FaultException { get; private set; } = null!; /// /// The script hash of the current context. This field could be if no context is loaded to the engine. /// - public UInt160 CurrentScriptHash => CurrentContext?.GetScriptHash(); + public UInt160? CurrentScriptHash => CurrentContext?.GetScriptHash(); /// /// The script hash of the calling contract. This field could be if the current context is the entry context. /// - public UInt160 CallingScriptHash + public UInt160? CallingScriptHash { get { if (CurrentContext is null) return null; var state = CurrentContext.GetState(); - return state.NativeCallingScriptHash ?? state.CallingContext?.GetState().ScriptHash; + return state.NativeCallingScriptHash ?? state.CallingContext.GetState().ScriptHash; } } /// /// The script hash of the entry context. This field could be if no context is loaded to the engine. /// - public UInt160 EntryScriptHash => EntryContext?.GetScriptHash(); + public UInt160? EntryScriptHash => EntryContext?.GetScriptHash(); /// /// The notifications sent during the execution. @@ -155,7 +155,7 @@ public UInt160 CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic) { this.Trigger = trigger; this.ScriptContainer = container; @@ -202,9 +202,9 @@ internal void Throw(Exception ex) private ExecutionContext CallContractInternal(UInt160 contractHash, string method, CallFlags flags, bool hasReturnValue, StackItem[] args) { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Length); + ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Length); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Length} parameter(s) doesn't exist in the contract {contractHash}."); return CallContractInternal(contract, md, flags, hasReturnValue, args); } @@ -220,7 +220,7 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe } else { - ContractState currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + ContractState? currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!); if (currentContract?.CanCall(contract, method.Name) == false) throw new InvalidOperationException($"Cannot Call Method {method.Name} Of Contract {contract.Hash} From Contract {CurrentScriptHash}"); } @@ -234,7 +234,7 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe invocationCounter[contract.Hash] = 1; } - ExecutionContext currentContext = CurrentContext; + ExecutionContext currentContext = CurrentContext.NullExceptionOr(); ExecutionContextState state = currentContext.GetState(); CallFlags callingFlags = state.CallFlags; @@ -295,7 +295,7 @@ protected override void ContextUnloaded(ExecutionContext context) else { if (state.NotificationCount > 0) - notifications.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); + notifications?.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); } } Diagnostic?.ContextUnloaded(context); @@ -318,7 +318,7 @@ protected override void ContextUnloaded(ExecutionContext context) /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock = null, ProtocolSettings? settings = null, long gas = TestModeGas, IDiagnostic? diagnostic = null) { return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -378,12 +378,12 @@ public ExecutionContext LoadContract(ContractState contract, ContractMethodDescr /// The initial position of the instruction pointer. /// The action used to configure the state of the loaded context. /// The loaded context. - public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action configureState = null) + public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action? configureState = null) { // Create and configure context ExecutionContext context = CreateContext(script, rvcount, initialPosition); ExecutionContextState state = context.GetState(); - state.Snapshot = Snapshot?.CreateSnapshot(); + state.Snapshot = Snapshot.CreateSnapshot(); configureState?.Invoke(state); // Load context @@ -394,16 +394,16 @@ public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialP protected override ExecutionContext LoadToken(ushort tokenId) { ValidateCallFlags(CallFlags.ReadStates | CallFlags.AllowCall); - ContractState contract = CurrentContext.GetState().Contract; + ContractState? contract = CurrentContext?.GetState().Contract; if (contract is null || tokenId >= contract.Nef.Tokens.Length) throw new InvalidOperationException(); MethodToken token = contract.Nef.Tokens[tokenId]; - if (token.ParametersCount > CurrentContext.EvaluationStack.Count) + if (token.ParametersCount > CurrentContext?.EvaluationStack.Count) throw new InvalidOperationException(); StackItem[] args = new StackItem[token.ParametersCount]; for (int i = 0; i < token.ParametersCount; i++) args[i] = Pop(); - return CallContractInternal(token.Hash, token.Method, token.CallFlags, token.HasReturnValue, args); + return CallContractInternal(token.Hash!, token.Method!, token.CallFlags, token.HasReturnValue, args); } /// @@ -455,7 +455,7 @@ protected internal object Convert(StackItem item, InteropParameterDescriptor des Array av; if (item is VMArray array) { - av = Array.CreateInstance(descriptor.Type.GetElementType(), array.Count); + av = Array.CreateInstance(descriptor.Type.GetElementType()!, array.Count); for (int i = 0; i < av.Length; i++) av.SetValue(descriptor.Converter(array[i]), i); } @@ -463,7 +463,7 @@ protected internal object Convert(StackItem item, InteropParameterDescriptor des { int count = (int)item.GetInteger(); if (count > Limits.MaxStackSize) throw new InvalidOperationException(); - av = Array.CreateInstance(descriptor.Type.GetElementType(), count); + av = Array.CreateInstance(descriptor.Type.GetElementType()!, count); for (int i = 0; i < av.Length; i++) av.SetValue(descriptor.Converter(Pop()), i); } @@ -498,14 +498,14 @@ public override void Dispose() /// The requirements to check. internal protected void ValidateCallFlags(CallFlags requiredCallFlags) { - ExecutionContextState state = CurrentContext.GetState(); - if (!state.CallFlags.HasFlag(requiredCallFlags)) - throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state.CallFlags}."); + ExecutionContextState? state = CurrentContext?.GetState(); + if (state == null || !state.CallFlags.HasFlag(requiredCallFlags)) + throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state?.CallFlags}."); } protected override void OnSysCall(uint method) { - OnSysCall(services[method]); + OnSysCall(services![method]); } /// @@ -521,8 +521,8 @@ protected virtual void OnSysCall(InteropDescriptor descriptor) for (int i = 0; i < parameters.Length; i++) parameters[i] = Convert(Pop(), descriptor.Parameters[i]); - object returnValue = descriptor.Handler.Invoke(this, parameters); - if (descriptor.Handler.ReturnType != typeof(void)) + object? returnValue = descriptor.Handler.Invoke(this, parameters); + if (returnValue is not null && descriptor.Handler.ReturnType != typeof(void)) Push(Convert(returnValue)); } @@ -541,7 +541,7 @@ protected override void PostExecuteInstruction(Instruction instruction) private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings settings) { UInt256 hash = NativeContract.Ledger.CurrentHash(snapshot); - Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash); + Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash)!; return new Block { Header = new Header @@ -565,7 +565,7 @@ private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings setti private static InteropDescriptor Register(string name, string handler, long fixedPrice, CallFlags requiredCallFlags) { MethodInfo method = typeof(ApplicationEngine).GetMethod(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) - ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).GetMethod; + ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)!.GetMethod!; InteropDescriptor descriptor = new() { Name = name, @@ -590,7 +590,7 @@ private static InteropDescriptor Register(string name, string handler, long fixe /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable container = null, Block persistingBlock = null, ProtocolSettings settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic diagnostic = null) + public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable? container = null, Block? persistingBlock = null, ProtocolSettings? settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic? diagnostic = null) { persistingBlock ??= CreateDummyBlock(snapshot, settings ?? ProtocolSettings.Default); ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -601,35 +601,38 @@ public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snaps public T GetState() { - if (states is null) return default; - if (!states.TryGetValue(typeof(T), out object state)) return default; + if (states is null) return default!; + if (!states.TryGetValue(typeof(T), out object? state)) return default!; return (T)state; } public void SetState(T state) { states ??= new Dictionary(); - states[typeof(T)] = state; + if (state != null) + { + states[typeof(T)] = state; + } } public bool IsHardforkEnabled(Hardfork hardfork) { // Return true if there's no specific configuration or PersistingBlock is null - if (PersistingBlock is null || ProtocolSettings.Hardforks.Count == 0) + if (PersistingBlock is null || ProtocolSettings?.Hardforks.Count == 0) return true; // If the hardfork isn't specified in the configuration, check if it's a new one. - if (!ProtocolSettings.Hardforks.ContainsKey(hardfork)) + if (ProtocolSettings is not null && !ProtocolSettings!.Hardforks.ContainsKey(hardfork)) { int currentHardforkIndex = AllHardforks.IndexOf(hardfork); - int lastConfiguredHardforkIndex = AllHardforks.IndexOf(ProtocolSettings.Hardforks.Keys.Last()); + int lastConfiguredHardforkIndex = AllHardforks.IndexOf(ProtocolSettings!.Hardforks.Keys.Last()); // If it's a newer hardfork compared to the ones in the configuration, disable it. if (currentHardforkIndex > lastConfiguredHardforkIndex) return false; } - if (ProtocolSettings.Hardforks.TryGetValue(hardfork, out uint height)) + if (ProtocolSettings is not null && ProtocolSettings!.Hardforks.TryGetValue(hardfork, out uint height)) { // If the hardfork has a specific height in the configuration, check the block height. return PersistingBlock.Index >= height; diff --git a/src/Neo/SmartContract/BinarySerializer.cs b/src/Neo/SmartContract/BinarySerializer.cs index 2bdeced678..14236e139a 100644 --- a/src/Neo/SmartContract/BinarySerializer.cs +++ b/src/Neo/SmartContract/BinarySerializer.cs @@ -39,7 +39,7 @@ public ContainerPlaceholder(StackItemType type, int count) ElementCount = count; } - public override bool Equals(StackItem other) => throw new NotSupportedException(); + public override bool Equals(StackItem? other) => throw new NotSupportedException(); public override int GetHashCode() => throw new NotSupportedException(); @@ -53,7 +53,7 @@ public ContainerPlaceholder(StackItemType type, int count) /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) { MemoryReader reader = new(data); return Deserialize(ref reader, (uint)Math.Min(data.Length, limits.MaxItemSize), limits.MaxStackSize, referenceCounter); @@ -66,7 +66,7 @@ public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLi /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) { return Deserialize(ref reader, limits.MaxItemSize, limits.MaxStackSize, referenceCounter); } @@ -79,7 +79,7 @@ public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimi /// The max of items to serialize /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter? referenceCounter = null) { Stack deserialized = new(); int undeserialized = 1; diff --git a/src/Neo/SmartContract/Contract.cs b/src/Neo/SmartContract/Contract.cs index dc60c42d50..45f8a3fe8b 100644 --- a/src/Neo/SmartContract/Contract.cs +++ b/src/Neo/SmartContract/Contract.cs @@ -25,14 +25,14 @@ public class Contract /// /// The script of the contract. /// - public byte[] Script; + public byte[]? Script; /// /// The parameters of the contract. /// - public ContractParameterType[] ParameterList; + public ContractParameterType[] ParameterList = Array.Empty(); - private UInt160 _scriptHash; + private UInt160? _scriptHash; /// /// The hash of the contract. /// @@ -42,9 +42,9 @@ public virtual UInt160 ScriptHash { if (_scriptHash == null) { - _scriptHash = Script.ToScriptHash(); + _scriptHash = Script?.ToScriptHash(); } - return _scriptHash; + return _scriptHash!; } } diff --git a/src/Neo/SmartContract/ContractParameter.cs b/src/Neo/SmartContract/ContractParameter.cs index 027fa50e00..a289156726 100644 --- a/src/Neo/SmartContract/ContractParameter.cs +++ b/src/Neo/SmartContract/ContractParameter.cs @@ -10,6 +10,7 @@ // modifications are permitted. using Neo.Cryptography.ECC; +using Neo.IO; using Neo.Json; using System; using System.Collections.Generic; @@ -32,7 +33,7 @@ public class ContractParameter /// /// The value of the parameter. /// - public object Value; + public object? Value; /// /// Initializes a new instance of the class. @@ -72,20 +73,21 @@ public static ContractParameter FromJson(JObject json) { ContractParameter parameter = new() { - Type = Enum.Parse(json["type"].GetString()) + Type = Enum.Parse(json["type"]!.GetString()) }; - if (json["value"] != null) + var value = json["value"]; + if (value != null) parameter.Value = parameter.Type switch { - ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(json["value"].AsString()), - ContractParameterType.Boolean => json["value"].AsBoolean(), - ContractParameterType.Integer => BigInteger.Parse(json["value"].AsString()), - ContractParameterType.Hash160 => UInt160.Parse(json["value"].AsString()), - ContractParameterType.Hash256 => UInt256.Parse(json["value"].AsString()), - ContractParameterType.PublicKey => ECPoint.Parse(json["value"].AsString(), ECCurve.Secp256r1), - ContractParameterType.String => json["value"].AsString(), - ContractParameterType.Array => ((JArray)json["value"]).Select(p => FromJson((JObject)p)).ToList(), - ContractParameterType.Map => ((JArray)json["value"]).Select(p => new KeyValuePair(FromJson((JObject)p["key"]), FromJson((JObject)p["value"]))).ToList(), + ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(value.AsString()), + ContractParameterType.Boolean => value.AsBoolean(), + ContractParameterType.Integer => BigInteger.Parse(value.AsString()), + ContractParameterType.Hash160 => UInt160.Parse(value.AsString()), + ContractParameterType.Hash256 => UInt256.Parse(value.AsString()), + ContractParameterType.PublicKey => ECPoint.Parse(value.AsString(), ECCurve.Secp256r1), + ContractParameterType.String => value.AsString(), + ContractParameterType.Array => ((JArray)value).Select(p => FromJson(p.NullExceptionOr())).ToList(), + ContractParameterType.Map => ((JArray)value).Select(p => new KeyValuePair(FromJson((JObject)p!["key"]!), FromJson(p["value"].NullExceptionOr()))).ToList(), _ => throw new ArgumentException(null, nameof(json)), }; return parameter; @@ -139,7 +141,7 @@ public JObject ToJson() return ToJson(this, null); } - private static JObject ToJson(ContractParameter parameter, HashSet context) + private static JObject ToJson(ContractParameter parameter, HashSet? context) { JObject json = new(); json["type"] = parameter.Type; @@ -191,7 +193,7 @@ public override string ToString() return ToString(this, null); } - private static string ToString(ContractParameter parameter, HashSet context) + private static string ToString(ContractParameter parameter, HashSet? context) { switch (parameter.Value) { @@ -246,7 +248,7 @@ private static string ToString(ContractParameter parameter, HashSet Signatures; public ContextItem(Contract contract) { - this.Script = contract.Script; + this.Script = contract.Script!; this.Parameters = contract.ParameterList.Select(p => new ContractParameter { Type = p }).ToArray(); this.Signatures = new Dictionary(); } public ContextItem(JObject json) { - this.Script = Convert.FromBase64String(json["script"].AsString()); - this.Parameters = ((JArray)json["parameters"]).Select(p => ContractParameter.FromJson((JObject)p)).ToArray(); - this.Signatures = ((JObject)json["signatures"]).Properties.Select(p => new + this.Script = Convert.FromBase64String(json["script"]!.AsString()); + this.Parameters = json["parameters"].NullExceptionOr().Select(p => ContractParameter.FromJson(p.NullExceptionOr())).ToArray(); + this.Signatures = json["signatures"].NullExceptionOr().Properties.Select(p => new { PublicKey = ECPoint.Parse(p.Key, ECCurve.Secp256r1), - Signature = Convert.FromBase64String(p.Value.AsString()) + Signature = Convert.FromBase64String(p.Value!.AsString()) }).ToDictionary(p => p.PublicKey, p => p.Signature); } public JObject ToJson() { JObject json = new(); - json["script"] = Convert.ToBase64String(Script); + json["script"] = Convert.ToBase64String(Script!); json["parameters"] = new JArray(Parameters.Select(p => p.ToJson())); json["signatures"] = new JObject(); foreach (var signature in Signatures) - json["signatures"][signature.Key.ToString()] = Convert.ToBase64String(signature.Value); + json["signatures"]![signature.Key.ToString()] = Convert.ToBase64String(signature.Value); return json; } } @@ -80,7 +80,7 @@ public JObject ToJson() /// public readonly uint Network; - private readonly Dictionary ContextItems; + private readonly Dictionary ContextItems; /// /// Determines whether all witnesses are ready to be added. @@ -95,7 +95,7 @@ public bool Completed } } - private UInt160[] _ScriptHashes = null; + private UInt160[]? _ScriptHashes; /// /// Gets the script hashes to be verified for the . /// @@ -111,7 +111,7 @@ public ContractParametersContext(DataCache snapshot, IVerifiable verifiable, uin { this.Verifiable = verifiable; this.Snapshot = snapshot; - this.ContextItems = new Dictionary(); + this.ContextItems = new Dictionary(); this.Network = network; } @@ -124,7 +124,7 @@ public ContractParametersContext(DataCache snapshot, IVerifiable verifiable, uin /// if the parameter is added successfully; otherwise, . public bool Add(Contract contract, int index, object parameter) { - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; item.Parameters[index].Value = parameter; return true; @@ -138,7 +138,7 @@ public bool Add(Contract contract, int index, object parameter) /// if the parameters are added successfully; otherwise, . public bool Add(Contract contract, params object[] parameters) { - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; for (int index = 0; index < parameters.Length; index++) { @@ -156,10 +156,10 @@ public bool Add(Contract contract, params object[] parameters) /// if the signature is added successfully; otherwise, . public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) { - if (IsMultiSigContract(contract.Script, out _, out ECPoint[] points)) + if (IsMultiSigContract(contract.Script, out _, out ECPoint[]? points)) { if (!points.Contains(pubkey)) return false; - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; if (item.Parameters.All(p => p.Value != null)) return false; if (!item.Signatures.TryAdd(pubkey, signature)) @@ -198,7 +198,7 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) // return now to prevent array index out of bounds exception return false; } - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; if (!item.Signatures.TryAdd(pubkey, signature)) return false; @@ -207,9 +207,9 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) } } - private ContextItem CreateItem(Contract contract) + private ContextItem? CreateItem(Contract contract) { - if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem item)) + if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem? item)) return item; if (!ScriptHashes.Contains(contract.ScriptHash)) return null; @@ -226,22 +226,22 @@ private ContextItem CreateItem(Contract contract) /// The converted context. public static ContractParametersContext FromJson(JObject json, DataCache snapshot) { - var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"].AsString()); + var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"]!.AsString()); if (!typeof(IVerifiable).IsAssignableFrom(type)) throw new FormatException(); - var verifiable = (IVerifiable)Activator.CreateInstance(type); - byte[] data = Convert.FromBase64String(json["data"].AsString()); + var verifiable = (IVerifiable)Activator.CreateInstance(type)!; + byte[] data = Convert.FromBase64String(json["data"]!.AsString()); MemoryReader reader = new(data); verifiable.DeserializeUnsigned(ref reader); if (json.ContainsProperty("hash")) { - UInt256 hash = UInt256.Parse(json["hash"].GetString()); + UInt256? hash = UInt256.Parse(json["hash"]!.GetString()); if (hash != verifiable.Hash) throw new FormatException(); } - ContractParametersContext context = new(snapshot, verifiable, (uint)json["network"].GetInt32()); - foreach (var (key, value) in ((JObject)json["items"]).Properties) + ContractParametersContext context = new(snapshot, verifiable, (uint)json["network"]!.GetInt32()); + foreach (var (key, value) in ((JObject)json["items"]!).Properties) { - context.ContextItems.Add(UInt160.Parse(key), new ContextItem((JObject)value)); + context.ContextItems.Add(UInt160.Parse(key), new ContextItem((JObject)value!)); } return context; } @@ -252,7 +252,7 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// The hash of the witness script. /// The specified index. /// The parameter with the specified index. - public ContractParameter GetParameter(UInt160 scriptHash, int index) + public ContractParameter? GetParameter(UInt160 scriptHash, int index) { return GetParameters(scriptHash)?[index]; } @@ -262,11 +262,11 @@ public ContractParameter GetParameter(UInt160 scriptHash, int index) /// /// The hash of the witness script. /// The parameters from the witness script. - public IReadOnlyList GetParameters(UInt160 scriptHash) + public IReadOnlyList? GetParameters(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) return null; - return item.Parameters; + return item?.Parameters; } /// @@ -274,11 +274,11 @@ public IReadOnlyList GetParameters(UInt160 scriptHash) /// /// The hash of the witness script. /// The signatures from the witness script. - public IReadOnlyDictionary GetSignatures(UInt160 scriptHash) + public IReadOnlyDictionary? GetSignatures(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) return null; - return item.Signatures; + return item?.Signatures; } /// @@ -286,11 +286,11 @@ public IReadOnlyDictionary GetSignatures(UInt160 scriptHash) /// /// The hash of the witness script. /// The witness script. - public byte[] GetScript(UInt160 scriptHash) + public byte[]? GetScript(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) return null; - return item.Script; + return item?.Script; } /// @@ -304,7 +304,8 @@ public Witness[] GetWitnesses() Witness[] witnesses = new Witness[ScriptHashes.Count]; for (int i = 0; i < ScriptHashes.Count; i++) { - ContextItem item = ContextItems[ScriptHashes[i]]; + ContextItem? item = ContextItems[ScriptHashes[i]]; + if (item == null) continue; using ScriptBuilder sb = new(); for (int j = item.Parameters.Length - 1; j >= 0; j--) { @@ -327,7 +328,7 @@ public Witness[] GetWitnesses() /// The parsed context. public static ContractParametersContext Parse(string value, DataCache snapshot) { - return FromJson((JObject)JToken.Parse(value), snapshot); + return FromJson((JObject)JToken.Parse(value)!, snapshot); } /// @@ -348,7 +349,7 @@ public JObject ToJson() } json["items"] = new JObject(); foreach (var item in ContextItems) - json["items"][item.Key.ToString()] = item.Value.ToJson(); + json["items"]![item.Key.ToString()] = item!.Value!.ToJson(); json["network"] = Network; return json; } diff --git a/src/Neo/SmartContract/ContractState.cs b/src/Neo/SmartContract/ContractState.cs index 83ac9d3353..873b65f514 100644 --- a/src/Neo/SmartContract/ContractState.cs +++ b/src/Neo/SmartContract/ContractState.cs @@ -38,17 +38,17 @@ public class ContractState : IInteroperable /// /// The hash of the contract. /// - public UInt160 Hash; + public UInt160 Hash = null!; /// /// The nef of the contract. /// - public NefFile Nef; + public NefFile Nef = null!; /// /// The manifest of the contract. /// - public ContractManifest Manifest; + public ContractManifest Manifest = null!; /// /// The script of the contract. @@ -114,9 +114,9 @@ public JObject ToJson() }; } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { - return new Array(referenceCounter, new StackItem[] { Id, (int)UpdateCounter, Hash.ToArray(), Nef.ToArray(), Manifest.ToStackItem(referenceCounter) }); + return new Array(referenceCounter, new[] { Id, (int)UpdateCounter, Hash.ToArray(), Nef.ToArray(), Manifest.ToStackItem(referenceCounter) }); } } } diff --git a/src/Neo/SmartContract/ContractTask.cs b/src/Neo/SmartContract/ContractTask.cs index 6df3627c37..72d4b91472 100644 --- a/src/Neo/SmartContract/ContractTask.cs +++ b/src/Neo/SmartContract/ContractTask.cs @@ -33,7 +33,7 @@ public ContractTask() protected virtual ContractTaskAwaiter CreateAwaiter() => new(); public virtual ContractTaskAwaiter GetAwaiter() => awaiter; - public virtual object GetResult() => null; + public virtual object? GetResult() => null; } [AsyncMethodBuilder(typeof(ContractTaskMethodBuilder<>))] @@ -41,6 +41,6 @@ class ContractTask : ContractTask { protected override ContractTaskAwaiter CreateAwaiter() => new ContractTaskAwaiter(); public override ContractTaskAwaiter GetAwaiter() => (ContractTaskAwaiter)base.GetAwaiter(); - public override object GetResult() => ((ContractTaskAwaiter)GetAwaiter()).GetResult(); + public override object? GetResult() => ((ContractTaskAwaiter)GetAwaiter()).GetResult(); } } diff --git a/src/Neo/SmartContract/ContractTaskAwaiter.cs b/src/Neo/SmartContract/ContractTaskAwaiter.cs index a0a0c9a1bb..2bd23d3fc2 100644 --- a/src/Neo/SmartContract/ContractTaskAwaiter.cs +++ b/src/Neo/SmartContract/ContractTaskAwaiter.cs @@ -17,15 +17,15 @@ namespace Neo.SmartContract { class ContractTaskAwaiter : INotifyCompletion { - private Action continuation; - private Exception exception; + private Action _continuation = null!; + private Exception _exception = null!; public bool IsCompleted { get; private set; } public void GetResult() { - if (exception is not null) - throw exception; + if (_exception is not null) + throw _exception; } public void SetResult() => RunContinuation(); @@ -34,35 +34,35 @@ public void GetResult() public void SetException(Exception exception) { - this.exception = exception; + this._exception = exception; RunContinuation(); } public void OnCompleted(Action continuation) { - Interlocked.CompareExchange(ref this.continuation, continuation, null); + Interlocked.CompareExchange(ref this._continuation, continuation, null); } protected void RunContinuation() { IsCompleted = true; - continuation?.Invoke(); + _continuation.Invoke(); } } class ContractTaskAwaiter : ContractTaskAwaiter { - private T result; + private T _result = default!; public new T GetResult() { base.GetResult(); - return result; + return _result; } public void SetResult(T result) { - this.result = result; + this._result = result; RunContinuation(); } diff --git a/src/Neo/SmartContract/ContractTaskMethodBuilder.cs b/src/Neo/SmartContract/ContractTaskMethodBuilder.cs index bae1146f25..2cf6030635 100644 --- a/src/Neo/SmartContract/ContractTaskMethodBuilder.cs +++ b/src/Neo/SmartContract/ContractTaskMethodBuilder.cs @@ -16,7 +16,7 @@ namespace Neo.SmartContract { sealed class ContractTaskMethodBuilder { - private ContractTask task; + private ContractTask? task; public ContractTask Task => task ??= new ContractTask(); @@ -58,7 +58,7 @@ public void SetStateMachine(IAsyncStateMachine stateMachine) sealed class ContractTaskMethodBuilder { - private ContractTask task; + private ContractTask? task; public ContractTask Task => task ??= new ContractTask(); diff --git a/src/Neo/SmartContract/DeployedContract.cs b/src/Neo/SmartContract/DeployedContract.cs index 0587a029e5..4ea6c7845d 100644 --- a/src/Neo/SmartContract/DeployedContract.cs +++ b/src/Neo/SmartContract/DeployedContract.cs @@ -32,7 +32,7 @@ public DeployedContract(ContractState contract) Script = null; ScriptHash = contract.Hash; - ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor? descriptor = contract.Manifest.Abi.GetMethod("verify", -1); if (descriptor is null) throw new NotSupportedException("The smart contract haven't got verify method."); ParameterList = descriptor.Parameters.Select(u => u.Type).ToArray(); diff --git a/src/Neo/SmartContract/ExecutionContextState.cs b/src/Neo/SmartContract/ExecutionContextState.cs index 8b61ff1197..abbdfb3aa1 100644 --- a/src/Neo/SmartContract/ExecutionContextState.cs +++ b/src/Neo/SmartContract/ExecutionContextState.cs @@ -22,29 +22,29 @@ public class ExecutionContextState /// /// The script hash of the current context. /// - public UInt160 ScriptHash { get; set; } + public UInt160? ScriptHash { get; set; } /// /// The calling context. /// - public ExecutionContext CallingContext { get; set; } + public ExecutionContext CallingContext { get; set; } = null!; /// /// The script hash of the calling native contract. Used in native contracts only. /// - internal UInt160 NativeCallingScriptHash { get; set; } + internal UInt160? NativeCallingScriptHash { get; set; } /// /// The of the current context. /// - public ContractState Contract { get; set; } + public ContractState Contract { get; set; } = null!; /// /// The of the current context. /// public CallFlags CallFlags { get; set; } = CallFlags.All; - public DataCache Snapshot { get; set; } + public DataCache Snapshot { get; set; } = null!; public int NotificationCount { get; set; } diff --git a/src/Neo/SmartContract/Helper.cs b/src/Neo/SmartContract/Helper.cs index 5045c74717..1b12b2fd28 100644 --- a/src/Neo/SmartContract/Helper.cs +++ b/src/Neo/SmartContract/Helper.cs @@ -20,6 +20,7 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Neo.SmartContract @@ -110,7 +111,7 @@ public static UInt160 GetContractHash(UInt160 sender, uint nefCheckSum, string n /// The script hash of the context. public static UInt160 GetScriptHash(this ExecutionContext context) { - return context.GetState().ScriptHash; + return context.GetState().ScriptHash!; } /// @@ -142,7 +143,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out /// The minimum number of correct signatures that need to be provided in order for the verification to pass. /// The public keys in the account. /// if the contract is a multi-signature contract; otherwise, . - public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out ECPoint[] points) + public static bool IsMultiSigContract(ReadOnlySpan script, out int m, [NotNullWhen(true)] out ECPoint[]? points) { List list = new(); if (IsMultiSigContract(script, out m, out _, list)) @@ -157,7 +158,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out } } - private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List points) + private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List? points) { m = 0; n = 0; int i = 0; @@ -316,13 +317,13 @@ internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings { return false; } - using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.CreateSnapshot(), null, settings, gas)) + using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot.CreateSnapshot(), null, settings, gas)) { if (witness.VerificationScript.Length == 0) { - ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash); + ContractState? cs = NativeContract.ContractManagement.GetContract(snapshot, hash); if (cs is null) return false; - ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor? md = cs.Manifest.Abi.GetMethod("verify", -1); if (md?.ReturnType != ContractParameterType.Boolean) return false; engine.LoadContract(cs, md, CallFlags.ReadOnly); } diff --git a/src/Neo/SmartContract/IApplicationEngineProvider.cs b/src/Neo/SmartContract/IApplicationEngineProvider.cs index ef06c6b92c..d39286fda8 100644 --- a/src/Neo/SmartContract/IApplicationEngineProvider.cs +++ b/src/Neo/SmartContract/IApplicationEngineProvider.cs @@ -30,6 +30,6 @@ public interface IApplicationEngineProvider /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic); + ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic); } } diff --git a/src/Neo/SmartContract/IInteroperable.cs b/src/Neo/SmartContract/IInteroperable.cs index 5254898efe..d9009625b1 100644 --- a/src/Neo/SmartContract/IInteroperable.cs +++ b/src/Neo/SmartContract/IInteroperable.cs @@ -31,7 +31,7 @@ public interface IInteroperable /// /// The used by the . /// The converted . - StackItem ToStackItem(ReferenceCounter referenceCounter); + StackItem ToStackItem(ReferenceCounter? referenceCounter); public IInteroperable Clone() { diff --git a/src/Neo/SmartContract/InteropDescriptor.cs b/src/Neo/SmartContract/InteropDescriptor.cs index 29c88f46ed..f21ba88b49 100644 --- a/src/Neo/SmartContract/InteropDescriptor.cs +++ b/src/Neo/SmartContract/InteropDescriptor.cs @@ -26,7 +26,7 @@ public record InteropDescriptor /// /// The name of the interoperable service. /// - public string Name { get; init; } + public string Name { get; init; } = null!; private uint _hash; /// @@ -45,9 +45,9 @@ public uint Hash /// /// The used to handle the interoperable service. /// - public MethodInfo Handler { get; init; } + public MethodInfo Handler { get; init; } = null!; - private IReadOnlyList _parameters; + private IReadOnlyList? _parameters; /// /// The parameters of the interoperable service. /// diff --git a/src/Neo/SmartContract/InteropParameterDescriptor.cs b/src/Neo/SmartContract/InteropParameterDescriptor.cs index 6a65beb93f..603c91f3ad 100644 --- a/src/Neo/SmartContract/InteropParameterDescriptor.cs +++ b/src/Neo/SmartContract/InteropParameterDescriptor.cs @@ -24,12 +24,12 @@ namespace Neo.SmartContract /// public class InteropParameterDescriptor { - private readonly ValidatorAttribute[] validators; + private readonly ValidatorAttribute[] validators = null!; /// /// The name of the parameter. /// - public string Name { get; } + public string Name { get; } = null!; /// /// The type of the parameter. @@ -56,7 +56,7 @@ public class InteropParameterDescriptor /// public bool IsInterface { get; } - private static readonly Dictionary> converters = new() + private static readonly Dictionary> converters = new() { [typeof(StackItem)] = p => p, [typeof(VM.Types.Pointer)] = p => p, @@ -82,7 +82,7 @@ public class InteropParameterDescriptor internal InteropParameterDescriptor(ParameterInfo parameterInfo) : this(parameterInfo.ParameterType) { - this.Name = parameterInfo.Name; + this.Name = parameterInfo.Name!; this.validators = parameterInfo.GetCustomAttributes(true).ToArray(); } @@ -91,19 +91,19 @@ internal InteropParameterDescriptor(Type type) this.Type = type; if (IsEnum) { - Converter = converters[type.GetEnumUnderlyingType()]; + Converter = converters[type.GetEnumUnderlyingType()]!; } else if (IsArray) { - Converter = converters[type.GetElementType()]; + Converter = converters[type.GetElementType()!]!; } else { IsInterface = !converters.TryGetValue(type, out var converter); if (IsInterface) - Converter = converters[typeof(InteropInterface)]; + Converter = converters[typeof(InteropInterface)]!; else - Converter = converter; + Converter = converter!; } } From 343cb9b84cb2c400f9469bdace35f0c70c06a601 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 15:43:29 +0800 Subject: [PATCH 15/36] Revert "use part of contract nullable" This reverts commit 6240fca09d0594e69e0653019970c17310b486c0. --- .../ApplicationEngine.Contract.cs | 14 +-- .../SmartContract/ApplicationEngine.Crypto.cs | 4 +- .../ApplicationEngine.Runtime.cs | 64 +++++------ .../ApplicationEngine.Storage.cs | 7 +- src/Neo/SmartContract/ApplicationEngine.cs | 103 +++++++++--------- src/Neo/SmartContract/BinarySerializer.cs | 8 +- src/Neo/SmartContract/Contract.cs | 10 +- src/Neo/SmartContract/ContractParameter.cs | 32 +++--- .../ContractParametersContext.cs | 77 +++++++------ src/Neo/SmartContract/ContractState.cs | 10 +- src/Neo/SmartContract/ContractTask.cs | 4 +- src/Neo/SmartContract/ContractTaskAwaiter.cs | 20 ++-- .../ContractTaskMethodBuilder.cs | 4 +- src/Neo/SmartContract/DeployedContract.cs | 2 +- .../SmartContract/ExecutionContextState.cs | 10 +- src/Neo/SmartContract/Helper.cs | 13 +-- .../IApplicationEngineProvider.cs | 2 +- src/Neo/SmartContract/IInteroperable.cs | 2 +- src/Neo/SmartContract/InteropDescriptor.cs | 6 +- .../InteropParameterDescriptor.cs | 16 +-- 20 files changed, 196 insertions(+), 212 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.Contract.cs b/src/Neo/SmartContract/ApplicationEngine.Contract.cs index dc6c17d036..5e45ba4645 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Contract.cs @@ -76,9 +76,9 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl if ((callFlags & ~CallFlags.All) != 0) throw new ArgumentOutOfRangeException(nameof(callFlags)); - ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Count); + ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Count); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Count} parameter(s) doesn't exist in the contract {contractHash}."); bool hasReturnValue = md.ReturnType != ContractParameterType.Void; @@ -93,10 +93,10 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl /// The version of the native contract to be called. protected internal void CallNativeContract(byte version) { - NativeContract? contract = NativeContract.GetContract(CurrentScriptHash!); + NativeContract contract = NativeContract.GetContract(CurrentScriptHash); if (contract is null) throw new InvalidOperationException("It is not allowed to use \"System.Contract.CallNative\" directly."); - if (!contract.IsActive(ProtocolSettings!, NativeContract.Ledger.CurrentIndex(Snapshot))) + if (!contract.IsActive(ProtocolSettings, NativeContract.Ledger.CurrentIndex(Snapshot))) throw new InvalidOperationException($"The native contract {contract.Name} is not active."); contract.Invoke(this, version); } @@ -108,7 +108,7 @@ protected internal void CallNativeContract(byte version) /// The of the current context. protected internal CallFlags GetCallFlags() { - var state = CurrentContext!.GetState(); + var state = CurrentContext.GetState(); return state.CallFlags; } @@ -155,7 +155,7 @@ protected internal async void NativeOnPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings!, PersistingBlock!.Index)) + if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) await contract.OnPersist(this); } } @@ -177,7 +177,7 @@ protected internal async void NativePostPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings!, PersistingBlock!.Index)) + if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) await contract.PostPersist(this); } } diff --git a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs index 7c151e6f2e..1a8b2c7d6d 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs @@ -46,7 +46,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) { try { - return Crypto.VerifySignature(ScriptContainer!.GetSignData(ProtocolSettings!.Network), signature, pubkey, ECCurve.Secp256r1); + return Crypto.VerifySignature(ScriptContainer.GetSignData(ProtocolSettings.Network), signature, pubkey, ECCurve.Secp256r1); } catch (ArgumentException) { @@ -63,7 +63,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) /// if the signatures are valid; otherwise, . protected internal bool CheckMultisig(byte[][] pubkeys, byte[][] signatures) { - byte[] message = ScriptContainer!.GetSignData(ProtocolSettings!.Network); + byte[] message = ScriptContainer.GetSignData(ProtocolSettings.Network); int m = signatures.Length, n = pubkeys.Length; if (n == 0 || m == 0 || m > n) throw new ArgumentException(); AddGas(CheckSigPrice * n * ExecFeeFactor); diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index 6d7b9d1f9b..293b245bd7 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -10,6 +10,7 @@ // modifications are permitted. using Neo.Cryptography.ECC; +using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.SmartContract.Native; using Neo.VM; @@ -35,7 +36,7 @@ partial class ApplicationEngine /// public const int MaxNotificationSize = 1024; - private uint random_times; + private uint random_times = 0; /// /// The of System.Runtime.Platform. @@ -168,7 +169,7 @@ internal protected static string GetPlatform() /// The magic number of the current network. internal protected uint GetNetwork() { - return ProtocolSettings!.Network; + return ProtocolSettings.Network; } /// @@ -178,7 +179,7 @@ internal protected uint GetNetwork() /// The address version of the current network. internal protected byte GetAddressVersion() { - return ProtocolSettings!.AddressVersion; + return ProtocolSettings.AddressVersion; } /// @@ -188,7 +189,7 @@ internal protected byte GetAddressVersion() /// The timestamp of the current block. protected internal ulong GetTime() { - return PersistingBlock!.Timestamp; + return PersistingBlock.Timestamp; } /// @@ -211,7 +212,7 @@ protected internal void RuntimeLoadScript(byte[] script, CallFlags callFlags, Ar if ((callFlags & ~CallFlags.All) != 0) throw new ArgumentOutOfRangeException(nameof(callFlags)); - ExecutionContextState state = CurrentContext!.GetState(); + ExecutionContextState state = CurrentContext.GetState(); ExecutionContext context = LoadScript(new Script(script, true), configureState: p => { p.CallingContext = CurrentContext; @@ -252,17 +253,17 @@ protected internal bool CheckWitnessInternal(UInt160 hash) if (ScriptContainer is Transaction tx) { Signer[] signers; - OracleResponse? response = tx.GetAttribute(); + OracleResponse response = tx.GetAttribute(); if (response is null) { signers = tx.Signers; } else { - OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id).NotNull(); - signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid)!.Signers; + OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id); + signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid).Signers; } - Signer? signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); + Signer signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); if (signer is null) return false; foreach (WitnessRule rule in signer.GetAllRules()) { @@ -289,9 +290,9 @@ protected internal bool CheckWitnessInternal(UInt160 hash) /// The number of times the current contract has been called during the execution. protected internal int GetInvocationCounter() { - if (!invocationCounter.TryGetValue(CurrentScriptHash!, out var counter)) + if (!invocationCounter.TryGetValue(CurrentScriptHash, out var counter)) { - invocationCounter[CurrentScriptHash!] = counter = 1; + invocationCounter[CurrentScriptHash] = counter = 1; } return counter; } @@ -307,12 +308,12 @@ protected internal BigInteger GetRandom() long price; if (IsHardforkEnabled(Hardfork.HF_Aspidochelone)) { - buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings!.Network + random_times++); + buffer = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network + random_times++); price = 1 << 13; } else { - buffer = nonceData = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings!.Network); + buffer = nonceData = Cryptography.Helper.Murmur128(nonceData, ProtocolSettings.Network); price = 1 << 4; } AddGas(price * ExecFeeFactor); @@ -330,7 +331,7 @@ protected internal void RuntimeLog(byte[] state) try { string message = Utility.StrictUTF8.GetString(state); - Log?.Invoke(this, new LogEventArgs(ScriptContainer!, CurrentScriptHash!, message)); + Log?.Invoke(this, new LogEventArgs(ScriptContainer, CurrentScriptHash, message)); } catch { @@ -353,7 +354,7 @@ protected internal void RuntimeNotify(byte[] eventName, Array state) } if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); string name = Utility.StrictUTF8.GetString(eventName); - ContractState? contract = CurrentContext?.GetState().Contract; + ContractState contract = CurrentContext.GetState().Contract; if (contract is null) throw new InvalidOperationException("Notifications are not allowed in dynamic scripts."); var @event = contract.Manifest.Abi.Events.FirstOrDefault(p => string.Equals(p.Name, name, StringComparison.Ordinal)); @@ -370,21 +371,18 @@ protected internal void RuntimeNotify(byte[] eventName, Array state) using MemoryStream ms = new(MaxNotificationSize); using BinaryWriter writer = new(ms, Utility.StrictUTF8, true); BinarySerializer.Serialize(writer, state, MaxNotificationSize, Limits.MaxStackSize); - if (CurrentScriptHash != null) - { - SendNotification(CurrentScriptHash, name, state); - } + SendNotification(CurrentScriptHash, name, state); } protected internal void RuntimeNotifyV1(byte[] eventName, Array state) { if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); - if (CurrentContext?.GetState().Contract is null) + if (CurrentContext.GetState().Contract is null) throw new InvalidOperationException("Notifications are not allowed in dynamic scripts."); using MemoryStream ms = new(MaxNotificationSize); using BinaryWriter writer = new(ms, Utility.StrictUTF8, true); BinarySerializer.Serialize(writer, state, MaxNotificationSize, Limits.MaxStackSize); - SendNotification(CurrentScriptHash!, Utility.StrictUTF8.GetString(eventName), state); + SendNotification(CurrentScriptHash, Utility.StrictUTF8.GetString(eventName), state); } /// @@ -395,14 +393,11 @@ protected internal void RuntimeNotifyV1(byte[] eventName, Array state) /// The arguments of the event. protected internal void SendNotification(UInt160 hash, string eventName, Array state) { - NotifyEventArgs notification = new(ScriptContainer!, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); - Notify.Invoke(this, notification); + NotifyEventArgs notification = new(ScriptContainer, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); + Notify?.Invoke(this, notification); notifications ??= new List(); notifications.Add(notification); - if (CurrentContext != null) - { - CurrentContext.GetState().NotificationCount++; - } + CurrentContext.GetState().NotificationCount++; } /// @@ -411,12 +406,12 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s /// /// The hash of the specified contract. It can be set to to get all notifications. /// The notifications sent during the execution. - protected internal NotifyEventArgs[] GetNotifications(UInt160? hash) + protected internal NotifyEventArgs[] GetNotifications(UInt160 hash) { - IEnumerable notifyEventArgsEnumerable = Notifications; + IEnumerable notifications = Notifications; if (hash != null) // must filter by scriptHash - notifyEventArgsEnumerable = notifyEventArgsEnumerable.Where(p => p.ScriptHash == hash); - NotifyEventArgs[] array = notifyEventArgsEnumerable.ToArray(); + notifications = notifications.Where(p => p.ScriptHash == hash); + NotifyEventArgs[] array = notifications.ToArray(); if (array.Length > Limits.MaxStackSize) throw new InvalidOperationException(); return array; } @@ -437,7 +432,7 @@ protected internal void BurnGas(long gas) /// Get the Signers of the current transaction. /// /// The signers of the current transaction, or null if is not related to a transaction execution. - protected internal Signer[]? GetCurrentSigners() + protected internal Signer[] GetCurrentSigners() { if (ScriptContainer is Transaction tx) return tx.Signers; @@ -468,10 +463,7 @@ private static bool CheckItemType(StackItem item, ContractParameterType type) _ = Utility.StrictUTF8.GetString(item.GetSpan()); // Prevent any non-UTF8 string return true; } - catch - { - // ignored - } + catch { } } return false; } diff --git a/src/Neo/SmartContract/ApplicationEngine.Storage.cs b/src/Neo/SmartContract/ApplicationEngine.Storage.cs index 557e1f73bc..3a8bb9d122 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Storage.cs @@ -9,7 +9,6 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo.IO; using Neo.Persistence; using Neo.SmartContract.Iterators; using Neo.SmartContract.Native; @@ -78,7 +77,7 @@ partial class ApplicationEngine /// The storage context for the current contract. protected internal StorageContext GetStorageContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!)!; + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); return new StorageContext { Id = contract.Id, @@ -93,7 +92,7 @@ protected internal StorageContext GetStorageContext() /// The storage context for the current contract. protected internal StorageContext GetReadOnlyContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!)!; + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); return new StorageContext { Id = contract.Id, @@ -178,7 +177,7 @@ protected internal void Put(StorageContext context, byte[] key, byte[] value) Id = context.Id, Key = key }; - StorageItem? item = Snapshot.GetAndChange(skey); + StorageItem item = Snapshot.GetAndChange(skey); if (item is null) { newDataSize = key.Length + value.Length; diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 8d99880871..ba161e6951 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -40,20 +40,20 @@ public partial class ApplicationEngine : ExecutionEngine /// /// Triggered when a contract calls System.Runtime.Notify. /// - public static event EventHandler Notify = null!; + public static event EventHandler Notify; /// /// Triggered when a contract calls System.Runtime.Log. /// - public static event EventHandler Log = null!; + public static event EventHandler Log; private static readonly IList AllHardforks = Enum.GetValues(typeof(Hardfork)).Cast().ToArray(); - private static Dictionary? services; + private static Dictionary services; private readonly long gas_amount; - private Dictionary? states; - private readonly DataCache? originalSnapshot; - private List? notifications; - private List? disposables; + private Dictionary states; + private readonly DataCache originalSnapshot; + private List notifications; + private List disposables; private readonly Dictionary invocationCounter = new(); private readonly Dictionary contractTasks = new(); internal readonly uint ExecFeeFactor; @@ -63,17 +63,17 @@ public partial class ApplicationEngine : ExecutionEngine /// /// Gets or sets the provider used to create the . /// - public static IApplicationEngineProvider? Provider { get; set; } + public static IApplicationEngineProvider Provider { get; set; } /// /// Gets the descriptors of all interoperable services available in NEO. /// - public static IReadOnlyDictionary Services => services!; + public static IReadOnlyDictionary Services => services; /// /// The diagnostic used by the engine. This property can be . /// - public IDiagnostic? Diagnostic { get; } + public IDiagnostic Diagnostic { get; } private List Disposables => disposables ??= new List(); @@ -85,27 +85,27 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The container that containing the executed script. This field could be if the contract is invoked by system. /// - public IVerifiable? ScriptContainer { get; } + public IVerifiable ScriptContainer { get; } /// /// The snapshot used to read or write data. /// - public DataCache Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot ?? throw new InvalidOperationException("No snapshot available."); + public DataCache Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot; /// /// The block being persisted. This field could be if the is . /// - public Block? PersistingBlock { get; } + public Block PersistingBlock { get; } /// /// The used by the engine. /// - public ProtocolSettings? ProtocolSettings { get; } + public ProtocolSettings ProtocolSettings { get; } /// /// GAS spent to execute. /// - public long GasConsumed { get; private set; } + public long GasConsumed { get; private set; } = 0; /// /// The remaining GAS that can be spent in order to complete the execution. @@ -115,30 +115,30 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The exception that caused the execution to terminate abnormally. This field could be if no exception is thrown. /// - public Exception FaultException { get; private set; } = null!; + public Exception FaultException { get; private set; } /// /// The script hash of the current context. This field could be if no context is loaded to the engine. /// - public UInt160? CurrentScriptHash => CurrentContext?.GetScriptHash(); + public UInt160 CurrentScriptHash => CurrentContext?.GetScriptHash(); /// /// The script hash of the calling contract. This field could be if the current context is the entry context. /// - public UInt160? CallingScriptHash + public UInt160 CallingScriptHash { get { if (CurrentContext is null) return null; var state = CurrentContext.GetState(); - return state.NativeCallingScriptHash ?? state.CallingContext.GetState().ScriptHash; + return state.NativeCallingScriptHash ?? state.CallingContext?.GetState().ScriptHash; } } /// /// The script hash of the entry context. This field could be if no context is loaded to the engine. /// - public UInt160? EntryScriptHash => EntryContext?.GetScriptHash(); + public UInt160 EntryScriptHash => EntryContext?.GetScriptHash(); /// /// The notifications sent during the execution. @@ -155,7 +155,7 @@ public UInt160? CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic) + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) { this.Trigger = trigger; this.ScriptContainer = container; @@ -202,9 +202,9 @@ internal void Throw(Exception ex) private ExecutionContext CallContractInternal(UInt160 contractHash, string method, CallFlags flags, bool hasReturnValue, StackItem[] args) { - ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Length); + ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Length); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Length} parameter(s) doesn't exist in the contract {contractHash}."); return CallContractInternal(contract, md, flags, hasReturnValue, args); } @@ -220,7 +220,7 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe } else { - ContractState? currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash!); + ContractState currentContract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); if (currentContract?.CanCall(contract, method.Name) == false) throw new InvalidOperationException($"Cannot Call Method {method.Name} Of Contract {contract.Hash} From Contract {CurrentScriptHash}"); } @@ -234,7 +234,7 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe invocationCounter[contract.Hash] = 1; } - ExecutionContext currentContext = CurrentContext.NullExceptionOr(); + ExecutionContext currentContext = CurrentContext; ExecutionContextState state = currentContext.GetState(); CallFlags callingFlags = state.CallFlags; @@ -295,7 +295,7 @@ protected override void ContextUnloaded(ExecutionContext context) else { if (state.NotificationCount > 0) - notifications?.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); + notifications.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); } } Diagnostic?.ContextUnloaded(context); @@ -318,7 +318,7 @@ protected override void ContextUnloaded(ExecutionContext context) /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock = null, ProtocolSettings? settings = null, long gas = TestModeGas, IDiagnostic? diagnostic = null) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) { return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -378,12 +378,12 @@ public ExecutionContext LoadContract(ContractState contract, ContractMethodDescr /// The initial position of the instruction pointer. /// The action used to configure the state of the loaded context. /// The loaded context. - public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action? configureState = null) + public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action configureState = null) { // Create and configure context ExecutionContext context = CreateContext(script, rvcount, initialPosition); ExecutionContextState state = context.GetState(); - state.Snapshot = Snapshot.CreateSnapshot(); + state.Snapshot = Snapshot?.CreateSnapshot(); configureState?.Invoke(state); // Load context @@ -394,16 +394,16 @@ public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialP protected override ExecutionContext LoadToken(ushort tokenId) { ValidateCallFlags(CallFlags.ReadStates | CallFlags.AllowCall); - ContractState? contract = CurrentContext?.GetState().Contract; + ContractState contract = CurrentContext.GetState().Contract; if (contract is null || tokenId >= contract.Nef.Tokens.Length) throw new InvalidOperationException(); MethodToken token = contract.Nef.Tokens[tokenId]; - if (token.ParametersCount > CurrentContext?.EvaluationStack.Count) + if (token.ParametersCount > CurrentContext.EvaluationStack.Count) throw new InvalidOperationException(); StackItem[] args = new StackItem[token.ParametersCount]; for (int i = 0; i < token.ParametersCount; i++) args[i] = Pop(); - return CallContractInternal(token.Hash!, token.Method!, token.CallFlags, token.HasReturnValue, args); + return CallContractInternal(token.Hash, token.Method, token.CallFlags, token.HasReturnValue, args); } /// @@ -455,7 +455,7 @@ protected internal object Convert(StackItem item, InteropParameterDescriptor des Array av; if (item is VMArray array) { - av = Array.CreateInstance(descriptor.Type.GetElementType()!, array.Count); + av = Array.CreateInstance(descriptor.Type.GetElementType(), array.Count); for (int i = 0; i < av.Length; i++) av.SetValue(descriptor.Converter(array[i]), i); } @@ -463,7 +463,7 @@ protected internal object Convert(StackItem item, InteropParameterDescriptor des { int count = (int)item.GetInteger(); if (count > Limits.MaxStackSize) throw new InvalidOperationException(); - av = Array.CreateInstance(descriptor.Type.GetElementType()!, count); + av = Array.CreateInstance(descriptor.Type.GetElementType(), count); for (int i = 0; i < av.Length; i++) av.SetValue(descriptor.Converter(Pop()), i); } @@ -498,14 +498,14 @@ public override void Dispose() /// The requirements to check. internal protected void ValidateCallFlags(CallFlags requiredCallFlags) { - ExecutionContextState? state = CurrentContext?.GetState(); - if (state == null || !state.CallFlags.HasFlag(requiredCallFlags)) - throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state?.CallFlags}."); + ExecutionContextState state = CurrentContext.GetState(); + if (!state.CallFlags.HasFlag(requiredCallFlags)) + throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state.CallFlags}."); } protected override void OnSysCall(uint method) { - OnSysCall(services![method]); + OnSysCall(services[method]); } /// @@ -521,8 +521,8 @@ protected virtual void OnSysCall(InteropDescriptor descriptor) for (int i = 0; i < parameters.Length; i++) parameters[i] = Convert(Pop(), descriptor.Parameters[i]); - object? returnValue = descriptor.Handler.Invoke(this, parameters); - if (returnValue is not null && descriptor.Handler.ReturnType != typeof(void)) + object returnValue = descriptor.Handler.Invoke(this, parameters); + if (descriptor.Handler.ReturnType != typeof(void)) Push(Convert(returnValue)); } @@ -541,7 +541,7 @@ protected override void PostExecuteInstruction(Instruction instruction) private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings settings) { UInt256 hash = NativeContract.Ledger.CurrentHash(snapshot); - Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash)!; + Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash); return new Block { Header = new Header @@ -565,7 +565,7 @@ private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings setti private static InteropDescriptor Register(string name, string handler, long fixedPrice, CallFlags requiredCallFlags) { MethodInfo method = typeof(ApplicationEngine).GetMethod(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) - ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)!.GetMethod!; + ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).GetMethod; InteropDescriptor descriptor = new() { Name = name, @@ -590,7 +590,7 @@ private static InteropDescriptor Register(string name, string handler, long fixe /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable? container = null, Block? persistingBlock = null, ProtocolSettings? settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic? diagnostic = null) + public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable container = null, Block persistingBlock = null, ProtocolSettings settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic diagnostic = null) { persistingBlock ??= CreateDummyBlock(snapshot, settings ?? ProtocolSettings.Default); ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -601,38 +601,35 @@ public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snaps public T GetState() { - if (states is null) return default!; - if (!states.TryGetValue(typeof(T), out object? state)) return default!; + if (states is null) return default; + if (!states.TryGetValue(typeof(T), out object state)) return default; return (T)state; } public void SetState(T state) { states ??= new Dictionary(); - if (state != null) - { - states[typeof(T)] = state; - } + states[typeof(T)] = state; } public bool IsHardforkEnabled(Hardfork hardfork) { // Return true if there's no specific configuration or PersistingBlock is null - if (PersistingBlock is null || ProtocolSettings?.Hardforks.Count == 0) + if (PersistingBlock is null || ProtocolSettings.Hardforks.Count == 0) return true; // If the hardfork isn't specified in the configuration, check if it's a new one. - if (ProtocolSettings is not null && !ProtocolSettings!.Hardforks.ContainsKey(hardfork)) + if (!ProtocolSettings.Hardforks.ContainsKey(hardfork)) { int currentHardforkIndex = AllHardforks.IndexOf(hardfork); - int lastConfiguredHardforkIndex = AllHardforks.IndexOf(ProtocolSettings!.Hardforks.Keys.Last()); + int lastConfiguredHardforkIndex = AllHardforks.IndexOf(ProtocolSettings.Hardforks.Keys.Last()); // If it's a newer hardfork compared to the ones in the configuration, disable it. if (currentHardforkIndex > lastConfiguredHardforkIndex) return false; } - if (ProtocolSettings is not null && ProtocolSettings!.Hardforks.TryGetValue(hardfork, out uint height)) + if (ProtocolSettings.Hardforks.TryGetValue(hardfork, out uint height)) { // If the hardfork has a specific height in the configuration, check the block height. return PersistingBlock.Index >= height; diff --git a/src/Neo/SmartContract/BinarySerializer.cs b/src/Neo/SmartContract/BinarySerializer.cs index 14236e139a..2bdeced678 100644 --- a/src/Neo/SmartContract/BinarySerializer.cs +++ b/src/Neo/SmartContract/BinarySerializer.cs @@ -39,7 +39,7 @@ public ContainerPlaceholder(StackItemType type, int count) ElementCount = count; } - public override bool Equals(StackItem? other) => throw new NotSupportedException(); + public override bool Equals(StackItem other) => throw new NotSupportedException(); public override int GetHashCode() => throw new NotSupportedException(); @@ -53,7 +53,7 @@ public ContainerPlaceholder(StackItemType type, int count) /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) + public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) { MemoryReader reader = new(data); return Deserialize(ref reader, (uint)Math.Min(data.Length, limits.MaxItemSize), limits.MaxStackSize, referenceCounter); @@ -66,7 +66,7 @@ public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLi /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) { return Deserialize(ref reader, limits.MaxItemSize, limits.MaxStackSize, referenceCounter); } @@ -79,7 +79,7 @@ public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimi /// The max of items to serialize /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter? referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter referenceCounter = null) { Stack deserialized = new(); int undeserialized = 1; diff --git a/src/Neo/SmartContract/Contract.cs b/src/Neo/SmartContract/Contract.cs index 45f8a3fe8b..dc60c42d50 100644 --- a/src/Neo/SmartContract/Contract.cs +++ b/src/Neo/SmartContract/Contract.cs @@ -25,14 +25,14 @@ public class Contract /// /// The script of the contract. /// - public byte[]? Script; + public byte[] Script; /// /// The parameters of the contract. /// - public ContractParameterType[] ParameterList = Array.Empty(); + public ContractParameterType[] ParameterList; - private UInt160? _scriptHash; + private UInt160 _scriptHash; /// /// The hash of the contract. /// @@ -42,9 +42,9 @@ public virtual UInt160 ScriptHash { if (_scriptHash == null) { - _scriptHash = Script?.ToScriptHash(); + _scriptHash = Script.ToScriptHash(); } - return _scriptHash!; + return _scriptHash; } } diff --git a/src/Neo/SmartContract/ContractParameter.cs b/src/Neo/SmartContract/ContractParameter.cs index a289156726..027fa50e00 100644 --- a/src/Neo/SmartContract/ContractParameter.cs +++ b/src/Neo/SmartContract/ContractParameter.cs @@ -10,7 +10,6 @@ // modifications are permitted. using Neo.Cryptography.ECC; -using Neo.IO; using Neo.Json; using System; using System.Collections.Generic; @@ -33,7 +32,7 @@ public class ContractParameter /// /// The value of the parameter. /// - public object? Value; + public object Value; /// /// Initializes a new instance of the class. @@ -73,21 +72,20 @@ public static ContractParameter FromJson(JObject json) { ContractParameter parameter = new() { - Type = Enum.Parse(json["type"]!.GetString()) + Type = Enum.Parse(json["type"].GetString()) }; - var value = json["value"]; - if (value != null) + if (json["value"] != null) parameter.Value = parameter.Type switch { - ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(value.AsString()), - ContractParameterType.Boolean => value.AsBoolean(), - ContractParameterType.Integer => BigInteger.Parse(value.AsString()), - ContractParameterType.Hash160 => UInt160.Parse(value.AsString()), - ContractParameterType.Hash256 => UInt256.Parse(value.AsString()), - ContractParameterType.PublicKey => ECPoint.Parse(value.AsString(), ECCurve.Secp256r1), - ContractParameterType.String => value.AsString(), - ContractParameterType.Array => ((JArray)value).Select(p => FromJson(p.NullExceptionOr())).ToList(), - ContractParameterType.Map => ((JArray)value).Select(p => new KeyValuePair(FromJson((JObject)p!["key"]!), FromJson(p["value"].NullExceptionOr()))).ToList(), + ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(json["value"].AsString()), + ContractParameterType.Boolean => json["value"].AsBoolean(), + ContractParameterType.Integer => BigInteger.Parse(json["value"].AsString()), + ContractParameterType.Hash160 => UInt160.Parse(json["value"].AsString()), + ContractParameterType.Hash256 => UInt256.Parse(json["value"].AsString()), + ContractParameterType.PublicKey => ECPoint.Parse(json["value"].AsString(), ECCurve.Secp256r1), + ContractParameterType.String => json["value"].AsString(), + ContractParameterType.Array => ((JArray)json["value"]).Select(p => FromJson((JObject)p)).ToList(), + ContractParameterType.Map => ((JArray)json["value"]).Select(p => new KeyValuePair(FromJson((JObject)p["key"]), FromJson((JObject)p["value"]))).ToList(), _ => throw new ArgumentException(null, nameof(json)), }; return parameter; @@ -141,7 +139,7 @@ public JObject ToJson() return ToJson(this, null); } - private static JObject ToJson(ContractParameter parameter, HashSet? context) + private static JObject ToJson(ContractParameter parameter, HashSet context) { JObject json = new(); json["type"] = parameter.Type; @@ -193,7 +191,7 @@ public override string ToString() return ToString(this, null); } - private static string ToString(ContractParameter parameter, HashSet? context) + private static string ToString(ContractParameter parameter, HashSet context) { switch (parameter.Value) { @@ -248,7 +246,7 @@ private static string ToString(ContractParameter parameter, HashSet Signatures; public ContextItem(Contract contract) { - this.Script = contract.Script!; + this.Script = contract.Script; this.Parameters = contract.ParameterList.Select(p => new ContractParameter { Type = p }).ToArray(); this.Signatures = new Dictionary(); } public ContextItem(JObject json) { - this.Script = Convert.FromBase64String(json["script"]!.AsString()); - this.Parameters = json["parameters"].NullExceptionOr().Select(p => ContractParameter.FromJson(p.NullExceptionOr())).ToArray(); - this.Signatures = json["signatures"].NullExceptionOr().Properties.Select(p => new + this.Script = Convert.FromBase64String(json["script"].AsString()); + this.Parameters = ((JArray)json["parameters"]).Select(p => ContractParameter.FromJson((JObject)p)).ToArray(); + this.Signatures = ((JObject)json["signatures"]).Properties.Select(p => new { PublicKey = ECPoint.Parse(p.Key, ECCurve.Secp256r1), - Signature = Convert.FromBase64String(p.Value!.AsString()) + Signature = Convert.FromBase64String(p.Value.AsString()) }).ToDictionary(p => p.PublicKey, p => p.Signature); } public JObject ToJson() { JObject json = new(); - json["script"] = Convert.ToBase64String(Script!); + json["script"] = Convert.ToBase64String(Script); json["parameters"] = new JArray(Parameters.Select(p => p.ToJson())); json["signatures"] = new JObject(); foreach (var signature in Signatures) - json["signatures"]![signature.Key.ToString()] = Convert.ToBase64String(signature.Value); + json["signatures"][signature.Key.ToString()] = Convert.ToBase64String(signature.Value); return json; } } @@ -80,7 +80,7 @@ public JObject ToJson() /// public readonly uint Network; - private readonly Dictionary ContextItems; + private readonly Dictionary ContextItems; /// /// Determines whether all witnesses are ready to be added. @@ -95,7 +95,7 @@ public bool Completed } } - private UInt160[]? _ScriptHashes; + private UInt160[] _ScriptHashes = null; /// /// Gets the script hashes to be verified for the . /// @@ -111,7 +111,7 @@ public ContractParametersContext(DataCache snapshot, IVerifiable verifiable, uin { this.Verifiable = verifiable; this.Snapshot = snapshot; - this.ContextItems = new Dictionary(); + this.ContextItems = new Dictionary(); this.Network = network; } @@ -124,7 +124,7 @@ public ContractParametersContext(DataCache snapshot, IVerifiable verifiable, uin /// if the parameter is added successfully; otherwise, . public bool Add(Contract contract, int index, object parameter) { - ContextItem? item = CreateItem(contract); + ContextItem item = CreateItem(contract); if (item == null) return false; item.Parameters[index].Value = parameter; return true; @@ -138,7 +138,7 @@ public bool Add(Contract contract, int index, object parameter) /// if the parameters are added successfully; otherwise, . public bool Add(Contract contract, params object[] parameters) { - ContextItem? item = CreateItem(contract); + ContextItem item = CreateItem(contract); if (item == null) return false; for (int index = 0; index < parameters.Length; index++) { @@ -156,10 +156,10 @@ public bool Add(Contract contract, params object[] parameters) /// if the signature is added successfully; otherwise, . public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) { - if (IsMultiSigContract(contract.Script, out _, out ECPoint[]? points)) + if (IsMultiSigContract(contract.Script, out _, out ECPoint[] points)) { if (!points.Contains(pubkey)) return false; - ContextItem? item = CreateItem(contract); + ContextItem item = CreateItem(contract); if (item == null) return false; if (item.Parameters.All(p => p.Value != null)) return false; if (!item.Signatures.TryAdd(pubkey, signature)) @@ -198,7 +198,7 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) // return now to prevent array index out of bounds exception return false; } - ContextItem? item = CreateItem(contract); + ContextItem item = CreateItem(contract); if (item == null) return false; if (!item.Signatures.TryAdd(pubkey, signature)) return false; @@ -207,9 +207,9 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) } } - private ContextItem? CreateItem(Contract contract) + private ContextItem CreateItem(Contract contract) { - if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem? item)) + if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem item)) return item; if (!ScriptHashes.Contains(contract.ScriptHash)) return null; @@ -226,22 +226,22 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) /// The converted context. public static ContractParametersContext FromJson(JObject json, DataCache snapshot) { - var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"]!.AsString()); + var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"].AsString()); if (!typeof(IVerifiable).IsAssignableFrom(type)) throw new FormatException(); - var verifiable = (IVerifiable)Activator.CreateInstance(type)!; - byte[] data = Convert.FromBase64String(json["data"]!.AsString()); + var verifiable = (IVerifiable)Activator.CreateInstance(type); + byte[] data = Convert.FromBase64String(json["data"].AsString()); MemoryReader reader = new(data); verifiable.DeserializeUnsigned(ref reader); if (json.ContainsProperty("hash")) { - UInt256? hash = UInt256.Parse(json["hash"]!.GetString()); + UInt256 hash = UInt256.Parse(json["hash"].GetString()); if (hash != verifiable.Hash) throw new FormatException(); } - ContractParametersContext context = new(snapshot, verifiable, (uint)json["network"]!.GetInt32()); - foreach (var (key, value) in ((JObject)json["items"]!).Properties) + ContractParametersContext context = new(snapshot, verifiable, (uint)json["network"].GetInt32()); + foreach (var (key, value) in ((JObject)json["items"]).Properties) { - context.ContextItems.Add(UInt160.Parse(key), new ContextItem((JObject)value!)); + context.ContextItems.Add(UInt160.Parse(key), new ContextItem((JObject)value)); } return context; } @@ -252,7 +252,7 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// The hash of the witness script. /// The specified index. /// The parameter with the specified index. - public ContractParameter? GetParameter(UInt160 scriptHash, int index) + public ContractParameter GetParameter(UInt160 scriptHash, int index) { return GetParameters(scriptHash)?[index]; } @@ -262,11 +262,11 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// /// The hash of the witness script. /// The parameters from the witness script. - public IReadOnlyList? GetParameters(UInt160 scriptHash) + public IReadOnlyList GetParameters(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) return null; - return item?.Parameters; + return item.Parameters; } /// @@ -274,11 +274,11 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// /// The hash of the witness script. /// The signatures from the witness script. - public IReadOnlyDictionary? GetSignatures(UInt160 scriptHash) + public IReadOnlyDictionary GetSignatures(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) return null; - return item?.Signatures; + return item.Signatures; } /// @@ -286,11 +286,11 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// /// The hash of the witness script. /// The witness script. - public byte[]? GetScript(UInt160 scriptHash) + public byte[] GetScript(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) return null; - return item?.Script; + return item.Script; } /// @@ -304,8 +304,7 @@ public Witness[] GetWitnesses() Witness[] witnesses = new Witness[ScriptHashes.Count]; for (int i = 0; i < ScriptHashes.Count; i++) { - ContextItem? item = ContextItems[ScriptHashes[i]]; - if (item == null) continue; + ContextItem item = ContextItems[ScriptHashes[i]]; using ScriptBuilder sb = new(); for (int j = item.Parameters.Length - 1; j >= 0; j--) { @@ -328,7 +327,7 @@ public Witness[] GetWitnesses() /// The parsed context. public static ContractParametersContext Parse(string value, DataCache snapshot) { - return FromJson((JObject)JToken.Parse(value)!, snapshot); + return FromJson((JObject)JToken.Parse(value), snapshot); } /// @@ -349,7 +348,7 @@ public JObject ToJson() } json["items"] = new JObject(); foreach (var item in ContextItems) - json["items"]![item.Key.ToString()] = item!.Value!.ToJson(); + json["items"][item.Key.ToString()] = item.Value.ToJson(); json["network"] = Network; return json; } diff --git a/src/Neo/SmartContract/ContractState.cs b/src/Neo/SmartContract/ContractState.cs index 873b65f514..83ac9d3353 100644 --- a/src/Neo/SmartContract/ContractState.cs +++ b/src/Neo/SmartContract/ContractState.cs @@ -38,17 +38,17 @@ public class ContractState : IInteroperable /// /// The hash of the contract. /// - public UInt160 Hash = null!; + public UInt160 Hash; /// /// The nef of the contract. /// - public NefFile Nef = null!; + public NefFile Nef; /// /// The manifest of the contract. /// - public ContractManifest Manifest = null!; + public ContractManifest Manifest; /// /// The script of the contract. @@ -114,9 +114,9 @@ public JObject ToJson() }; } - public StackItem ToStackItem(ReferenceCounter? referenceCounter) + public StackItem ToStackItem(ReferenceCounter referenceCounter) { - return new Array(referenceCounter, new[] { Id, (int)UpdateCounter, Hash.ToArray(), Nef.ToArray(), Manifest.ToStackItem(referenceCounter) }); + return new Array(referenceCounter, new StackItem[] { Id, (int)UpdateCounter, Hash.ToArray(), Nef.ToArray(), Manifest.ToStackItem(referenceCounter) }); } } } diff --git a/src/Neo/SmartContract/ContractTask.cs b/src/Neo/SmartContract/ContractTask.cs index 72d4b91472..6df3627c37 100644 --- a/src/Neo/SmartContract/ContractTask.cs +++ b/src/Neo/SmartContract/ContractTask.cs @@ -33,7 +33,7 @@ public ContractTask() protected virtual ContractTaskAwaiter CreateAwaiter() => new(); public virtual ContractTaskAwaiter GetAwaiter() => awaiter; - public virtual object? GetResult() => null; + public virtual object GetResult() => null; } [AsyncMethodBuilder(typeof(ContractTaskMethodBuilder<>))] @@ -41,6 +41,6 @@ class ContractTask : ContractTask { protected override ContractTaskAwaiter CreateAwaiter() => new ContractTaskAwaiter(); public override ContractTaskAwaiter GetAwaiter() => (ContractTaskAwaiter)base.GetAwaiter(); - public override object? GetResult() => ((ContractTaskAwaiter)GetAwaiter()).GetResult(); + public override object GetResult() => ((ContractTaskAwaiter)GetAwaiter()).GetResult(); } } diff --git a/src/Neo/SmartContract/ContractTaskAwaiter.cs b/src/Neo/SmartContract/ContractTaskAwaiter.cs index 2bd23d3fc2..a0a0c9a1bb 100644 --- a/src/Neo/SmartContract/ContractTaskAwaiter.cs +++ b/src/Neo/SmartContract/ContractTaskAwaiter.cs @@ -17,15 +17,15 @@ namespace Neo.SmartContract { class ContractTaskAwaiter : INotifyCompletion { - private Action _continuation = null!; - private Exception _exception = null!; + private Action continuation; + private Exception exception; public bool IsCompleted { get; private set; } public void GetResult() { - if (_exception is not null) - throw _exception; + if (exception is not null) + throw exception; } public void SetResult() => RunContinuation(); @@ -34,35 +34,35 @@ public void GetResult() public void SetException(Exception exception) { - this._exception = exception; + this.exception = exception; RunContinuation(); } public void OnCompleted(Action continuation) { - Interlocked.CompareExchange(ref this._continuation, continuation, null); + Interlocked.CompareExchange(ref this.continuation, continuation, null); } protected void RunContinuation() { IsCompleted = true; - _continuation.Invoke(); + continuation?.Invoke(); } } class ContractTaskAwaiter : ContractTaskAwaiter { - private T _result = default!; + private T result; public new T GetResult() { base.GetResult(); - return _result; + return result; } public void SetResult(T result) { - this._result = result; + this.result = result; RunContinuation(); } diff --git a/src/Neo/SmartContract/ContractTaskMethodBuilder.cs b/src/Neo/SmartContract/ContractTaskMethodBuilder.cs index 2cf6030635..bae1146f25 100644 --- a/src/Neo/SmartContract/ContractTaskMethodBuilder.cs +++ b/src/Neo/SmartContract/ContractTaskMethodBuilder.cs @@ -16,7 +16,7 @@ namespace Neo.SmartContract { sealed class ContractTaskMethodBuilder { - private ContractTask? task; + private ContractTask task; public ContractTask Task => task ??= new ContractTask(); @@ -58,7 +58,7 @@ public void SetStateMachine(IAsyncStateMachine stateMachine) sealed class ContractTaskMethodBuilder { - private ContractTask? task; + private ContractTask task; public ContractTask Task => task ??= new ContractTask(); diff --git a/src/Neo/SmartContract/DeployedContract.cs b/src/Neo/SmartContract/DeployedContract.cs index 4ea6c7845d..0587a029e5 100644 --- a/src/Neo/SmartContract/DeployedContract.cs +++ b/src/Neo/SmartContract/DeployedContract.cs @@ -32,7 +32,7 @@ public DeployedContract(ContractState contract) Script = null; ScriptHash = contract.Hash; - ContractMethodDescriptor? descriptor = contract.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod("verify", -1); if (descriptor is null) throw new NotSupportedException("The smart contract haven't got verify method."); ParameterList = descriptor.Parameters.Select(u => u.Type).ToArray(); diff --git a/src/Neo/SmartContract/ExecutionContextState.cs b/src/Neo/SmartContract/ExecutionContextState.cs index abbdfb3aa1..8b61ff1197 100644 --- a/src/Neo/SmartContract/ExecutionContextState.cs +++ b/src/Neo/SmartContract/ExecutionContextState.cs @@ -22,29 +22,29 @@ public class ExecutionContextState /// /// The script hash of the current context. /// - public UInt160? ScriptHash { get; set; } + public UInt160 ScriptHash { get; set; } /// /// The calling context. /// - public ExecutionContext CallingContext { get; set; } = null!; + public ExecutionContext CallingContext { get; set; } /// /// The script hash of the calling native contract. Used in native contracts only. /// - internal UInt160? NativeCallingScriptHash { get; set; } + internal UInt160 NativeCallingScriptHash { get; set; } /// /// The of the current context. /// - public ContractState Contract { get; set; } = null!; + public ContractState Contract { get; set; } /// /// The of the current context. /// public CallFlags CallFlags { get; set; } = CallFlags.All; - public DataCache Snapshot { get; set; } = null!; + public DataCache Snapshot { get; set; } public int NotificationCount { get; set; } diff --git a/src/Neo/SmartContract/Helper.cs b/src/Neo/SmartContract/Helper.cs index 1b12b2fd28..5045c74717 100644 --- a/src/Neo/SmartContract/Helper.cs +++ b/src/Neo/SmartContract/Helper.cs @@ -20,7 +20,6 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Neo.SmartContract @@ -111,7 +110,7 @@ public static UInt160 GetContractHash(UInt160 sender, uint nefCheckSum, string n /// The script hash of the context. public static UInt160 GetScriptHash(this ExecutionContext context) { - return context.GetState().ScriptHash!; + return context.GetState().ScriptHash; } /// @@ -143,7 +142,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out /// The minimum number of correct signatures that need to be provided in order for the verification to pass. /// The public keys in the account. /// if the contract is a multi-signature contract; otherwise, . - public static bool IsMultiSigContract(ReadOnlySpan script, out int m, [NotNullWhen(true)] out ECPoint[]? points) + public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out ECPoint[] points) { List list = new(); if (IsMultiSigContract(script, out m, out _, list)) @@ -158,7 +157,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, [Not } } - private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List? points) + private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List points) { m = 0; n = 0; int i = 0; @@ -317,13 +316,13 @@ internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings { return false; } - using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot.CreateSnapshot(), null, settings, gas)) + using (ApplicationEngine engine = ApplicationEngine.Create(TriggerType.Verification, verifiable, snapshot?.CreateSnapshot(), null, settings, gas)) { if (witness.VerificationScript.Length == 0) { - ContractState? cs = NativeContract.ContractManagement.GetContract(snapshot, hash); + ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash); if (cs is null) return false; - ContractMethodDescriptor? md = cs.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify", -1); if (md?.ReturnType != ContractParameterType.Boolean) return false; engine.LoadContract(cs, md, CallFlags.ReadOnly); } diff --git a/src/Neo/SmartContract/IApplicationEngineProvider.cs b/src/Neo/SmartContract/IApplicationEngineProvider.cs index d39286fda8..ef06c6b92c 100644 --- a/src/Neo/SmartContract/IApplicationEngineProvider.cs +++ b/src/Neo/SmartContract/IApplicationEngineProvider.cs @@ -30,6 +30,6 @@ public interface IApplicationEngineProvider /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic); + ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic); } } diff --git a/src/Neo/SmartContract/IInteroperable.cs b/src/Neo/SmartContract/IInteroperable.cs index d9009625b1..5254898efe 100644 --- a/src/Neo/SmartContract/IInteroperable.cs +++ b/src/Neo/SmartContract/IInteroperable.cs @@ -31,7 +31,7 @@ public interface IInteroperable /// /// The used by the . /// The converted . - StackItem ToStackItem(ReferenceCounter? referenceCounter); + StackItem ToStackItem(ReferenceCounter referenceCounter); public IInteroperable Clone() { diff --git a/src/Neo/SmartContract/InteropDescriptor.cs b/src/Neo/SmartContract/InteropDescriptor.cs index f21ba88b49..29c88f46ed 100644 --- a/src/Neo/SmartContract/InteropDescriptor.cs +++ b/src/Neo/SmartContract/InteropDescriptor.cs @@ -26,7 +26,7 @@ public record InteropDescriptor /// /// The name of the interoperable service. /// - public string Name { get; init; } = null!; + public string Name { get; init; } private uint _hash; /// @@ -45,9 +45,9 @@ public uint Hash /// /// The used to handle the interoperable service. /// - public MethodInfo Handler { get; init; } = null!; + public MethodInfo Handler { get; init; } - private IReadOnlyList? _parameters; + private IReadOnlyList _parameters; /// /// The parameters of the interoperable service. /// diff --git a/src/Neo/SmartContract/InteropParameterDescriptor.cs b/src/Neo/SmartContract/InteropParameterDescriptor.cs index 603c91f3ad..6a65beb93f 100644 --- a/src/Neo/SmartContract/InteropParameterDescriptor.cs +++ b/src/Neo/SmartContract/InteropParameterDescriptor.cs @@ -24,12 +24,12 @@ namespace Neo.SmartContract /// public class InteropParameterDescriptor { - private readonly ValidatorAttribute[] validators = null!; + private readonly ValidatorAttribute[] validators; /// /// The name of the parameter. /// - public string Name { get; } = null!; + public string Name { get; } /// /// The type of the parameter. @@ -56,7 +56,7 @@ public class InteropParameterDescriptor /// public bool IsInterface { get; } - private static readonly Dictionary> converters = new() + private static readonly Dictionary> converters = new() { [typeof(StackItem)] = p => p, [typeof(VM.Types.Pointer)] = p => p, @@ -82,7 +82,7 @@ public class InteropParameterDescriptor internal InteropParameterDescriptor(ParameterInfo parameterInfo) : this(parameterInfo.ParameterType) { - this.Name = parameterInfo.Name!; + this.Name = parameterInfo.Name; this.validators = parameterInfo.GetCustomAttributes(true).ToArray(); } @@ -91,19 +91,19 @@ internal InteropParameterDescriptor(Type type) this.Type = type; if (IsEnum) { - Converter = converters[type.GetEnumUnderlyingType()]!; + Converter = converters[type.GetEnumUnderlyingType()]; } else if (IsArray) { - Converter = converters[type.GetElementType()!]!; + Converter = converters[type.GetElementType()]; } else { IsInterface = !converters.TryGetValue(type, out var converter); if (IsInterface) - Converter = converters[typeof(InteropInterface)]!; + Converter = converters[typeof(InteropInterface)]; else - Converter = converter!; + Converter = converter; } } From 9960d060c9d91f0cade68036eb5961712ce56f1d Mon Sep 17 00:00:00 2001 From: Jimmy Date: Thu, 8 Feb 2024 15:52:36 +0800 Subject: [PATCH 16/36] nullable manifest --- src/Neo/SmartContract/Manifest/ContractAbi.cs | 14 +++---- .../Manifest/ContractEventDescriptor.cs | 13 ++++--- .../SmartContract/Manifest/ContractGroup.cs | 10 ++--- .../Manifest/ContractManifest.cs | 38 +++++++++---------- .../Manifest/ContractMethodDescriptor.cs | 13 ++++--- .../Manifest/ContractParameterDefinition.cs | 10 ++--- .../Manifest/ContractPermission.cs | 20 +++++----- .../Manifest/ContractPermissionDescriptor.cs | 24 ++++++------ .../Manifest/WildCardContainer.cs | 12 +++--- 9 files changed, 78 insertions(+), 76 deletions(-) diff --git a/src/Neo/SmartContract/Manifest/ContractAbi.cs b/src/Neo/SmartContract/Manifest/ContractAbi.cs index 3660d1a99e..b9df716799 100644 --- a/src/Neo/SmartContract/Manifest/ContractAbi.cs +++ b/src/Neo/SmartContract/Manifest/ContractAbi.cs @@ -25,17 +25,17 @@ namespace Neo.SmartContract.Manifest /// For more details, see NEP-14. public class ContractAbi : IInteroperable { - private IReadOnlyDictionary<(string, int), ContractMethodDescriptor> methodDictionary; + private IReadOnlyDictionary<(string, int), ContractMethodDescriptor>? methodDictionary; /// /// Gets the methods in the ABI. /// - public ContractMethodDescriptor[] Methods { get; set; } + public ContractMethodDescriptor[] Methods { get; set; } = null!; /// /// Gets the events in the ABI. /// - public ContractEventDescriptor[] Events { get; set; } + public ContractEventDescriptor[] Events { get; set; } = null!; void IInteroperable.FromStackItem(StackItem stackItem) { @@ -44,7 +44,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) Events = ((Array)@struct[1]).Select(p => p.ToInteroperable()).ToArray(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { @@ -62,8 +62,8 @@ public static ContractAbi FromJson(JObject json) { ContractAbi abi = new() { - Methods = ((JArray)json["methods"]).Select(u => ContractMethodDescriptor.FromJson((JObject)u)).ToArray(), - Events = ((JArray)json["events"]).Select(u => ContractEventDescriptor.FromJson((JObject)u)).ToArray() + Methods = json["methods"].NullExceptionOr().Select(u => ContractMethodDescriptor.FromJson(u.NullExceptionOr())).ToArray(), + Events = json["events"].NullExceptionOr().Select(u => ContractEventDescriptor.FromJson(u.NullExceptionOr())).ToArray() }; if (abi.Methods.Length == 0) throw new FormatException(); return abi; @@ -75,7 +75,7 @@ public static ContractAbi FromJson(JObject json) /// The name of the method. /// The number of parameters of the method. It can be set to -1 to search for the method with the specified name and any number of parameters. /// The method that matches the specified name and number of parameters. If is set to -1, the first method with the specified name will be returned. - public ContractMethodDescriptor GetMethod(string name, int pcount) + public ContractMethodDescriptor? GetMethod(string name, int pcount) { if (pcount < -1 || pcount > ushort.MaxValue) throw new ArgumentOutOfRangeException(nameof(pcount)); if (pcount >= 0) diff --git a/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs index 90227dd78d..7a637c12cc 100644 --- a/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractEventDescriptor.cs @@ -9,6 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.IO; using Neo.Json; using Neo.VM; using Neo.VM.Types; @@ -26,21 +27,21 @@ public class ContractEventDescriptor : IInteroperable /// /// The name of the event or method. /// - public string Name { get; set; } + public string Name { get; set; } = null!; /// /// The parameters of the event or method. /// - public ContractParameterDefinition[] Parameters { get; set; } + public ContractParameterDefinition[] Parameters { get; set; } = null!; public virtual void FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; - Name = @struct[0].GetString(); + Name = @struct[0].GetString()!; Parameters = ((Array)@struct[1]).Select(p => p.ToInteroperable()).ToArray(); } - public virtual StackItem ToStackItem(ReferenceCounter referenceCounter) + public virtual StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { @@ -58,8 +59,8 @@ public static ContractEventDescriptor FromJson(JObject json) { ContractEventDescriptor descriptor = new() { - Name = json["name"].GetString(), - Parameters = ((JArray)json["parameters"]).Select(u => ContractParameterDefinition.FromJson((JObject)u)).ToArray(), + Name = json["name"]!.GetString(), + Parameters = json["parameters"].NullExceptionOr().Select(u => ContractParameterDefinition.FromJson(u.NullExceptionOr())).ToArray(), }; if (string.IsNullOrEmpty(descriptor.Name)) throw new FormatException(); _ = descriptor.Parameters.ToDictionary(p => p.Name); diff --git a/src/Neo/SmartContract/Manifest/ContractGroup.cs b/src/Neo/SmartContract/Manifest/ContractGroup.cs index 231354327c..b24ba00613 100644 --- a/src/Neo/SmartContract/Manifest/ContractGroup.cs +++ b/src/Neo/SmartContract/Manifest/ContractGroup.cs @@ -29,12 +29,12 @@ public class ContractGroup : IInteroperable /// /// The public key of the group. /// - public ECPoint PubKey { get; set; } + public ECPoint PubKey { get; set; } = null!; /// /// The signature of the contract hash which can be verified by . /// - public byte[] Signature { get; set; } + public byte[] Signature { get; set; } = null!; void IInteroperable.FromStackItem(StackItem stackItem) { @@ -43,7 +43,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) Signature = @struct[1].GetSpan().ToArray(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { PubKey.ToArray(), Signature }; } @@ -57,8 +57,8 @@ public static ContractGroup FromJson(JObject json) { ContractGroup group = new() { - PubKey = ECPoint.Parse(json["pubkey"].GetString(), ECCurve.Secp256r1), - Signature = Convert.FromBase64String(json["signature"].GetString()), + PubKey = ECPoint.Parse(json["pubkey"]!.GetString(), ECCurve.Secp256r1), + Signature = Convert.FromBase64String(json["signature"]!.GetString()), }; if (group.Signature.Length != 64) throw new FormatException(); return group; diff --git a/src/Neo/SmartContract/Manifest/ContractManifest.cs b/src/Neo/SmartContract/Manifest/ContractManifest.cs index 078e8fd35e..55036e2c72 100644 --- a/src/Neo/SmartContract/Manifest/ContractManifest.cs +++ b/src/Neo/SmartContract/Manifest/ContractManifest.cs @@ -35,47 +35,47 @@ public class ContractManifest : IInteroperable /// /// The name of the contract. /// - public string Name { get; set; } + public string Name { get; set; } = null!; /// /// The groups of the contract. /// - public ContractGroup[] Groups { get; set; } + public ContractGroup[] Groups { get; set; } = null!; /// /// Indicates which standards the contract supports. It can be a list of NEPs. /// - public string[] SupportedStandards { get; set; } + public string[] SupportedStandards { get; set; } = null!; /// /// The ABI of the contract. /// - public ContractAbi Abi { get; set; } + public ContractAbi Abi { get; set; } = null!; /// /// The permissions of the contract. /// - public ContractPermission[] Permissions { get; set; } + public ContractPermission[] Permissions { get; set; } = null!; /// /// The trusted contracts and groups of the contract. /// If a contract is trusted, the user interface will not give any warnings when called by the contract. /// - public WildcardContainer Trusts { get; set; } + public WildcardContainer Trusts { get; set; } = null!; /// /// Custom user data. /// - public JObject Extra { get; set; } + public JObject? Extra { get; set; } void IInteroperable.FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; - Name = @struct[0].GetString(); + Name = @struct[0].GetString().NullExceptionOr(); Groups = ((Array)@struct[1]).Select(p => p.ToInteroperable()).ToArray(); if (((Map)@struct[2]).Count != 0) throw new ArgumentException(null, nameof(stackItem)); - SupportedStandards = ((Array)@struct[3]).Select(p => p.GetString()).ToArray(); + SupportedStandards = @struct[3].NullExceptionOr().Select(p => p.GetString()).ToArray()!; Abi = @struct[4].ToInteroperable(); Permissions = ((Array)@struct[5]).Select(p => p.ToInteroperable()).ToArray(); Trusts = @struct[6] switch @@ -85,10 +85,10 @@ void IInteroperable.FromStackItem(StackItem stackItem) Array array => WildcardContainer.Create(array.Select(ContractPermissionDescriptor.Create).ToArray()), _ => throw new ArgumentException(null, nameof(stackItem)) }; - Extra = (JObject)JToken.Parse(@struct[7].GetSpan()); + Extra = (JObject)JToken.Parse(@struct[7].GetSpan())!; } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { @@ -112,13 +112,13 @@ public static ContractManifest FromJson(JObject json) { ContractManifest manifest = new() { - Name = json["name"].GetString(), - Groups = ((JArray)json["groups"]).Select(u => ContractGroup.FromJson((JObject)u)).ToArray(), - SupportedStandards = ((JArray)json["supportedstandards"]).Select(u => u.GetString()).ToArray(), - Abi = ContractAbi.FromJson((JObject)json["abi"]), - Permissions = ((JArray)json["permissions"]).Select(u => ContractPermission.FromJson((JObject)u)).ToArray(), - Trusts = WildcardContainer.FromJson(json["trusts"], u => ContractPermissionDescriptor.FromJson((JString)u)), - Extra = (JObject)json["extra"] + Name = json["name"]!.GetString(), + Groups = json["groups"].NullExceptionOr().Select(u => ContractGroup.FromJson(u.NullExceptionOr())).ToArray(), + SupportedStandards = json["supportedstandards"].NullExceptionOr().Select(u => u!.GetString()).ToArray(), + Abi = ContractAbi.FromJson(json["abi"].NullExceptionOr()), + Permissions = json["permissions"].NullExceptionOr().Select(u => ContractPermission.FromJson(u.NullExceptionOr())).ToArray(), + Trusts = WildcardContainer.FromJson(json["trusts"]!, u => ContractPermissionDescriptor.FromJson((JString)u)), + Extra = (JObject?)json["extra"] }; if (string.IsNullOrEmpty(manifest.Name)) throw new FormatException(); @@ -141,7 +141,7 @@ public static ContractManifest FromJson(JObject json) public static ContractManifest Parse(ReadOnlySpan json) { if (json.Length > MaxLength) throw new ArgumentException(null, nameof(json)); - return FromJson((JObject)JToken.Parse(json)); + return FromJson(JToken.Parse(json).NullExceptionOr()); } /// diff --git a/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs index cc8d0a16d5..84ee8b2963 100644 --- a/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractMethodDescriptor.cs @@ -9,6 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.IO; using Neo.Json; using Neo.VM; using Neo.VM.Types; @@ -47,7 +48,7 @@ public override void FromStackItem(StackItem stackItem) Safe = @struct[4].GetBoolean(); } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { Struct @struct = (Struct)base.ToStackItem(referenceCounter); @struct.Add((byte)ReturnType); @@ -65,11 +66,11 @@ public override StackItem ToStackItem(ReferenceCounter referenceCounter) { ContractMethodDescriptor descriptor = new() { - Name = json["name"].GetString(), - Parameters = ((JArray)json["parameters"]).Select(u => ContractParameterDefinition.FromJson((JObject)u)).ToArray(), - ReturnType = Enum.Parse(json["returntype"].GetString()), - Offset = json["offset"].GetInt32(), - Safe = json["safe"].GetBoolean() + Name = json["name"]!.GetString(), + Parameters = json["parameters"].NullExceptionOr().Select(u => ContractParameterDefinition.FromJson(u.NullExceptionOr())).ToArray(), + ReturnType = Enum.Parse(json["returntype"]!.GetString()), + Offset = json["offset"]!.GetInt32(), + Safe = json["safe"]!.GetBoolean() }; if (string.IsNullOrEmpty(descriptor.Name)) throw new FormatException(); _ = descriptor.Parameters.ToDictionary(p => p.Name); diff --git a/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs b/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs index 61906558d0..fd7292e345 100644 --- a/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs +++ b/src/Neo/SmartContract/Manifest/ContractParameterDefinition.cs @@ -24,7 +24,7 @@ public class ContractParameterDefinition : IInteroperable /// /// The name of the parameter. /// - public string Name { get; set; } + public string Name { get; set; } = null!; /// /// The type of the parameter. It can be any value of except . @@ -34,11 +34,11 @@ public class ContractParameterDefinition : IInteroperable void IInteroperable.FromStackItem(StackItem stackItem) { Struct @struct = (Struct)stackItem; - Name = @struct[0].GetString(); + Name = @struct[0].GetString()!; Type = (ContractParameterType)(byte)@struct[1].GetInteger(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { Name, (byte)Type }; } @@ -52,8 +52,8 @@ public static ContractParameterDefinition FromJson(JObject json) { ContractParameterDefinition parameter = new() { - Name = json["name"].GetString(), - Type = Enum.Parse(json["type"].GetString()) + Name = json["name"]!.GetString(), + Type = Enum.Parse(json["type"]!.GetString()) }; if (string.IsNullOrEmpty(parameter.Name)) throw new FormatException(); diff --git a/src/Neo/SmartContract/Manifest/ContractPermission.cs b/src/Neo/SmartContract/Manifest/ContractPermission.cs index 44c67fd9a1..d9c9d910ed 100644 --- a/src/Neo/SmartContract/Manifest/ContractPermission.cs +++ b/src/Neo/SmartContract/Manifest/ContractPermission.cs @@ -34,14 +34,14 @@ public class ContractPermission : IInteroperable /// If it specifies a public key of a group, then any contract in this group /// may be invoked; If it specifies a wildcard *, then any contract may be invoked. /// - public ContractPermissionDescriptor Contract { get; set; } + public ContractPermissionDescriptor Contract { get; set; } = null!; /// /// Indicates which methods to be called. /// It can also be assigned with a wildcard *. If it is a wildcard *, /// then it means that any method can be called. /// - public WildcardContainer Methods { get; set; } + public WildcardContainer Methods { get; set; } = null!; /// /// A default permission that both and fields are set to wildcard *. @@ -63,16 +63,16 @@ void IInteroperable.FromStackItem(StackItem stackItem) Methods = @struct[1] switch { Null => WildcardContainer.CreateWildcard(), - Array array => WildcardContainer.Create(array.Select(p => p.GetString()).ToArray()), + Array array => WildcardContainer.Create(array.Select(p => p.GetString()!).ToArray()), _ => throw new ArgumentException(null, nameof(stackItem)) }; } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { - Contract.IsWildcard ? StackItem.Null : Contract.IsHash ? Contract.Hash.ToArray() : Contract.Group.ToArray(), + Contract.IsWildcard ? StackItem.Null : Contract.IsHash ? Contract.Hash!.ToArray() : Contract.Group!.ToArray(), Methods.IsWildcard ? StackItem.Null : new Array(referenceCounter, Methods.Select(p => (StackItem)p)), }; } @@ -86,10 +86,10 @@ public static ContractPermission FromJson(JObject json) { ContractPermission permission = new() { - Contract = ContractPermissionDescriptor.FromJson((JString)json["contract"]), - Methods = WildcardContainer.FromJson(json["methods"], u => u.GetString()), + Contract = ContractPermissionDescriptor.FromJson(json["contract"].NullExceptionOr()), + Methods = WildcardContainer.FromJson(json["methods"]!, u => u.GetString()), }; - if (permission.Methods.Any(p => string.IsNullOrEmpty(p))) + if (permission.Methods.Any(string.IsNullOrEmpty)) throw new FormatException(); _ = permission.Methods.ToDictionary(p => p); return permission; @@ -103,7 +103,7 @@ public JObject ToJson() { var json = new JObject(); json["contract"] = Contract.ToJson(); - json["methods"] = Methods.ToJson(p => p); + json["methods"] = Methods.ToJson(p => p!); return json; } @@ -117,7 +117,7 @@ public bool IsAllowed(ContractState targetContract, string targetMethod) { if (Contract.IsHash) { - if (!Contract.Hash.Equals(targetContract.Hash)) return false; + if (!Contract.Hash!.Equals(targetContract.Hash)) return false; } else if (Contract.IsGroup) { diff --git a/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs b/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs index ce85889423..60b642f07c 100644 --- a/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs +++ b/src/Neo/SmartContract/Manifest/ContractPermissionDescriptor.cs @@ -25,12 +25,12 @@ public class ContractPermissionDescriptor : IEquatable /// The hash of the contract. It can't be set with . /// - public UInt160 Hash { get; } + public UInt160? Hash { get; } /// /// The group of the contracts. It can't be set with . /// - public ECPoint Group { get; } + public ECPoint? Group { get; } /// /// Indicates whether is set. @@ -47,7 +47,7 @@ public class ContractPermissionDescriptor : IEquatable public bool IsWildcard => Hash is null && Group is null; - private ContractPermissionDescriptor(UInt160 hash, ECPoint group) + private ContractPermissionDescriptor(UInt160? hash, ECPoint? group) { this.Hash = hash; this.Group = group; @@ -102,19 +102,19 @@ public static ContractPermissionDescriptor CreateWildcard() return new ContractPermissionDescriptor(null, null); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is not ContractPermissionDescriptor other) return false; return Equals(other); } - public bool Equals(ContractPermissionDescriptor other) + public bool Equals(ContractPermissionDescriptor? other) { if (other is null) return false; - if (this == other) return true; + if (this.Equals(other)) return true; if (IsWildcard == other.IsWildcard) return true; - if (IsHash) return Hash.Equals(other.Hash); - else return Group.Equals(other.Group); + if (IsHash) return Hash!.Equals(other.Hash); + return IsGroup && Group!.Equals(other.Group); } public override int GetHashCode() @@ -145,16 +145,16 @@ public static ContractPermissionDescriptor FromJson(JString json) /// The permission descriptor represented by a JSON object. public JString ToJson() { - if (IsHash) return Hash.ToString(); - if (IsGroup) return Group.ToString(); - return "*"; + if (IsHash) return Hash!.ToString()!; + if (IsGroup) return Group!.ToString()!; + return "*"!; } /// /// Converts the permission descriptor to byte array. /// /// The converted byte array. Or if it is a wildcard. - public byte[] ToArray() + public byte[]? ToArray() { return Hash?.ToArray() ?? Group?.EncodePoint(true); } diff --git a/src/Neo/SmartContract/Manifest/WildCardContainer.cs b/src/Neo/SmartContract/Manifest/WildCardContainer.cs index 3002042d04..56a4df55e8 100644 --- a/src/Neo/SmartContract/Manifest/WildCardContainer.cs +++ b/src/Neo/SmartContract/Manifest/WildCardContainer.cs @@ -23,9 +23,9 @@ namespace Neo.SmartContract.Manifest /// The type of the elements. public class WildcardContainer : IReadOnlyList { - private readonly T[] _data; + private readonly T[]? _data; - public T this[int index] => _data[index]; + public T this[int index] => _data![index]; public int Count => _data?.Length ?? 0; @@ -34,7 +34,7 @@ public class WildcardContainer : IReadOnlyList /// public bool IsWildcard => _data is null; - private WildcardContainer(T[] data) + private WildcardContainer(T[]? data) { _data = data; } @@ -66,7 +66,7 @@ public static WildcardContainer FromJson(JToken json, Func element if (str.Value != "*") throw new FormatException(); return CreateWildcard(); case JArray array: - return Create(array.Select(p => elementSelector(p)).ToArray()); + return Create(array.Select(p => elementSelector(p!)).ToArray()); default: throw new FormatException(); } @@ -87,8 +87,8 @@ public IEnumerator GetEnumerator() /// The list represented by a JSON object. public JToken ToJson(Func elementSelector) { - if (IsWildcard) return "*"; - return _data.Select(p => elementSelector(p)).ToArray(); + if (IsWildcard) return "*"!; + return _data!.Select(p => elementSelector(p)).ToArray(); } } } From b38b6170720e32a327ed171b6463dbb713663da5 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 11:15:51 +0800 Subject: [PATCH 17/36] nullable contract --- src/Neo/Persistence/DataCache.cs | 6 +++--- src/Neo/SmartContract/ApplicationEngine.cs | 20 +++++++++---------- .../SmartContract/ExecutionContextState.cs | 4 ++-- .../Native/ContractManagement.cs | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 6a1a5236bc..31212a7331 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -478,17 +478,17 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) /// /// The key of the entry. /// The cached data. Or if it is neither in the cache nor in the underlying storage. - public StorageItem TryGet(StorageKey key) + public StorageItem? TryGet(StorageKey key) { lock (dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (dictionary.TryGetValue(key, out Trackable? trackable)) { if (trackable.State == TrackState.Deleted || trackable.State == TrackState.NotFound) return null; return trackable.Item; } - StorageItem value = TryGetInternal(key); + StorageItem? value = TryGetInternal(key); if (value == null) return null; dictionary.Add(key, new Trackable { diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index ba161e6951..e983909cb8 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -51,9 +51,9 @@ public partial class ApplicationEngine : ExecutionEngine private static Dictionary services; private readonly long gas_amount; private Dictionary states; - private readonly DataCache originalSnapshot; - private List notifications; - private List disposables; + private readonly DataCache? originalSnapshot; + private List? notifications; + private List? disposables; private readonly Dictionary invocationCounter = new(); private readonly Dictionary contractTasks = new(); internal readonly uint ExecFeeFactor; @@ -63,7 +63,7 @@ public partial class ApplicationEngine : ExecutionEngine /// /// Gets or sets the provider used to create the . /// - public static IApplicationEngineProvider Provider { get; set; } + public static IApplicationEngineProvider? Provider { get; set; } /// /// Gets the descriptors of all interoperable services available in NEO. @@ -120,12 +120,12 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The script hash of the current context. This field could be if no context is loaded to the engine. /// - public UInt160 CurrentScriptHash => CurrentContext?.GetScriptHash(); + public UInt160? CurrentScriptHash => CurrentContext?.GetScriptHash(); /// /// The script hash of the calling contract. This field could be if the current context is the entry context. /// - public UInt160 CallingScriptHash + public UInt160? CallingScriptHash { get { @@ -138,7 +138,7 @@ public UInt160 CallingScriptHash /// /// The script hash of the entry context. This field could be if no context is loaded to the engine. /// - public UInt160 EntryScriptHash => EntryContext?.GetScriptHash(); + public UInt160? EntryScriptHash => EntryContext?.GetScriptHash(); /// /// The notifications sent during the execution. @@ -155,7 +155,7 @@ public UInt160 CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache? snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) { this.Trigger = trigger; this.ScriptContainer = container; @@ -202,7 +202,7 @@ internal void Throw(Exception ex) private ExecutionContext CallContractInternal(UInt160 contractHash, string method, CallFlags flags, bool hasReturnValue, StackItem[] args) { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Length); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Length} parameter(s) doesn't exist in the contract {contractHash}."); @@ -294,7 +294,7 @@ protected override void ContextUnloaded(ExecutionContext context) } else { - if (state.NotificationCount > 0) + if (notifications != null && state.NotificationCount > 0) notifications.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); } } diff --git a/src/Neo/SmartContract/ExecutionContextState.cs b/src/Neo/SmartContract/ExecutionContextState.cs index 8b61ff1197..3bade126d7 100644 --- a/src/Neo/SmartContract/ExecutionContextState.cs +++ b/src/Neo/SmartContract/ExecutionContextState.cs @@ -27,12 +27,12 @@ public class ExecutionContextState /// /// The calling context. /// - public ExecutionContext CallingContext { get; set; } + public ExecutionContext? CallingContext { get; set; } /// /// The script hash of the calling native contract. Used in native contracts only. /// - internal UInt160 NativeCallingScriptHash { get; set; } + internal UInt160? NativeCallingScriptHash { get; set; } /// /// The of the current context. diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 0f846a37cc..9807b0a6bb 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -143,7 +143,7 @@ private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) /// The hash of the deployed contract. /// The deployed contract. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - public ContractState GetContract(DataCache snapshot, UInt160 hash) + public ContractState? GetContract(DataCache snapshot, UInt160 hash) { return snapshot.TryGet(CreateStorageKey(Prefix_Contract).Add(hash))?.GetInteroperable(); } From a12e8b188040a993053dbf43f2cde6d6cf354f23 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 11:20:53 +0800 Subject: [PATCH 18/36] smart contract nullable --- src/Neo/Persistence/DataCache.cs | 22 +++++++++---------- .../Native/ContractManagement.cs | 6 ++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 31212a7331..2b98600d32 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -35,7 +35,7 @@ public class Trackable /// /// The data of the entry. /// - public StorageItem Item; + public StorageItem? Item; /// /// The state of the entry. @@ -89,7 +89,7 @@ public void Add(StorageKey key, StorageItem value) { lock (dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (dictionary.TryGetValue(key, out Trackable? trackable)) { trackable.Item = value; trackable.State = trackable.State switch @@ -117,7 +117,7 @@ public void Add(StorageKey key, StorageItem value) /// /// The key of the entry. /// The data of the entry. - protected abstract void AddInternal(StorageKey key, StorageItem value); + protected abstract void AddInternal(StorageKey key, StorageItem? value); /// /// Commits all changes in the cache to the underlying storage. @@ -165,7 +165,7 @@ public void Delete(StorageKey key) { lock (dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (dictionary.TryGetValue(key, out Trackable? trackable)) { if (trackable.State == TrackState.Added) { @@ -180,7 +180,7 @@ public void Delete(StorageKey key) } else { - StorageItem item = TryGetInternal(key); + StorageItem? item = TryGetInternal(key); if (item == null) return; dictionary.Add(key, new Trackable { @@ -283,7 +283,7 @@ public bool Contains(StorageKey key) { lock (dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (dictionary.TryGetValue(key, out Trackable? trackable)) return trackable.State != TrackState.Deleted && trackable.State != TrackState.NotFound; return ContainsInternal(key); } @@ -309,11 +309,11 @@ public bool Contains(StorageKey key) /// The key of the entry. /// A delegate used to create the entry if it doesn't exist. If the entry already exists, the factory will not be used. /// The cached data. Or if it doesn't exist and the is not provided. - public StorageItem GetAndChange(StorageKey key, Func factory = null) + public StorageItem? GetAndChange(StorageKey key, Func? factory = null) { lock (dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (dictionary.TryGetValue(key, out Trackable? trackable)) { if (trackable.State == TrackState.Deleted || trackable.State == TrackState.NotFound) { @@ -369,7 +369,7 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) { lock (dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (dictionary.TryGetValue(key, out Trackable? trackable)) { if (trackable.State == TrackState.Deleted || trackable.State == TrackState.NotFound) { @@ -414,7 +414,7 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) /// The key to be sought. /// The direction of seek. /// An enumerator containing all the entries after seeking. - public IEnumerable<(StorageKey Key, StorageItem Value)> Seek(byte[] keyOrPrefix = null, SeekDirection direction = SeekDirection.Forward) + public IEnumerable<(StorageKey Key, StorageItem Value)> Seek(byte[]? keyOrPrefix = null, SeekDirection direction = SeekDirection.Forward) { IEnumerable<(byte[], StorageKey, StorageItem)> cached; HashSet cachedKeySet; @@ -505,7 +505,7 @@ public StorageItem GetOrAdd(StorageKey key, Func factory) /// /// The key of the entry. /// The data of the entry. Or if it doesn't exist. - protected abstract StorageItem TryGetInternal(StorageKey key); + protected abstract StorageItem? TryGetInternal(StorageKey key); /// /// Updates an entry in the underlying storage. diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 9807b0a6bb..4cf8c47674 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -97,7 +97,7 @@ internal override ContractTask Initialize(ApplicationEngine engine) private async ContractTask OnDeploy(ApplicationEngine engine, ContractState contract, StackItem data, bool update) { - ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2); + ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod("_deploy", 2); if (md is not null) await engine.CallFromNativeContract(Hash, contract.Hash, md.Name, data, update); engine.SendNotification(Hash, update ? "Update" : "Deploy", new VM.Types.Array(engine.ReferenceCounter) { contract.Hash.ToArray() }); @@ -155,9 +155,9 @@ private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) /// Contract ID. /// The deployed contract. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - public ContractState GetContractById(DataCache snapshot, int id) + public ContractState? GetContractById(DataCache snapshot, int id) { - StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_ContractHash).AddBigEndian(id)); + StorageItem? item = snapshot.TryGet(CreateStorageKey(Prefix_ContractHash).AddBigEndian(id)); if (item is null) return null; var hash = new UInt160(item.Value.Span); return GetContract(snapshot, hash); From e4c6c188f316784351a57951fb22278638708d5e Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 11:30:54 +0800 Subject: [PATCH 19/36] add more nullable to contracts --- src/Neo/SmartContract/JsonSerializer.cs | 4 +- .../SmartContract/Native/LedgerContract.cs | 52 +++++++++---------- .../SmartContract/Native/TransactionState.cs | 3 +- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/Neo/SmartContract/JsonSerializer.cs b/src/Neo/SmartContract/JsonSerializer.cs index 4d77104a6e..7de12e9fa0 100644 --- a/src/Neo/SmartContract/JsonSerializer.cs +++ b/src/Neo/SmartContract/JsonSerializer.cs @@ -171,7 +171,7 @@ public static StackItem Deserialize(ApplicationEngine engine, JToken json, Execu return Deserialize(engine, json, ref maxStackSize, referenceCounter); } - private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref uint maxStackSize, ReferenceCounter referenceCounter) + private static StackItem Deserialize(ApplicationEngine engine, JToken? json, ref uint maxStackSize, ReferenceCounter referenceCounter) { if (maxStackSize-- == 0) throw new FormatException(); switch (json) @@ -183,7 +183,7 @@ private static StackItem Deserialize(ApplicationEngine engine, JToken json, ref case JArray array: { List list = new(array.Count); - foreach (JToken obj in array) + foreach (JToken? obj in array) list.Add(Deserialize(engine, obj, ref maxStackSize, referenceCounter)); return new Array(referenceCounter, list); } diff --git a/src/Neo/SmartContract/Native/LedgerContract.cs b/src/Neo/SmartContract/Native/LedgerContract.cs index 3bb7568adf..46a1142c07 100644 --- a/src/Neo/SmartContract/Native/LedgerContract.cs +++ b/src/Neo/SmartContract/Native/LedgerContract.cs @@ -93,9 +93,9 @@ private bool IsTraceableBlock(DataCache snapshot, uint index, uint maxTraceableB /// The snapshot used to read data. /// The index of the block. /// The hash of the block. - public UInt256 GetBlockHash(DataCache snapshot, uint index) + public UInt256? GetBlockHash(DataCache snapshot, uint index) { - StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_BlockHash).AddBigEndian(index)); + StorageItem? item = snapshot.TryGet(CreateStorageKey(Prefix_BlockHash).AddBigEndian(index)); if (item is null) return null; return new UInt256(item.Value.Span); } @@ -178,17 +178,17 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerableThe snapshot used to read data. /// The hash of the block. /// The trimmed block. - public TrimmedBlock GetTrimmedBlock(DataCache snapshot, UInt256 hash) + public TrimmedBlock? GetTrimmedBlock(DataCache snapshot, UInt256 hash) { - StorageItem item = snapshot.TryGet(CreateStorageKey(Prefix_Block).Add(hash)); + StorageItem? item = snapshot.TryGet(CreateStorageKey(Prefix_Block).Add(hash)); if (item is null) return null; return item.Value.AsSerializable(); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - private TrimmedBlock GetBlock(ApplicationEngine engine, byte[] indexOrHash) + private TrimmedBlock? GetBlock(ApplicationEngine engine, byte[] indexOrHash) { - UInt256 hash; + UInt256? hash; if (indexOrHash.Length < UInt256.Length) hash = GetBlockHash(engine.Snapshot, (uint)new BigInteger(indexOrHash)); else if (indexOrHash.Length == UInt256.Length) @@ -196,7 +196,7 @@ private TrimmedBlock GetBlock(ApplicationEngine engine, byte[] indexOrHash) else throw new ArgumentException(null, nameof(indexOrHash)); if (hash is null) return null; - TrimmedBlock block = GetTrimmedBlock(engine.Snapshot, hash); + TrimmedBlock? block = GetTrimmedBlock(engine.Snapshot, hash); if (block is null || !IsTraceableBlock(engine.Snapshot, block.Index, engine.ProtocolSettings.MaxTraceableBlocks)) return null; return block; } @@ -207,9 +207,9 @@ private TrimmedBlock GetBlock(ApplicationEngine engine, byte[] indexOrHash) /// The snapshot used to read data. /// The hash of the block. /// The block with the specified hash. - public Block GetBlock(DataCache snapshot, UInt256 hash) + public Block? GetBlock(DataCache snapshot, UInt256 hash) { - TrimmedBlock state = GetTrimmedBlock(snapshot, hash); + TrimmedBlock? state = GetTrimmedBlock(snapshot, hash); if (state is null) return null; return new Block { @@ -224,9 +224,9 @@ public Block GetBlock(DataCache snapshot, UInt256 hash) /// The snapshot used to read data. /// The index of the block. /// The block with the specified index. - public Block GetBlock(DataCache snapshot, uint index) + public Block? GetBlock(DataCache snapshot, uint index) { - UInt256 hash = GetBlockHash(snapshot, index); + UInt256? hash = GetBlockHash(snapshot, index); if (hash is null) return null; return GetBlock(snapshot, hash); } @@ -237,7 +237,7 @@ public Block GetBlock(DataCache snapshot, uint index) /// The snapshot used to read data. /// The hash of the block. /// The block header with the specified hash. - public Header GetHeader(DataCache snapshot, UInt256 hash) + public Header? GetHeader(DataCache snapshot, UInt256 hash) { return GetTrimmedBlock(snapshot, hash)?.Header; } @@ -248,9 +248,9 @@ public Header GetHeader(DataCache snapshot, UInt256 hash) /// The snapshot used to read data. /// The index of the block. /// The block header with the specified index. - public Header GetHeader(DataCache snapshot, uint index) + public Header? GetHeader(DataCache snapshot, uint index) { - UInt256 hash = GetBlockHash(snapshot, index); + UInt256? hash = GetBlockHash(snapshot, index); if (hash is null) return null; return GetHeader(snapshot, hash); } @@ -261,7 +261,7 @@ public Header GetHeader(DataCache snapshot, uint index) /// The snapshot used to read data. /// The hash of the transaction. /// The with the specified hash. - public TransactionState GetTransactionState(DataCache snapshot, UInt256 hash) + public TransactionState? GetTransactionState(DataCache snapshot, UInt256 hash) { var state = snapshot.TryGet(CreateStorageKey(Prefix_Transaction).Add(hash))?.GetInteroperable(); if (state?.Transaction is null) return null; @@ -274,31 +274,31 @@ public TransactionState GetTransactionState(DataCache snapshot, UInt256 hash) /// The snapshot used to read data. /// The hash of the transaction. /// The transaction with the specified hash. - public Transaction GetTransaction(DataCache snapshot, UInt256 hash) + public Transaction? GetTransaction(DataCache snapshot, UInt256 hash) { return GetTransactionState(snapshot, hash)?.Transaction; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates, Name = "getTransaction")] - private Transaction GetTransactionForContract(ApplicationEngine engine, UInt256 hash) + private Transaction? GetTransactionForContract(ApplicationEngine engine, UInt256 hash) { - TransactionState state = GetTransactionState(engine.Snapshot, hash); + TransactionState? state = GetTransactionState(engine.Snapshot, hash); if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return null; return state.Transaction; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - private Signer[] GetTransactionSigners(ApplicationEngine engine, UInt256 hash) + private Signer[]? GetTransactionSigners(ApplicationEngine engine, UInt256 hash) { - TransactionState state = GetTransactionState(engine.Snapshot, hash); + TransactionState? state = GetTransactionState(engine.Snapshot, hash); if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return null; - return state.Transaction.Signers; + return state.Transaction?.Signers; } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private VMState GetTransactionVMState(ApplicationEngine engine, UInt256 hash) { - TransactionState state = GetTransactionState(engine.Snapshot, hash); + TransactionState? state = GetTransactionState(engine.Snapshot, hash); if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return VMState.NONE; return state.State; } @@ -306,15 +306,15 @@ private VMState GetTransactionVMState(ApplicationEngine engine, UInt256 hash) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] private int GetTransactionHeight(ApplicationEngine engine, UInt256 hash) { - TransactionState state = GetTransactionState(engine.Snapshot, hash); + TransactionState? state = GetTransactionState(engine.Snapshot, hash); if (state is null || !IsTraceableBlock(engine.Snapshot, state.BlockIndex, engine.ProtocolSettings.MaxTraceableBlocks)) return -1; return (int)state.BlockIndex; } [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.ReadStates)] - private Transaction GetTransactionFromBlock(ApplicationEngine engine, byte[] blockIndexOrHash, int txIndex) + private Transaction? GetTransactionFromBlock(ApplicationEngine engine, byte[] blockIndexOrHash, int txIndex) { - UInt256 hash; + UInt256? hash; if (blockIndexOrHash.Length < UInt256.Length) hash = GetBlockHash(engine.Snapshot, (uint)new BigInteger(blockIndexOrHash)); else if (blockIndexOrHash.Length == UInt256.Length) @@ -322,7 +322,7 @@ private Transaction GetTransactionFromBlock(ApplicationEngine engine, byte[] blo else throw new ArgumentException(null, nameof(blockIndexOrHash)); if (hash is null) return null; - TrimmedBlock block = GetTrimmedBlock(engine.Snapshot, hash); + TrimmedBlock? block = GetTrimmedBlock(engine.Snapshot, hash); if (block is null || !IsTraceableBlock(engine.Snapshot, block.Index, engine.ProtocolSettings.MaxTraceableBlocks)) return null; if (txIndex < 0 || txIndex >= block.Hashes.Length) throw new ArgumentOutOfRangeException(nameof(txIndex)); diff --git a/src/Neo/SmartContract/Native/TransactionState.cs b/src/Neo/SmartContract/Native/TransactionState.cs index b17296b42d..4facb8d1f4 100644 --- a/src/Neo/SmartContract/Native/TransactionState.cs +++ b/src/Neo/SmartContract/Native/TransactionState.cs @@ -14,7 +14,6 @@ using Neo.VM; using Neo.VM.Types; using System; -using System.Linq; namespace Neo.SmartContract.Native { @@ -31,7 +30,7 @@ public class TransactionState : IInteroperable /// /// The transaction, if the transaction is trimmed this value will be null /// - public Transaction Transaction; + public Transaction? Transaction; /// /// The execution state From ba7b50d8e8a0cdd3e0f39e6f7c76ccb126417614 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 11:41:28 +0800 Subject: [PATCH 20/36] more contract nullable --- src/Neo/NeoSystem.cs | 2 +- src/Neo/SmartContract/ApplicationEngine.cs | 10 +++---- src/Neo/SmartContract/ContractParameter.cs | 6 ++-- .../ContractParametersContext.cs | 28 +++++++++---------- .../SmartContract/ExecutionContextState.cs | 2 +- .../IApplicationEngineProvider.cs | 2 +- src/Neo/SmartContract/IInteroperable.cs | 2 +- .../Native/ContractManagement.cs | 6 ++-- src/Neo/SmartContract/StorageItem.cs | 2 +- src/Neo/Wallets/Wallet.cs | 6 ++-- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/Neo/NeoSystem.cs b/src/Neo/NeoSystem.cs index 4713c284ff..91dcb435e5 100644 --- a/src/Neo/NeoSystem.cs +++ b/src/Neo/NeoSystem.cs @@ -188,7 +188,7 @@ public void AddService(object service) /// The type of the service object. /// An action used to filter the service objects. This parameter can be . /// The service object found. - public T GetService(Func filter = null) + public T? GetService(Func? filter = null) { IEnumerable result = services.OfType(); if (filter is null) diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index e983909cb8..ae760bb8a9 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -85,7 +85,7 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The container that containing the executed script. This field could be if the contract is invoked by system. /// - public IVerifiable ScriptContainer { get; } + public IVerifiable? ScriptContainer { get; } /// /// The snapshot used to read or write data. @@ -155,7 +155,7 @@ public UInt160? CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable container, DataCache? snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) { this.Trigger = trigger; this.ScriptContainer = container; @@ -204,7 +204,7 @@ private ExecutionContext CallContractInternal(UInt160 contractHash, string metho { ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method, args.Length); + ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Length); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Length} parameter(s) doesn't exist in the contract {contractHash}."); return CallContractInternal(contract, md, flags, hasReturnValue, args); } @@ -318,7 +318,7 @@ protected override void ContextUnloaded(ExecutionContext context) /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) { return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -541,7 +541,7 @@ protected override void PostExecuteInstruction(Instruction instruction) private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings settings) { UInt256 hash = NativeContract.Ledger.CurrentHash(snapshot); - Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash); + Block currentBlock = NativeContract.Ledger.GetBlock(snapshot, hash)!; return new Block { Header = new Header diff --git a/src/Neo/SmartContract/ContractParameter.cs b/src/Neo/SmartContract/ContractParameter.cs index 027fa50e00..ba55874065 100644 --- a/src/Neo/SmartContract/ContractParameter.cs +++ b/src/Neo/SmartContract/ContractParameter.cs @@ -32,7 +32,7 @@ public class ContractParameter /// /// The value of the parameter. /// - public object Value; + public object? Value; /// /// Initializes a new instance of the class. @@ -139,7 +139,7 @@ public JObject ToJson() return ToJson(this, null); } - private static JObject ToJson(ContractParameter parameter, HashSet context) + private static JObject ToJson(ContractParameter parameter, HashSet? context) { JObject json = new(); json["type"] = parameter.Type; @@ -191,7 +191,7 @@ public override string ToString() return ToString(this, null); } - private static string ToString(ContractParameter parameter, HashSet context) + private static string ToString(ContractParameter parameter, HashSet? context) { switch (parameter.Value) { diff --git a/src/Neo/SmartContract/ContractParametersContext.cs b/src/Neo/SmartContract/ContractParametersContext.cs index f6a18e081d..c3f1a67369 100644 --- a/src/Neo/SmartContract/ContractParametersContext.cs +++ b/src/Neo/SmartContract/ContractParametersContext.cs @@ -95,7 +95,7 @@ public bool Completed } } - private UInt160[] _ScriptHashes = null; + private UInt160[]? _ScriptHashes = null; /// /// Gets the script hashes to be verified for the . /// @@ -124,7 +124,7 @@ public ContractParametersContext(DataCache snapshot, IVerifiable verifiable, uin /// if the parameter is added successfully; otherwise, . public bool Add(Contract contract, int index, object parameter) { - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; item.Parameters[index].Value = parameter; return true; @@ -138,7 +138,7 @@ public bool Add(Contract contract, int index, object parameter) /// if the parameters are added successfully; otherwise, . public bool Add(Contract contract, params object[] parameters) { - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; for (int index = 0; index < parameters.Length; index++) { @@ -159,7 +159,7 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) if (IsMultiSigContract(contract.Script, out _, out ECPoint[] points)) { if (!points.Contains(pubkey)) return false; - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; if (item.Parameters.All(p => p.Value != null)) return false; if (!item.Signatures.TryAdd(pubkey, signature)) @@ -198,7 +198,7 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) // return now to prevent array index out of bounds exception return false; } - ContextItem item = CreateItem(contract); + ContextItem? item = CreateItem(contract); if (item == null) return false; if (!item.Signatures.TryAdd(pubkey, signature)) return false; @@ -207,9 +207,9 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) } } - private ContextItem CreateItem(Contract contract) + private ContextItem? CreateItem(Contract contract) { - if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem item)) + if (ContextItems.TryGetValue(contract.ScriptHash, out ContextItem? item)) return item; if (!ScriptHashes.Contains(contract.ScriptHash)) return null; @@ -252,7 +252,7 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho /// The hash of the witness script. /// The specified index. /// The parameter with the specified index. - public ContractParameter GetParameter(UInt160 scriptHash, int index) + public ContractParameter? GetParameter(UInt160 scriptHash, int index) { return GetParameters(scriptHash)?[index]; } @@ -262,9 +262,9 @@ public ContractParameter GetParameter(UInt160 scriptHash, int index) /// /// The hash of the witness script. /// The parameters from the witness script. - public IReadOnlyList GetParameters(UInt160 scriptHash) + public IReadOnlyList? GetParameters(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) return null; return item.Parameters; } @@ -274,9 +274,9 @@ public IReadOnlyList GetParameters(UInt160 scriptHash) /// /// The hash of the witness script. /// The signatures from the witness script. - public IReadOnlyDictionary GetSignatures(UInt160 scriptHash) + public IReadOnlyDictionary? GetSignatures(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) return null; return item.Signatures; } @@ -286,9 +286,9 @@ public IReadOnlyDictionary GetSignatures(UInt160 scriptHash) /// /// The hash of the witness script. /// The witness script. - public byte[] GetScript(UInt160 scriptHash) + public byte[]? GetScript(UInt160 scriptHash) { - if (!ContextItems.TryGetValue(scriptHash, out ContextItem item)) + if (!ContextItems.TryGetValue(scriptHash, out ContextItem? item)) return null; return item.Script; } diff --git a/src/Neo/SmartContract/ExecutionContextState.cs b/src/Neo/SmartContract/ExecutionContextState.cs index 3bade126d7..89b192a1e5 100644 --- a/src/Neo/SmartContract/ExecutionContextState.cs +++ b/src/Neo/SmartContract/ExecutionContextState.cs @@ -22,7 +22,7 @@ public class ExecutionContextState /// /// The script hash of the current context. /// - public UInt160 ScriptHash { get; set; } + public UInt160? ScriptHash { get; set; } /// /// The calling context. diff --git a/src/Neo/SmartContract/IApplicationEngineProvider.cs b/src/Neo/SmartContract/IApplicationEngineProvider.cs index ef06c6b92c..36c16dd0c6 100644 --- a/src/Neo/SmartContract/IApplicationEngineProvider.cs +++ b/src/Neo/SmartContract/IApplicationEngineProvider.cs @@ -30,6 +30,6 @@ public interface IApplicationEngineProvider /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - ApplicationEngine Create(TriggerType trigger, IVerifiable container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic); + ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic); } } diff --git a/src/Neo/SmartContract/IInteroperable.cs b/src/Neo/SmartContract/IInteroperable.cs index 5254898efe..d9009625b1 100644 --- a/src/Neo/SmartContract/IInteroperable.cs +++ b/src/Neo/SmartContract/IInteroperable.cs @@ -31,7 +31,7 @@ public interface IInteroperable /// /// The used by the . /// The converted . - StackItem ToStackItem(ReferenceCounter referenceCounter); + StackItem ToStackItem(ReferenceCounter? referenceCounter); public IInteroperable Clone() { diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 4cf8c47674..2df0e87600 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -82,7 +82,7 @@ internal ContractManagement() private int GetNextAvailableId(DataCache snapshot) { - StorageItem item = snapshot.GetAndChange(CreateStorageKey(Prefix_NextAvailableId)); + StorageItem item = snapshot.GetAndChange(CreateStorageKey(Prefix_NextAvailableId))!; int value = (int)(BigInteger)item; item.Add(1); return value; @@ -304,9 +304,9 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private void Destroy(ApplicationEngine engine) { - UInt160 hash = engine.CallingScriptHash; + UInt160? hash = engine.CallingScriptHash; StorageKey ckey = CreateStorageKey(Prefix_Contract).Add(hash); - ContractState contract = engine.Snapshot.TryGet(ckey)?.GetInteroperable(); + ContractState? contract = engine.Snapshot.TryGet(ckey)?.GetInteroperable(); if (contract is null) return; engine.Snapshot.Delete(ckey); engine.Snapshot.Delete(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id)); diff --git a/src/Neo/SmartContract/StorageItem.cs b/src/Neo/SmartContract/StorageItem.cs index 0f13c3c1f0..0383a2303c 100644 --- a/src/Neo/SmartContract/StorageItem.cs +++ b/src/Neo/SmartContract/StorageItem.cs @@ -23,7 +23,7 @@ namespace Neo.SmartContract public class StorageItem : ISerializable { private ReadOnlyMemory value; - private object cache; + private object? cache; public int Size => Value.GetVarSize(); diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index ecffe85366..1c592359b5 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -767,10 +767,10 @@ public static Wallet Open(string path, string password, ProtocolSettings setting /// The created new wallet. public static Wallet Migrate(string path, string oldPath, string password, ProtocolSettings settings) { - IWalletFactory factoryOld = GetFactory(oldPath); + IWalletFactory? factoryOld = GetFactory(oldPath); if (factoryOld is null) throw new InvalidOperationException("The old wallet file format is not supported."); - IWalletFactory factoryNew = GetFactory(path); + IWalletFactory? factoryNew = GetFactory(path); if (factoryNew is null) throw new InvalidOperationException("The new wallet file format is not supported."); @@ -784,7 +784,7 @@ public static Wallet Migrate(string path, string oldPath, string password, Proto return newWallet; } - private static IWalletFactory GetFactory(string path) + private static IWalletFactory? GetFactory(string path) { return factories.FirstOrDefault(p => p.Handle(path)); } From af3fc79c259509187946823bdfa4fe9880f8d802 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 12:05:08 +0800 Subject: [PATCH 21/36] more nullable for smart contract --- src/Neo/Persistence/DataCache.cs | 6 +-- src/Neo/Persistence/IReadOnlyStore.cs | 2 +- src/Neo/Persistence/MemorySnapshot.cs | 8 +-- src/Neo/Persistence/SnapshotCache.cs | 6 +-- .../ApplicationEngine.Runtime.cs | 12 ++--- .../ApplicationEngine.Storage.cs | 6 +-- src/Neo/SmartContract/ApplicationEngine.cs | 9 ++-- src/Neo/SmartContract/BinarySerializer.cs | 8 +-- src/Neo/SmartContract/ContractParameter.cs | 14 ++--- .../SmartContract/Native/NativeContract.cs | 2 +- src/Neo/SmartContract/Native/NeoToken.cs | 24 ++++----- src/Neo/VM/Helper.cs | 14 ++--- src/Neo/Wallets/NEP6/NEP6Wallet.cs | 52 +++++++++---------- src/Neo/Wallets/Wallet.cs | 26 +++++----- 14 files changed, 95 insertions(+), 94 deletions(-) diff --git a/src/Neo/Persistence/DataCache.cs b/src/Neo/Persistence/DataCache.cs index 2b98600d32..5bab5973f4 100644 --- a/src/Neo/Persistence/DataCache.cs +++ b/src/Neo/Persistence/DataCache.cs @@ -58,7 +58,7 @@ public StorageItem this[StorageKey key] { lock (dictionary) { - if (dictionary.TryGetValue(key, out Trackable trackable)) + if (dictionary.TryGetValue(key, out Trackable? trackable)) { if (trackable.State == TrackState.Deleted || trackable.State == TrackState.NotFound) throw new KeyNotFoundException(); @@ -205,7 +205,7 @@ public void Delete(StorageKey key) /// The prefix of the key. /// The search direction. /// The entries found with the desired prefix. - public IEnumerable<(StorageKey Key, StorageItem Value)> Find(byte[] key_prefix = null, SeekDirection direction = SeekDirection.Forward) + public IEnumerable<(StorageKey Key, StorageItem Value)> Find(byte[]? key_prefix = null, SeekDirection direction = SeekDirection.Forward) { var seek_prefix = key_prefix; if (direction == SeekDirection.Backward) @@ -230,7 +230,7 @@ public void Delete(StorageKey key) throw new ArgumentException(); } } - return FindInternal(key_prefix, seek_prefix, direction); + return FindInternal(key_prefix!, seek_prefix!, direction); } private IEnumerable<(StorageKey Key, StorageItem Value)> FindInternal(byte[] key_prefix, byte[] seek_prefix, SeekDirection direction) diff --git a/src/Neo/Persistence/IReadOnlyStore.cs b/src/Neo/Persistence/IReadOnlyStore.cs index 4b6c3fe0ec..ce19b2b3a7 100644 --- a/src/Neo/Persistence/IReadOnlyStore.cs +++ b/src/Neo/Persistence/IReadOnlyStore.cs @@ -31,7 +31,7 @@ public interface IReadOnlyStore /// /// The key of the entry. /// The data of the entry. Or if it doesn't exist. - byte[] TryGet(byte[] key); + byte[]? TryGet(byte[] key); /// /// Determines whether the database contains the specified entry. diff --git a/src/Neo/Persistence/MemorySnapshot.cs b/src/Neo/Persistence/MemorySnapshot.cs index 756a4c83b2..f7b41c22f3 100644 --- a/src/Neo/Persistence/MemorySnapshot.cs +++ b/src/Neo/Persistence/MemorySnapshot.cs @@ -21,13 +21,13 @@ internal class MemorySnapshot : ISnapshot { private readonly ConcurrentDictionary innerData; private readonly ImmutableDictionary immutableData; - private readonly ConcurrentDictionary writeBatch; + private readonly ConcurrentDictionary writeBatch; public MemorySnapshot(ConcurrentDictionary innerData) { this.innerData = innerData; this.immutableData = innerData.ToImmutableDictionary(ByteArrayEqualityComparer.Default); - this.writeBatch = new ConcurrentDictionary(ByteArrayEqualityComparer.Default); + this.writeBatch = new ConcurrentDictionary(ByteArrayEqualityComparer.Default); } public void Commit() @@ -63,9 +63,9 @@ public void Put(byte[] key, byte[] value) return records.Select(p => (p.Key[..], p.Value[..])); } - public byte[] TryGet(byte[] key) + public byte[]? TryGet(byte[] key) { - immutableData.TryGetValue(key, out byte[] value); + immutableData.TryGetValue(key, out byte[]? value); return value?[..]; } diff --git a/src/Neo/Persistence/SnapshotCache.cs b/src/Neo/Persistence/SnapshotCache.cs index e441f977c0..8f117534f1 100644 --- a/src/Neo/Persistence/SnapshotCache.cs +++ b/src/Neo/Persistence/SnapshotCache.cs @@ -63,7 +63,7 @@ public void Dispose() protected override StorageItem GetInternal(StorageKey key) { - byte[] value = store.TryGet(key.ToArray()); + byte[]? value = store.TryGet(key.ToArray()); if (value == null) throw new KeyNotFoundException(); return new(value); } @@ -73,9 +73,9 @@ protected override StorageItem GetInternal(StorageKey key) return store.Seek(keyOrPrefix, direction).Select(p => (new StorageKey(p.Key), new StorageItem(p.Value))); } - protected override StorageItem TryGetInternal(StorageKey key) + protected override StorageItem? TryGetInternal(StorageKey key) { - byte[] value = store.TryGet(key.ToArray()); + byte[]? value = store.TryGet(key.ToArray()); if (value == null) return null; return new(value); } diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index 293b245bd7..a9a84bd7a0 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -187,9 +187,9 @@ internal protected byte GetAddressVersion() /// Gets the timestamp of the current block. /// /// The timestamp of the current block. - protected internal ulong GetTime() + protected internal ulong? GetTime() { - return PersistingBlock.Timestamp; + return PersistingBlock?.Timestamp; } /// @@ -253,7 +253,7 @@ protected internal bool CheckWitnessInternal(UInt160 hash) if (ScriptContainer is Transaction tx) { Signer[] signers; - OracleResponse response = tx.GetAttribute(); + OracleResponse? response = tx.GetAttribute(); if (response is null) { signers = tx.Signers; @@ -263,7 +263,7 @@ protected internal bool CheckWitnessInternal(UInt160 hash) OracleRequest request = NativeContract.Oracle.GetRequest(Snapshot, response.Id); signers = NativeContract.Ledger.GetTransaction(Snapshot, request.OriginalTxid).Signers; } - Signer signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); + Signer? signer = signers.FirstOrDefault(p => p.Account.Equals(hash)); if (signer is null) return false; foreach (WitnessRule rule in signer.GetAllRules()) { @@ -406,7 +406,7 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s /// /// The hash of the specified contract. It can be set to to get all notifications. /// The notifications sent during the execution. - protected internal NotifyEventArgs[] GetNotifications(UInt160 hash) + protected internal NotifyEventArgs[] GetNotifications(UInt160? hash) { IEnumerable notifications = Notifications; if (hash != null) // must filter by scriptHash @@ -432,7 +432,7 @@ protected internal void BurnGas(long gas) /// Get the Signers of the current transaction. /// /// The signers of the current transaction, or null if is not related to a transaction execution. - protected internal Signer[] GetCurrentSigners() + protected internal Signer[]? GetCurrentSigners() { if (ScriptContainer is Transaction tx) return tx.Signers; diff --git a/src/Neo/SmartContract/ApplicationEngine.Storage.cs b/src/Neo/SmartContract/ApplicationEngine.Storage.cs index 3a8bb9d122..a5857980e7 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Storage.cs @@ -177,11 +177,11 @@ protected internal void Put(StorageContext context, byte[] key, byte[] value) Id = context.Id, Key = key }; - StorageItem item = Snapshot.GetAndChange(skey); + StorageItem? item = Snapshot?.GetAndChange(skey); if (item is null) { newDataSize = key.Length + value.Length; - Snapshot.Add(skey, item = new StorageItem()); + Snapshot?.Add(skey, item = new StorageItem()); } else { @@ -196,7 +196,7 @@ protected internal void Put(StorageContext context, byte[] key, byte[] value) } AddGas(newDataSize * StoragePrice); - item.Value = value; + item!.Value = value; } /// diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index ae760bb8a9..637c438c93 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -90,12 +90,13 @@ public partial class ApplicationEngine : ExecutionEngine /// /// The snapshot used to read or write data. /// - public DataCache Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot; + public DataCache? Snapshot => CurrentContext?.GetState().Snapshot ?? originalSnapshot; /// - /// The block being persisted. This field could be if the is . + /// The block being persisted. + /// This field could be if the is . /// - public Block PersistingBlock { get; } + public Block? PersistingBlock { get; } /// /// The used by the engine. @@ -378,7 +379,7 @@ public ExecutionContext LoadContract(ContractState contract, ContractMethodDescr /// The initial position of the instruction pointer. /// The action used to configure the state of the loaded context. /// The loaded context. - public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action configureState = null) + public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action? configureState = null) { // Create and configure context ExecutionContext context = CreateContext(script, rvcount, initialPosition); diff --git a/src/Neo/SmartContract/BinarySerializer.cs b/src/Neo/SmartContract/BinarySerializer.cs index 2bdeced678..14236e139a 100644 --- a/src/Neo/SmartContract/BinarySerializer.cs +++ b/src/Neo/SmartContract/BinarySerializer.cs @@ -39,7 +39,7 @@ public ContainerPlaceholder(StackItemType type, int count) ElementCount = count; } - public override bool Equals(StackItem other) => throw new NotSupportedException(); + public override bool Equals(StackItem? other) => throw new NotSupportedException(); public override int GetHashCode() => throw new NotSupportedException(); @@ -53,7 +53,7 @@ public ContainerPlaceholder(StackItemType type, int count) /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) { MemoryReader reader = new(data); return Deserialize(ref reader, (uint)Math.Min(data.Length, limits.MaxItemSize), limits.MaxStackSize, referenceCounter); @@ -66,7 +66,7 @@ public static StackItem Deserialize(ReadOnlyMemory data, ExecutionEngineLi /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) { return Deserialize(ref reader, limits.MaxItemSize, limits.MaxStackSize, referenceCounter); } @@ -79,7 +79,7 @@ public static StackItem Deserialize(ref MemoryReader reader, ExecutionEngineLimi /// The max of items to serialize /// The used by the . /// The deserialized . - public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ref MemoryReader reader, uint maxSize, uint maxItems, ReferenceCounter? referenceCounter = null) { Stack deserialized = new(); int undeserialized = 1; diff --git a/src/Neo/SmartContract/ContractParameter.cs b/src/Neo/SmartContract/ContractParameter.cs index ba55874065..26b12c7581 100644 --- a/src/Neo/SmartContract/ContractParameter.cs +++ b/src/Neo/SmartContract/ContractParameter.cs @@ -72,17 +72,17 @@ public static ContractParameter FromJson(JObject json) { ContractParameter parameter = new() { - Type = Enum.Parse(json["type"].GetString()) + Type = Enum.Parse(json["type"]!.GetString()) }; if (json["value"] != null) parameter.Value = parameter.Type switch { - ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(json["value"].AsString()), - ContractParameterType.Boolean => json["value"].AsBoolean(), - ContractParameterType.Integer => BigInteger.Parse(json["value"].AsString()), - ContractParameterType.Hash160 => UInt160.Parse(json["value"].AsString()), - ContractParameterType.Hash256 => UInt256.Parse(json["value"].AsString()), - ContractParameterType.PublicKey => ECPoint.Parse(json["value"].AsString(), ECCurve.Secp256r1), + ContractParameterType.Signature or ContractParameterType.ByteArray => Convert.FromBase64String(json["value"]!.AsString()), + ContractParameterType.Boolean => json["value"]?.AsBoolean(), + ContractParameterType.Integer => BigInteger.Parse(json["value"]!.AsString()), + ContractParameterType.Hash160 => UInt160.Parse(json["value"]!.AsString()), + ContractParameterType.Hash256 => UInt256.Parse(json["value"]!.AsString()), + ContractParameterType.PublicKey => ECPoint.Parse(json["value"]!.AsString(), ECCurve.Secp256r1), ContractParameterType.String => json["value"].AsString(), ContractParameterType.Array => ((JArray)json["value"]).Select(p => FromJson((JObject)p)).ToList(), ContractParameterType.Map => ((JArray)json["value"]).Select(p => new KeyValuePair(FromJson((JObject)p["key"]), FromJson((JObject)p["value"]))).ToList(), diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index 0229582310..f132bdd03d 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -121,7 +121,7 @@ protected NativeContract() List descriptors = new(); foreach (MemberInfo member in GetType().GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { - ContractMethodAttribute attribute = member.GetCustomAttribute(); + ContractMethodAttribute? attribute = member.GetCustomAttribute(); if (attribute is null) continue; descriptors.Add(new ContractMethodMetadata(member, attribute)); } diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 2fd26d04a7..a6173c7be4 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -122,7 +122,7 @@ public override BigInteger TotalSupply(DataCache snapshot) internal override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { - GasDistribution distribution = DistributeGas(engine, account, state); + GasDistribution? distribution = DistributeGas(engine, account, state); if (distribution is not null) { var list = engine.CurrentContext.GetState>(); @@ -145,7 +145,7 @@ private protected override async ContractTask PostTransfer(ApplicationEngine eng await GAS.Mint(engine, distribution.Account, distribution.Amount, callOnPayment); } - private GasDistribution DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state) + private GasDistribution? DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state) { // PersistingBlock is null when running under the debugger if (engine.PersistingBlock is null) return null; @@ -377,13 +377,13 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) } [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] - private async ContractTask Vote(ApplicationEngine engine, UInt160 account, ECPoint voteTo) + private async ContractTask Vote(ApplicationEngine engine, UInt160 account, ECPoint? voteTo) { if (!engine.CheckWitnessInternal(account)) return false; - NeoAccountState state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); + NeoAccountState? state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); if (state_account is null) return false; if (state_account.Balance == 0) return false; - CandidateState validator_new = null; + CandidateState? validator_new = null; if (voteTo != null) { validator_new = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Candidate).Add(voteTo))?.GetInteroperable(); @@ -392,7 +392,7 @@ private async ContractTask Vote(ApplicationEngine engine, UInt160 account, } if (state_account.VoteTo is null ^ voteTo is null) { - StorageItem item = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)); + StorageItem item = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount))!; // Should never be null if (state_account.VoteTo is null) item.Add(state_account.Balance); else @@ -413,7 +413,7 @@ private async ContractTask Vote(ApplicationEngine engine, UInt160 account, var latestGasPerVote = engine.Snapshot.TryGet(voterRewardKey) ?? BigInteger.Zero; state_account.LastGasPerVote = latestGasPerVote; } - ECPoint from = state_account.VoteTo; + ECPoint? from = state_account.VoteTo; state_account.VoteTo = voteTo; if (validator_new != null) @@ -474,8 +474,8 @@ private IIterator GetAllCandidates(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public BigInteger GetCandidateVote(DataCache snapshot, ECPoint pubKey) { - StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubKey)); - CandidateState state = storage?.GetInteroperable(); + StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_Candidate).Add(pubKey)); + CandidateState? state = storage?.GetInteroperable(); return state?.Registered == true ? state.Votes : -1; } @@ -497,7 +497,7 @@ public ECPoint[] GetCommittee(DataCache snapshot) /// account /// The state of the account. [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] - public NeoAccountState GetAccountState(DataCache snapshot, UInt160 account) + public NeoAccountState? GetAccountState(DataCache snapshot, UInt160 account) { return snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); } @@ -578,7 +578,7 @@ public class NeoAccountState : AccountState /// /// The voting target of the account. This field can be . /// - public ECPoint VoteTo; + public ECPoint? VoteTo; public BigInteger LastGasPerVote; @@ -613,7 +613,7 @@ public void FromStackItem(StackItem stackItem) Votes = @struct[1].GetInteger(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { Registered, Votes }; } diff --git a/src/Neo/VM/Helper.cs b/src/Neo/VM/Helper.cs index 4a82041ea5..e303ba1e53 100644 --- a/src/Neo/VM/Helper.cs +++ b/src/Neo/VM/Helper.cs @@ -54,7 +54,7 @@ public static ScriptBuilder CreateArray(this ScriptBuilder builder, IReadOnly /// The to be used. /// The key/value pairs of the map. /// The same instance as . - public static ScriptBuilder CreateMap(this ScriptBuilder builder, IEnumerable> map = null) + public static ScriptBuilder CreateMap(this ScriptBuilder builder, IEnumerable>? map = null) { builder.Emit(OpCode.NEWMAP); if (map != null) @@ -303,13 +303,13 @@ public static JArray ToJson(this EvaluationStack stack, int maxSize = int.MaxVal return result; } - private static JObject ToJson(StackItem item, HashSet context, ref int maxSize) + private static JObject ToJson(StackItem item, HashSet? context, ref int maxSize) { JObject json = new() { ["type"] = item.Type }; - JToken value = null; + JToken? value = null; maxSize -= 11/*{"type":""}*/+ item.Type.ToString().Length; switch (item) { @@ -391,10 +391,10 @@ public static ContractParameter ToParameter(this StackItem item) return ToParameter(item, null); } - private static ContractParameter ToParameter(StackItem item, List<(StackItem, ContractParameter)> context) + private static ContractParameter ToParameter(StackItem item, List<(StackItem, ContractParameter)>? context) { if (item is null) throw new ArgumentNullException(nameof(item)); - ContractParameter parameter = null; + ContractParameter? parameter = null; switch (item) { case Array array: @@ -470,11 +470,11 @@ public static StackItem ToStackItem(this ContractParameter parameter) return ToStackItem(parameter, null); } - private static StackItem ToStackItem(ContractParameter parameter, List<(StackItem, ContractParameter)> context) + private static StackItem ToStackItem(ContractParameter parameter, List<(StackItem, ContractParameter)>? context) { if (parameter is null) throw new ArgumentNullException(nameof(parameter)); if (parameter.Value is null) return StackItem.Null; - StackItem stackItem = null; + StackItem? stackItem = null; switch (parameter.Type) { case ContractParameterType.Array: diff --git a/src/Neo/Wallets/NEP6/NEP6Wallet.cs b/src/Neo/Wallets/NEP6/NEP6Wallet.cs index 74b15209cb..4eb2f9f45b 100644 --- a/src/Neo/Wallets/NEP6/NEP6Wallet.cs +++ b/src/Neo/Wallets/NEP6/NEP6Wallet.cs @@ -30,7 +30,7 @@ public class NEP6Wallet : Wallet private string _password; private string? name; private Version version = null!; - private readonly Dictionary accounts; + private readonly Dictionary _accounts; private readonly JToken? extra; /// @@ -58,14 +58,14 @@ public NEP6Wallet(string path, string password, ProtocolSettings settings, strin if (File.Exists(path)) { JObject wallet = JToken.Parse(File.ReadAllBytes(path)).NullExceptionOr(); - LoadFromJson(wallet, out Scrypt, out accounts, out extra); + LoadFromJson(wallet, out Scrypt, out _accounts, out extra); } else { this.name = name; this.version = Version.Parse("1.0"); this.Scrypt = ScryptParameters.Default; - this.accounts = new Dictionary(); + this._accounts = new Dictionary(); this.extra = JToken.Null; } } @@ -80,7 +80,7 @@ public NEP6Wallet(string path, string password, ProtocolSettings settings, strin public NEP6Wallet(string path, string password, ProtocolSettings settings, JObject json) : base(path, settings) { this._password = password; - LoadFromJson(json, out Scrypt, out accounts, out extra); + LoadFromJson(json, out Scrypt, out _accounts, out extra); } private void LoadFromJson(JObject wallet, out ScryptParameters scrypt, out Dictionary accounts, out JToken? extra) @@ -96,9 +96,9 @@ private void LoadFromJson(JObject wallet, out ScryptParameters scrypt, out Dicti private void AddAccount(NEP6Account account) { - lock (accounts) + lock (_accounts) { - if (accounts.TryGetValue(account.ScriptHash, out NEP6Account? account_old)) + if (_accounts.TryGetValue(account.ScriptHash, out NEP6Account? account_old)) { account.Label = account_old.Label; account.IsDefault = account_old.IsDefault; @@ -119,15 +119,15 @@ private void AddAccount(NEP6Account account) } account.Extra = account_old.Extra; } - accounts[account.ScriptHash] = account; + _accounts[account.ScriptHash] = account; } } public override bool Contains(UInt160 scriptHash) { - lock (accounts) + lock (_accounts) { - return accounts.ContainsKey(scriptHash); + return _accounts.ContainsKey(scriptHash); } } @@ -197,26 +197,26 @@ public override void Delete() public override bool DeleteAccount(UInt160 scriptHash) { - lock (accounts) + lock (_accounts) { - return accounts.Remove(scriptHash); + return _accounts.Remove(scriptHash); } } public override WalletAccount? GetAccount(UInt160 scriptHash) { - lock (accounts) + lock (_accounts) { - accounts.TryGetValue(scriptHash, out NEP6Account? account); + _accounts.TryGetValue(scriptHash, out NEP6Account? account); return account; } } public override IEnumerable GetAccounts() { - lock (accounts) + lock (_accounts) { - foreach (NEP6Account account in accounts.Values) + foreach (NEP6Account account in _accounts.Values) yield return account; } } @@ -286,14 +286,14 @@ public override WalletAccount Import(string nep2, string passphrase, int N = 163 /// public JObject ToJson() { - lock (accounts) + lock (_accounts) { return new() { ["name"] = name, ["version"] = version.ToString(), ["scrypt"] = Scrypt.ToJson(), - ["accounts"] = accounts.Values.Select(p => p.ToJson()).ToArray(), + ["accounts"] = _accounts.Values.Select(p => p.ToJson()).ToArray(), ["extra"] = extra }; } @@ -311,12 +311,12 @@ public override bool VerifyPassword(string password) private bool VerifyPasswordInternal(string password) { - lock (accounts) + lock (_accounts) { - NEP6Account? account = accounts.Values.FirstOrDefault(p => !p.Decrypted); + NEP6Account? account = _accounts.Values.FirstOrDefault(p => !p.Decrypted); if (account == null) { - account = accounts.Values.FirstOrDefault(p => p.HasKey); + account = _accounts.Values.FirstOrDefault(p => p.HasKey); } if (account == null) return true; if (account.Decrypted) @@ -341,9 +341,9 @@ private bool VerifyPasswordInternal(string password) public override bool ChangePassword(string oldPassword, string newPassword) { bool succeed = true; - lock (accounts) + lock (_accounts) { - Parallel.ForEach(accounts.Values, (account, state) => + Parallel.ForEach(_accounts.Values, (account, state) => { if (!account.ChangePasswordPrepare(oldPassword, newPassword)) { @@ -354,9 +354,9 @@ public override bool ChangePassword(string oldPassword, string newPassword) } if (succeed) { - lock (accounts) + lock (_accounts) { - foreach (NEP6Account account in accounts.Values) + foreach (NEP6Account account in _accounts.Values) account.ChangePasswordCommit(); } @@ -364,9 +364,9 @@ public override bool ChangePassword(string oldPassword, string newPassword) } else { - lock (accounts) + lock (_accounts) { - foreach (NEP6Account account in accounts.Values) + foreach (NEP6Account account in _accounts.Values) account.ChangePasswordRoolback(); } } diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index 1c592359b5..3f04dea3c8 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -112,7 +112,7 @@ public abstract class Wallet /// /// The hash of the account. /// The account with the specified hash. - public abstract WalletAccount GetAccount(UInt160 scriptHash); + public abstract WalletAccount? GetAccount(UInt160 scriptHash); /// /// Gets all the accounts from the wallet. @@ -461,7 +461,7 @@ public virtual WalletAccount Import(string nep2, string passphrase, int N = 1638 /// The cosigners to be added to the transaction. /// The block environment to execute the transaction. If null, will be used. /// The created transaction. - public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, UInt160 from = null, Signer[] cosigners = null, Block persistingBlock = null) + public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, UInt160? from = null, Signer[]? cosigners = null, Block? persistingBlock = null) { UInt160[] accounts; if (from is null) @@ -474,7 +474,7 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, } Dictionary cosignerList = cosigners?.ToDictionary(p => p.Account) ?? new Dictionary(); byte[] script; - List<(UInt160 Account, BigInteger Value)> balances_gas = null; + List<(UInt160 Account, BigInteger Value)>? balances_gas = null; using (ScriptBuilder sb = new()) { foreach (var (assetId, group, sum) in outputs.GroupBy(p => p.AssetId, (k, g) => (k, g, g.Select(p => p.Value.Value).Sum()))) @@ -499,7 +499,7 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, var balances_used = FindPayingAccounts(balances, output.Value.Value); foreach (var (account, value) in balances_used) { - if (cosignerList.TryGetValue(account, out Signer signer)) + if (cosignerList.TryGetValue(account, out Signer? signer)) { if (signer.Scopes != WitnessScope.Global) signer.Scopes |= WitnessScope.CalledByEntry; @@ -538,7 +538,7 @@ public Transaction MakeTransaction(DataCache snapshot, TransferOutput[] outputs, /// The maximum gas that can be spent to execute the script. /// The block environment to execute the transaction. If null, will be used. /// The created transaction. - public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, UInt160 sender = null, Signer[] cosigners = null, TransactionAttribute[] attributes = null, long maxGas = ApplicationEngine.TestModeGas, Block persistingBlock = null) + public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, UInt160? sender = null, Signer[]? cosigners = null, TransactionAttribute[]? attributes = null, long maxGas = ApplicationEngine.TestModeGas, Block? persistingBlock = null) { UInt160[] accounts; if (sender is null) @@ -603,8 +603,8 @@ public long CalculateNetworkFee(DataCache snapshot, Transaction tx, long maxExec foreach (UInt160 hash in hashes) { index++; - byte[] witness_script = GetAccount(hash)?.Contract?.Script; - byte[] invocationScript = null; + byte[]? witness_script = GetAccount(hash)?.Contract?.Script; + byte[]? invocationScript = null; if (tx.Witnesses != null) { @@ -682,13 +682,13 @@ public bool Sign(ContractParametersContext context) bool fSuccess = false; foreach (UInt160 scriptHash in context.ScriptHashes) { - WalletAccount account = GetAccount(scriptHash); + WalletAccount? account = GetAccount(scriptHash); if (account != null) { // Try to sign self-contained multiSig - Contract multiSigContract = account.Contract; + Contract? multiSigContract = account.Contract; if (multiSigContract != null && IsMultiSigContract(multiSigContract.Script, out int m, out ECPoint[] points)) @@ -696,7 +696,7 @@ public bool Sign(ContractParametersContext context) foreach (var point in points) { account = GetAccount(point); - if (account?.HasKey != true) continue; + if (account.HasKey != true) continue; KeyPair key = account.GetKey(); byte[] signature = context.Verifiable.Sign(key, context.Network); fSuccess |= context.AddSignature(multiSigContract, key.PublicKey, signature); @@ -708,7 +708,7 @@ public bool Sign(ContractParametersContext context) else if (account.HasKey) { // Try to sign with regular accounts - KeyPair key = account.GetKey(); + KeyPair key = account.GetKey()!; byte[] signature = context.Verifiable.Sign(key, context.Network); fSuccess |= context.AddSignature(account.Contract, key.PublicKey, signature); continue; @@ -747,12 +747,12 @@ public bool Sign(ContractParametersContext context) /// public abstract void Save(); - public static Wallet Create(string name, string path, string password, ProtocolSettings settings) + public static Wallet? Create(string name, string path, string password, ProtocolSettings settings) { return GetFactory(path)?.CreateWallet(name, path, password, settings); } - public static Wallet Open(string path, string password, ProtocolSettings settings) + public static Wallet? Open(string path, string password, ProtocolSettings settings) { return GetFactory(path)?.OpenWallet(path, password, settings); } From cfaa143b246dd325ececdcdcd1e36ac2ad035021 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 12:07:33 +0800 Subject: [PATCH 22/36] fix UT --- src/Neo/Wallets/Wallet.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index 3f04dea3c8..4fc9c7161f 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -237,7 +237,7 @@ public WalletAccount CreateAccount(Contract contract, byte[] privateKey) /// /// The public key of the account. /// The account with the specified public key. - public WalletAccount GetAccount(ECPoint pubkey) + public WalletAccount? GetAccount(ECPoint pubkey) { return GetAccount(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash()); } @@ -696,7 +696,7 @@ public bool Sign(ContractParametersContext context) foreach (var point in points) { account = GetAccount(point); - if (account.HasKey != true) continue; + if (account == null || account.HasKey != true) continue; KeyPair key = account.GetKey(); byte[] signature = context.Verifiable.Sign(key, context.Network); fSuccess |= context.AddSignature(multiSigContract, key.PublicKey, signature); @@ -708,7 +708,7 @@ public bool Sign(ContractParametersContext context) else if (account.HasKey) { // Try to sign with regular accounts - KeyPair key = account.GetKey()!; + KeyPair key = account.GetKey(); byte[] signature = context.Verifiable.Sign(key, context.Network); fSuccess |= context.AddSignature(account.Contract, key.PublicKey, signature); continue; From 666983a8db03e9c31d92f962563ca6b6c4eaccf3 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 12:55:26 +0800 Subject: [PATCH 23/36] more nullable to smart contract --- .../SmartContract/Native/OracleContract.cs | 50 +++++++++++-------- src/Neo/Wallets/Wallet.cs | 2 +- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/Neo/SmartContract/Native/OracleContract.cs b/src/Neo/SmartContract/Native/OracleContract.cs index 42f41f5720..eb07e5b5a3 100644 --- a/src/Neo/SmartContract/Native/OracleContract.cs +++ b/src/Neo/SmartContract/Native/OracleContract.cs @@ -100,7 +100,7 @@ private void SetPrice(ApplicationEngine engine, long price) if (price <= 0) throw new ArgumentOutOfRangeException(nameof(price)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Price)).Set(price); + engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_Price))?.Set(price); } /// @@ -117,12 +117,13 @@ public long GetPrice(DataCache snapshot) [ContractMethod(RequiredCallFlags = CallFlags.States | CallFlags.AllowCall | CallFlags.AllowNotify)] private ContractTask Finish(ApplicationEngine engine) { - if (engine.InvocationStack.Count != 2) throw new InvalidOperationException(); - if (engine.GetInvocationCounter() != 1) throw new InvalidOperationException(); - Transaction tx = (Transaction)engine.ScriptContainer; - OracleResponse response = tx.GetAttribute(); + if(engine.Snapshot == null) throw new InvalidOperationException($"{engine.Snapshot} is null"); + if (engine.InvocationStack.Count != 2) throw new InvalidOperationException("The invocation stack is invalid"); + if (engine.GetInvocationCounter() != 1) throw new InvalidOperationException("The invocation counter is invalid"); + Transaction? tx = (Transaction?)engine.ScriptContainer; + OracleResponse? response = tx?.GetAttribute(); if (response == null) throw new ArgumentException("Oracle response was not found"); - OracleRequest request = GetRequest(engine.Snapshot, response.Id); + OracleRequest? request = GetRequest(engine.Snapshot, response.Id); if (request == null) throw new ArgumentException("Oracle request was not found"); engine.SendNotification(Hash, "OracleResponse", new VM.Types.Array(engine.ReferenceCounter) { response.Id, request.OriginalTxid.ToArray() }); StackItem userData = BinarySerializer.Deserialize(request.UserData, engine.Limits, engine.ReferenceCounter); @@ -131,10 +132,13 @@ private ContractTask Finish(ApplicationEngine engine) private UInt256 GetOriginalTxid(ApplicationEngine engine) { + if(engine.ScriptContainer == null) throw new InvalidOperationException($"{engine.ScriptContainer} is null"); + if(engine.Snapshot == null) throw new InvalidOperationException($"{engine.Snapshot} is null"); Transaction tx = (Transaction)engine.ScriptContainer; - OracleResponse response = tx.GetAttribute(); + OracleResponse? response = tx.GetAttribute(); if (response is null) return tx.Hash; - OracleRequest request = GetRequest(engine.Snapshot, response.Id); + OracleRequest? request = GetRequest(engine.Snapshot, response.Id); + if(request is null) throw new InvalidOperationException("Oracle request was not found"); return request.OriginalTxid; } @@ -144,7 +148,7 @@ private UInt256 GetOriginalTxid(ApplicationEngine engine) /// The snapshot used to read data. /// The id of the request. /// The pending request. Or if no request with the specified id is found. - public OracleRequest GetRequest(DataCache snapshot, ulong id) + public OracleRequest? GetRequest(DataCache snapshot, ulong id) { return snapshot.TryGet(CreateStorageKey(Prefix_Request).AddBigEndian(id))?.GetInteroperable(); } @@ -167,7 +171,7 @@ public OracleRequest GetRequest(DataCache snapshot, ulong id) /// All the requests with the specified url. public IEnumerable<(ulong, OracleRequest)> GetRequestsByUrl(DataCache snapshot, string url) { - IdList list = snapshot.TryGet(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)))?.GetInteroperable(); + IdList? list = snapshot.TryGet(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)))?.GetInteroperable(); if (list is null) yield break; foreach (ulong id in list) yield return (id, snapshot[CreateStorageKey(Prefix_Request).AddBigEndian(id)].GetInteroperable()); @@ -187,23 +191,24 @@ internal override ContractTask Initialize(ApplicationEngine engine) internal override async ContractTask PostPersist(ApplicationEngine engine) { - (UInt160 Account, BigInteger GAS)[] nodes = null; + if (engine.PersistingBlock == null || engine.Snapshot == null) throw new InvalidOperationException($"{nameof(engine.PersistingBlock)} or {nameof(engine.Snapshot)} is null"); + (UInt160 Account, BigInteger GAS)[]? nodes = null; foreach (Transaction tx in engine.PersistingBlock.Transactions) { //Filter the response transactions - OracleResponse response = tx.GetAttribute(); + OracleResponse? response = tx.GetAttribute(); if (response is null) continue; //Remove the request from storage StorageKey key = CreateStorageKey(Prefix_Request).AddBigEndian(response.Id); - OracleRequest request = engine.Snapshot.TryGet(key)?.GetInteroperable(); + OracleRequest? request = engine.Snapshot.TryGet(key)?.GetInteroperable(); if (request == null) continue; engine.Snapshot.Delete(key); //Remove the id from IdList key = CreateStorageKey(Prefix_IdList).Add(GetUrlHash(request.Url)); - IdList list = engine.Snapshot.GetAndChange(key).GetInteroperable(); - if (!list.Remove(response.Id)) throw new InvalidOperationException(); + IdList? list = engine.Snapshot.GetAndChange(key)?.GetInteroperable(); + if (list == null || !list.Remove(response.Id)) throw new InvalidOperationException(); if (list.Count == 0) engine.Snapshot.Delete(key); //Mint GAS for oracle nodes @@ -225,7 +230,7 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) } [ContractMethod(RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] - private async ContractTask Request(ApplicationEngine engine, string url, string filter, string callback, StackItem userData, long gasForResponse) + private async ContractTask Request(ApplicationEngine engine, string url, string? filter, string callback, StackItem userData, long gasForResponse) { //Check the arguments if (Utility.StrictUTF8.GetByteCount(url) > MaxUrlLength @@ -234,6 +239,8 @@ private async ContractTask Request(ApplicationEngine engine, string url, string || gasForResponse < 0_10000000) throw new ArgumentException(); + if (engine.Snapshot == null) throw new InvalidOperationException($"{engine.Snapshot} is null"); + engine.AddGas(GetPrice(engine.Snapshot)); //Mint gas for the response @@ -241,13 +248,13 @@ private async ContractTask Request(ApplicationEngine engine, string url, string await GAS.Mint(engine, Hash, gasForResponse, false); //Increase the request id - StorageItem item_id = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RequestId)); + StorageItem item_id = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RequestId))!; ulong id = (ulong)(BigInteger)item_id; item_id.Add(1); //Put the request to storage if (ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash) is null) - throw new InvalidOperationException(); + throw new InvalidOperationException("The calling contract is not deployed"); engine.Snapshot.Add(CreateStorageKey(Prefix_Request).AddBigEndian(id), new StorageItem(new OracleRequest { OriginalTxid = GetOriginalTxid(engine), @@ -260,7 +267,10 @@ private async ContractTask Request(ApplicationEngine engine, string url, string })); //Add the id to the IdList - var list = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)), () => new StorageItem(new IdList())).GetInteroperable(); + var list = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)), () => new StorageItem(new IdList()))?.GetInteroperable(); + + if(list == null) throw new InvalidOperationException($"{nameof(list)} is null"); + if (list.Count >= 256) throw new InvalidOperationException("There are too many pending responses for this url"); list.Add(id); @@ -271,7 +281,7 @@ private async ContractTask Request(ApplicationEngine engine, string url, string [ContractMethod(CpuFee = 1 << 15)] private bool Verify(ApplicationEngine engine) { - Transaction tx = (Transaction)engine.ScriptContainer; + Transaction? tx = (Transaction?)engine.ScriptContainer; return tx?.GetAttribute() != null; } diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index 4fc9c7161f..6e1dc05dd4 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -248,7 +248,7 @@ public WalletAccount CreateAccount(Contract contract, byte[] privateKey) /// The default account of the wallet. public virtual WalletAccount GetDefaultAccount() { - WalletAccount first = null; + WalletAccount? first = null; foreach (WalletAccount account in GetAccounts()) { if (account.IsDefault) return account; From 52c01dec9cb880d44234e6495edc0645c131c38e Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 13:08:14 +0800 Subject: [PATCH 24/36] more nullable to smart contract --- .../ApplicationEngine.Storage.cs | 14 +++++++--- src/Neo/SmartContract/Native/NeoToken.cs | 28 +++++++++++++------ .../SmartContract/Native/OracleContract.cs | 12 ++++---- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.Storage.cs b/src/Neo/SmartContract/ApplicationEngine.Storage.cs index a5857980e7..f4c9b78768 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Storage.cs @@ -77,7 +77,10 @@ partial class ApplicationEngine /// The storage context for the current contract. protected internal StorageContext GetStorageContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + if(Snapshot is null) throw new InvalidOperationException("No storage context available."); + if(CurrentScriptHash is null) throw new InvalidOperationException($"{nameof(CurrentScriptHash)} is null."); + ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + if (contract is null) throw new InvalidOperationException($"Contract does not exist: {CurrentScriptHash}"); return new StorageContext { Id = contract.Id, @@ -92,7 +95,10 @@ protected internal StorageContext GetStorageContext() /// The storage context for the current contract. protected internal StorageContext GetReadOnlyContext() { - ContractState contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + if(Snapshot is null) throw new InvalidOperationException("No storage context available."); + if(CurrentScriptHash is null) throw new InvalidOperationException($"{nameof(CurrentScriptHash)} is null."); + ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); + if (contract is null) throw new InvalidOperationException($"Contract does not exist: {CurrentScriptHash}"); return new StorageContext { Id = contract.Id, @@ -126,7 +132,7 @@ protected internal static StorageContext AsReadOnly(StorageContext context) /// The value of the entry. Or if the entry doesn't exist. protected internal ReadOnlyMemory? Get(StorageContext context, byte[] key) { - return Snapshot.TryGet(new StorageKey + return Snapshot?.TryGet(new StorageKey { Id = context.Id, Key = key @@ -208,7 +214,7 @@ protected internal void Put(StorageContext context, byte[] key, byte[] value) protected internal void Delete(StorageContext context, byte[] key) { if (context.IsReadOnly) throw new ArgumentException(null, nameof(context)); - Snapshot.Delete(new StorageKey + Snapshot?.Delete(new StorageKey { Id = context.Id, Key = key diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index a6173c7be4..f6c884e185 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -246,7 +246,8 @@ internal override ContractTask OnPersist(ApplicationEngine engine) internal override async ContractTask PostPersist(ApplicationEngine engine) { // Distribute GAS for committee - + if(engine.PersistingBlock == null) throw new InvalidOperationException("The persisting block is null."); + if (engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); int m = engine.ProtocolSettings.CommitteeMembersCount; int n = engine.ProtocolSettings.ValidatorsCount; int index = (int)(engine.PersistingBlock.Index % (uint)m); @@ -269,7 +270,8 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) { BigInteger voterSumRewardPerNEO = factor * voterRewardOfEachCommittee / Votes; StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(PublicKey); - StorageItem lastRewardPerNeo = engine.Snapshot.GetAndChange(voterRewardKey, () => new StorageItem(BigInteger.Zero)); + StorageItem? lastRewardPerNeo = engine.Snapshot.GetAndChange(voterRewardKey, () => new StorageItem(BigInteger.Zero)); + if(lastRewardPerNeo == null) throw new InvalidOperationException("The lastRewardPerNeo is null."); lastRewardPerNeo.Add(voterSumRewardPerNEO); } } @@ -279,6 +281,9 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] private void SetGasPerBlock(ApplicationEngine engine, BigInteger gasPerBlock) { + if(engine.PersistingBlock == null) throw new InvalidOperationException("The persisting block is null."); + if (engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); + if (gasPerBlock < 0 || gasPerBlock > 10 * GAS.Factor) throw new ArgumentOutOfRangeException(nameof(gasPerBlock)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); @@ -305,7 +310,7 @@ private void SetRegisterPrice(ApplicationEngine engine, long registerPrice) if (registerPrice <= 0) throw new ArgumentOutOfRangeException(nameof(registerPrice)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_RegisterPrice)).Set(registerPrice); + engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_RegisterPrice))?.Set(registerPrice); } /// @@ -337,7 +342,7 @@ public long GetRegisterPrice(DataCache snapshot) [ContractMethod(CpuFee = 1 << 17, RequiredCallFlags = CallFlags.ReadStates)] public BigInteger UnclaimedGas(DataCache snapshot, UInt160 account, uint end) { - StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); + StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); if (storage is null) return BigInteger.Zero; NeoAccountState state = storage.GetInteroperable(); return CalculateBonus(snapshot, state, end); @@ -348,10 +353,12 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) return false; + if(engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); engine.AddGas(GetRegisterPrice(engine.Snapshot)); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); - StorageItem item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState())); - CandidateState state = item.GetInteroperable(); + StorageItem? item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState())); + CandidateState? state = item?.GetInteroperable(); + if(state == null) throw new InvalidOperationException("The candidate state is null."); if (state.Registered) return true; state.Registered = true; engine.SendNotification(Hash, "CandidateStateChanged", @@ -362,12 +369,14 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) { + if(engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) return false; StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); if (engine.Snapshot.TryGet(key) is null) return true; - StorageItem item = engine.Snapshot.GetAndChange(key); - CandidateState state = item.GetInteroperable(); + StorageItem? item = engine.Snapshot.GetAndChange(key); + CandidateState? state = item?.GetInteroperable(); + if(state == null) throw new InvalidOperationException("The candidate state is null."); if (!state.Registered) return true; state.Registered = false; CheckCandidate(engine.Snapshot, pubkey, state); @@ -379,6 +388,7 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] private async ContractTask Vote(ApplicationEngine engine, UInt160 account, ECPoint? voteTo) { + if(engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); if (!engine.CheckWitnessInternal(account)) return false; NeoAccountState? state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); if (state_account is null) return false; @@ -398,7 +408,7 @@ private async ContractTask Vote(ApplicationEngine engine, UInt160 account, else item.Add(-state_account.Balance); } - GasDistribution gasDistribution = DistributeGas(engine, account, state_account); + GasDistribution? gasDistribution = DistributeGas(engine, account, state_account); if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state_account.VoteTo); diff --git a/src/Neo/SmartContract/Native/OracleContract.cs b/src/Neo/SmartContract/Native/OracleContract.cs index eb07e5b5a3..04729ec148 100644 --- a/src/Neo/SmartContract/Native/OracleContract.cs +++ b/src/Neo/SmartContract/Native/OracleContract.cs @@ -117,7 +117,7 @@ public long GetPrice(DataCache snapshot) [ContractMethod(RequiredCallFlags = CallFlags.States | CallFlags.AllowCall | CallFlags.AllowNotify)] private ContractTask Finish(ApplicationEngine engine) { - if(engine.Snapshot == null) throw new InvalidOperationException($"{engine.Snapshot} is null"); + if (engine.Snapshot == null) throw new InvalidOperationException($"{engine.Snapshot} is null"); if (engine.InvocationStack.Count != 2) throw new InvalidOperationException("The invocation stack is invalid"); if (engine.GetInvocationCounter() != 1) throw new InvalidOperationException("The invocation counter is invalid"); Transaction? tx = (Transaction?)engine.ScriptContainer; @@ -132,13 +132,13 @@ private ContractTask Finish(ApplicationEngine engine) private UInt256 GetOriginalTxid(ApplicationEngine engine) { - if(engine.ScriptContainer == null) throw new InvalidOperationException($"{engine.ScriptContainer} is null"); - if(engine.Snapshot == null) throw new InvalidOperationException($"{engine.Snapshot} is null"); + if (engine.ScriptContainer == null) throw new InvalidOperationException($"{engine.ScriptContainer} is null"); + if (engine.Snapshot == null) throw new InvalidOperationException($"{engine.Snapshot} is null"); Transaction tx = (Transaction)engine.ScriptContainer; OracleResponse? response = tx.GetAttribute(); if (response is null) return tx.Hash; OracleRequest? request = GetRequest(engine.Snapshot, response.Id); - if(request is null) throw new InvalidOperationException("Oracle request was not found"); + if (request is null) throw new InvalidOperationException("Oracle request was not found"); return request.OriginalTxid; } @@ -191,7 +191,7 @@ internal override ContractTask Initialize(ApplicationEngine engine) internal override async ContractTask PostPersist(ApplicationEngine engine) { - if (engine.PersistingBlock == null || engine.Snapshot == null) throw new InvalidOperationException($"{nameof(engine.PersistingBlock)} or {nameof(engine.Snapshot)} is null"); + if (engine.PersistingBlock == null || engine.Snapshot == null) throw new InvalidOperationException($"{nameof(engine.PersistingBlock)} or {nameof(engine.Snapshot)} is null"); (UInt160 Account, BigInteger GAS)[]? nodes = null; foreach (Transaction tx in engine.PersistingBlock.Transactions) { @@ -269,7 +269,7 @@ private async ContractTask Request(ApplicationEngine engine, string url, string? //Add the id to the IdList var list = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_IdList).Add(GetUrlHash(url)), () => new StorageItem(new IdList()))?.GetInteroperable(); - if(list == null) throw new InvalidOperationException($"{nameof(list)} is null"); + if (list == null) throw new InvalidOperationException($"{nameof(list)} is null"); if (list.Count >= 256) throw new InvalidOperationException("There are too many pending responses for this url"); From 6e86102d9018aa29e30be7ab8a0bf9a7ca82e986 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 13:13:23 +0800 Subject: [PATCH 25/36] update format --- .../ApplicationEngine.Storage.cs | 8 +++---- src/Neo/SmartContract/Native/NeoToken.cs | 22 ++++++++++--------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.Storage.cs b/src/Neo/SmartContract/ApplicationEngine.Storage.cs index f4c9b78768..aa47f37edb 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Storage.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Storage.cs @@ -77,8 +77,8 @@ partial class ApplicationEngine /// The storage context for the current contract. protected internal StorageContext GetStorageContext() { - if(Snapshot is null) throw new InvalidOperationException("No storage context available."); - if(CurrentScriptHash is null) throw new InvalidOperationException($"{nameof(CurrentScriptHash)} is null."); + if (Snapshot is null) throw new InvalidOperationException("No storage context available."); + if (CurrentScriptHash is null) throw new InvalidOperationException($"{nameof(CurrentScriptHash)} is null."); ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); if (contract is null) throw new InvalidOperationException($"Contract does not exist: {CurrentScriptHash}"); return new StorageContext @@ -95,8 +95,8 @@ protected internal StorageContext GetStorageContext() /// The storage context for the current contract. protected internal StorageContext GetReadOnlyContext() { - if(Snapshot is null) throw new InvalidOperationException("No storage context available."); - if(CurrentScriptHash is null) throw new InvalidOperationException($"{nameof(CurrentScriptHash)} is null."); + if (Snapshot is null) throw new InvalidOperationException("No storage context available."); + if (CurrentScriptHash is null) throw new InvalidOperationException($"{nameof(CurrentScriptHash)} is null."); ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, CurrentScriptHash); if (contract is null) throw new InvalidOperationException($"Contract does not exist: {CurrentScriptHash}"); return new StorageContext diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index f6c884e185..410792aa98 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -246,7 +246,7 @@ internal override ContractTask OnPersist(ApplicationEngine engine) internal override async ContractTask PostPersist(ApplicationEngine engine) { // Distribute GAS for committee - if(engine.PersistingBlock == null) throw new InvalidOperationException("The persisting block is null."); + if (engine.PersistingBlock == null) throw new InvalidOperationException("The persisting block is null."); if (engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); int m = engine.ProtocolSettings.CommitteeMembersCount; int n = engine.ProtocolSettings.ValidatorsCount; @@ -271,7 +271,7 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) BigInteger voterSumRewardPerNEO = factor * voterRewardOfEachCommittee / Votes; StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(PublicKey); StorageItem? lastRewardPerNeo = engine.Snapshot.GetAndChange(voterRewardKey, () => new StorageItem(BigInteger.Zero)); - if(lastRewardPerNeo == null) throw new InvalidOperationException("The lastRewardPerNeo is null."); + if (lastRewardPerNeo == null) throw new InvalidOperationException("The lastRewardPerNeo is null."); lastRewardPerNeo.Add(voterSumRewardPerNEO); } } @@ -281,7 +281,7 @@ internal override async ContractTask PostPersist(ApplicationEngine engine) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] private void SetGasPerBlock(ApplicationEngine engine, BigInteger gasPerBlock) { - if(engine.PersistingBlock == null) throw new InvalidOperationException("The persisting block is null."); + if (engine.PersistingBlock == null) throw new InvalidOperationException("The persisting block is null."); if (engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); if (gasPerBlock < 0 || gasPerBlock > 10 * GAS.Factor) @@ -353,12 +353,13 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) { if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) return false; - if(engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); + + if (engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); engine.AddGas(GetRegisterPrice(engine.Snapshot)); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); StorageItem? item = engine.Snapshot.GetAndChange(key, () => new StorageItem(new CandidateState())); CandidateState? state = item?.GetInteroperable(); - if(state == null) throw new InvalidOperationException("The candidate state is null."); + if (state == null) throw new InvalidOperationException("The candidate state is null."); if (state.Registered) return true; state.Registered = true; engine.SendNotification(Hash, "CandidateStateChanged", @@ -369,14 +370,14 @@ private bool RegisterCandidate(ApplicationEngine engine, ECPoint pubkey) [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) { - if(engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); + if (engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); if (!engine.CheckWitnessInternal(Contract.CreateSignatureRedeemScript(pubkey).ToScriptHash())) return false; StorageKey key = CreateStorageKey(Prefix_Candidate).Add(pubkey); if (engine.Snapshot.TryGet(key) is null) return true; StorageItem? item = engine.Snapshot.GetAndChange(key); CandidateState? state = item?.GetInteroperable(); - if(state == null) throw new InvalidOperationException("The candidate state is null."); + if (state == null) throw new InvalidOperationException("The candidate state is null."); if (!state.Registered) return true; state.Registered = false; CheckCandidate(engine.Snapshot, pubkey, state); @@ -388,7 +389,7 @@ private bool UnregisterCandidate(ApplicationEngine engine, ECPoint pubkey) [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.States)] private async ContractTask Vote(ApplicationEngine engine, UInt160 account, ECPoint? voteTo) { - if(engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); + if (engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); if (!engine.CheckWitnessInternal(account)) return false; NeoAccountState? state_account = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account))?.GetInteroperable(); if (state_account is null) return false; @@ -412,8 +413,9 @@ private async ContractTask Vote(ApplicationEngine engine, UInt160 account, if (state_account.VoteTo != null) { StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state_account.VoteTo); - StorageItem storage_validator = engine.Snapshot.GetAndChange(key); - CandidateState state_validator = storage_validator.GetInteroperable(); + StorageItem? storage_validator = engine.Snapshot.GetAndChange(key); + CandidateState? state_validator = storage_validator?.GetInteroperable(); + if (state_validator == null) throw new InvalidOperationException("The state validator is null."); state_validator.Votes -= state_account.Balance; CheckCandidate(engine.Snapshot, state_account.VoteTo, state_validator); } From 0337a177c4827ff9c50d87fb9354df47433f7038 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 14:00:53 +0800 Subject: [PATCH 26/36] more nullable, 570 nullable warnings to go --- src/Neo/SmartContract/ApplicationEngine.cs | 5 +++-- src/Neo/SmartContract/Native/ContractManagement.cs | 5 +++-- src/Neo/SmartContract/Native/FungibleToken.cs | 14 +++++++------- src/Neo/SmartContract/Native/LedgerContract.cs | 9 ++++++--- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 637c438c93..6bf0ba8404 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -235,8 +235,9 @@ private ExecutionContext CallContractInternal(ContractState contract, ContractMe invocationCounter[contract.Hash] = 1; } - ExecutionContext currentContext = CurrentContext; - ExecutionContextState state = currentContext.GetState(); + ExecutionContext? currentContext = CurrentContext; + ExecutionContextState? state = currentContext?.GetState(); + if (state is null) throw new InvalidOperationException("No context to call contract."); CallFlags callingFlags = state.CallFlags; if (args.Count != method.Parameters.Length) throw new InvalidOperationException($"Method {method} Expects {method.Parameters.Length} Arguments But Receives {args.Count} Arguments"); diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 2df0e87600..a59f685fad 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -133,7 +133,7 @@ private void SetMinimumDeploymentFee(ApplicationEngine engine, BigInteger value) { if (value < 0) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_MinimumDeploymentFee)).Set(value); + engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_MinimumDeploymentFee))?.Set(value); } /// @@ -273,7 +273,7 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); - var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable(); + var contract = engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable(); if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}"); if (contract.UpdateCounter == ushort.MaxValue) throw new InvalidOperationException($"The contract reached the maximum number of updates."); @@ -304,6 +304,7 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private void Destroy(ApplicationEngine engine) { + if(engine.Snapshot is null) throw new InvalidOperationException("Invalid snapshot"); UInt160? hash = engine.CallingScriptHash; StorageKey ckey = CreateStorageKey(Prefix_Contract).Add(hash); ContractState? contract = engine.Snapshot.TryGet(ckey)?.GetInteroperable(); diff --git a/src/Neo/SmartContract/Native/FungibleToken.cs b/src/Neo/SmartContract/Native/FungibleToken.cs index 1a3a2ac532..dab7005dc9 100644 --- a/src/Neo/SmartContract/Native/FungibleToken.cs +++ b/src/Neo/SmartContract/Native/FungibleToken.cs @@ -110,15 +110,15 @@ internal async ContractTask Burn(ApplicationEngine engine, UInt160 account, BigI if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); if (amount.IsZero) return; StorageKey key = CreateStorageKey(Prefix_Account).Add(account); - StorageItem storage = engine.Snapshot.GetAndChange(key); - TState state = storage.GetInteroperable(); - if (state.Balance < amount) throw new InvalidOperationException(); + StorageItem? storage = engine.Snapshot?.GetAndChange(key); + TState? state = storage?.GetInteroperable(); + if (state == null || state.Balance < amount) throw new InvalidOperationException("Insufficient funds."); OnBalanceChanging(engine, account, state, -amount); if (state.Balance == amount) - engine.Snapshot.Delete(key); + engine.Snapshot?.Delete(key); else state.Balance -= amount; - storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply)); + storage = engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_TotalSupply)); storage.Add(-amount); await PostTransfer(engine, account, null, amount, StackItem.Null, false); } @@ -145,7 +145,7 @@ public virtual BigInteger TotalSupply(DataCache snapshot) [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public virtual BigInteger BalanceOf(DataCache snapshot, UInt160 account) { - StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); + StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_Account).Add(account)); if (storage is null) return BigInteger.Zero; return storage.GetInteroperable().Balance; } @@ -199,7 +199,7 @@ internal virtual void OnBalanceChanging(ApplicationEngine engine, UInt160 accoun { } - private protected virtual async ContractTask PostTransfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount, StackItem data, bool callOnPayment) + private protected virtual async ContractTask PostTransfer(ApplicationEngine engine, UInt160? from, UInt160? to, BigInteger amount, StackItem data, bool callOnPayment) { // Send notification diff --git a/src/Neo/SmartContract/Native/LedgerContract.cs b/src/Neo/SmartContract/Native/LedgerContract.cs index 46a1142c07..e1d9b491f2 100644 --- a/src/Neo/SmartContract/Native/LedgerContract.cs +++ b/src/Neo/SmartContract/Native/LedgerContract.cs @@ -38,6 +38,8 @@ internal LedgerContract() internal override ContractTask OnPersist(ApplicationEngine engine) { + if(engine.PersistingBlock == null) throw new InvalidOperationException("No persisting block"); + if(engine.Snapshot == null) throw new InvalidOperationException("No snapshot"); TransactionState[] transactions = engine.PersistingBlock.Transactions.Select(p => new TransactionState { BlockIndex = engine.PersistingBlock.Index, @@ -56,10 +58,10 @@ internal override ContractTask OnPersist(ApplicationEngine engine) var conflictingSigners = tx.Transaction.Signers.Select(s => s.Account); foreach (var attr in tx.Transaction.GetAttributes()) { - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash), () => new StorageItem(new TransactionState())).FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash), () => new StorageItem(new TransactionState()))?.FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); foreach (var signer in conflictingSigners) { - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash).Add(signer), () => new StorageItem(new TransactionState())).FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash).Add(signer), () => new StorageItem(new TransactionState()))?.FromReplica(new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); } } } @@ -69,7 +71,8 @@ internal override ContractTask OnPersist(ApplicationEngine engine) internal override ContractTask PostPersist(ApplicationEngine engine) { - HashIndexState state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_CurrentBlock), () => new StorageItem(new HashIndexState())).GetInteroperable(); + HashIndexState? state = engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_CurrentBlock), () => new StorageItem(new HashIndexState()))?.GetInteroperable(); + if(state == null || engine.PersistingBlock == null) throw new InvalidOperationException("No persisting block"); state.Hash = engine.PersistingBlock.Hash; state.Index = engine.PersistingBlock.Index; return ContractTask.CompletedTask; From 8d7558b77b4e1bd958a71107fdbed15c70a40c4c Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 14:24:32 +0800 Subject: [PATCH 27/36] add more nullable --- .../Native/ContractManagement.cs | 22 +++++++-------- src/Neo/SmartContract/Native/FungibleToken.cs | 20 +++++++------- .../SmartContract/Native/HashIndexState.cs | 2 +- .../SmartContract/Native/LedgerContract.cs | 27 ++++++++++--------- .../SmartContract/Native/NativeContract.cs | 11 ++++---- src/Neo/SmartContract/Native/NeoToken.cs | 2 +- 6 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index a59f685fad..1248b36bc9 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -107,16 +107,16 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) { foreach (NativeContract contract in Contracts) { - if (contract.IsInitializeBlock(engine.ProtocolSettings, engine.PersistingBlock.Index)) + if (contract.IsInitializeBlock(engine.ProtocolSettings, engine.PersistingBlock.NotNull().Index)) { - engine.Snapshot.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(new ContractState + engine.Snapshot.NotNull().Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(new ContractState { Id = contract.Id, Nef = contract.Nef, Hash = contract.Hash, Manifest = contract.Manifest })); - engine.Snapshot.Add(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id), new StorageItem(contract.Hash.ToArray())); + engine.Snapshot.NotNull().Add(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id), new StorageItem(contract.Hash.ToArray())); await contract.Initialize(engine); } } @@ -227,7 +227,7 @@ private async ContractTask Deploy(ApplicationEngine engine, byte[ engine.AddGas(Math.Max( engine.StoragePrice * (nefFile.Length + manifest.Length), - GetMinimumDeploymentFee(engine.Snapshot) + GetMinimumDeploymentFee(engine.Snapshot.NotNull()) )); NefFile nef = nefFile.AsSerializable(); @@ -235,15 +235,15 @@ private async ContractTask Deploy(ApplicationEngine engine, byte[ Helper.Check(new VM.Script(nef.Script, engine.IsHardforkEnabled(Hardfork.HF_Basilisk)), parsedManifest.Abi); UInt160 hash = Helper.GetContractHash(tx.Sender, nef.CheckSum, parsedManifest.Name); - if (Policy.IsBlocked(engine.Snapshot, hash)) + if (Policy.IsBlocked(engine.Snapshot.NotNull(), hash)) throw new InvalidOperationException($"The contract {hash} has been blocked."); StorageKey key = CreateStorageKey(Prefix_Contract).Add(hash); - if (engine.Snapshot.Contains(key)) + if (engine.Snapshot.NotNull().Contains(key)) throw new InvalidOperationException($"Contract Already Exists: {hash}"); ContractState contract = new() { - Id = GetNextAvailableId(engine.Snapshot), + Id = GetNextAvailableId(engine.Snapshot.NotNull()), UpdateCounter = 0, Nef = nef, Hash = hash, @@ -252,8 +252,8 @@ private async ContractTask Deploy(ApplicationEngine engine, byte[ if (!contract.Manifest.IsValid(engine.Limits, hash)) throw new InvalidOperationException($"Invalid Manifest: {hash}"); - engine.Snapshot.Add(key, new StorageItem(contract)); - engine.Snapshot.Add(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id), new StorageItem(hash.ToArray())); + engine.Snapshot.NotNull().Add(key, new StorageItem(contract)); + engine.Snapshot.NotNull().Add(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id), new StorageItem(hash.ToArray())); await OnDeploy(engine, contract, data, false); @@ -273,7 +273,7 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0))); - var contract = engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable(); + var contract = engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash.NotNull()))?.GetInteroperable(); if (contract is null) throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}"); if (contract.UpdateCounter == ushort.MaxValue) throw new InvalidOperationException($"The contract reached the maximum number of updates."); @@ -304,7 +304,7 @@ private ContractTask Update(ApplicationEngine engine, byte[] nefFile, byte[] man [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] private void Destroy(ApplicationEngine engine) { - if(engine.Snapshot is null) throw new InvalidOperationException("Invalid snapshot"); + if (engine.Snapshot is null) throw new InvalidOperationException("Invalid snapshot"); UInt160? hash = engine.CallingScriptHash; StorageKey ckey = CreateStorageKey(Prefix_Contract).Add(hash); ContractState? contract = engine.Snapshot.TryGet(ckey)?.GetInteroperable(); diff --git a/src/Neo/SmartContract/Native/FungibleToken.cs b/src/Neo/SmartContract/Native/FungibleToken.cs index dab7005dc9..376e14ccac 100644 --- a/src/Neo/SmartContract/Native/FungibleToken.cs +++ b/src/Neo/SmartContract/Native/FungibleToken.cs @@ -96,12 +96,12 @@ internal async ContractTask Mint(ApplicationEngine engine, UInt160 account, BigI { if (amount.Sign < 0) throw new ArgumentOutOfRangeException(nameof(amount)); if (amount.IsZero) return; - StorageItem storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Account).Add(account), () => new StorageItem(new TState())); - TState state = storage.GetInteroperable(); + StorageItem? storage = engine.Snapshot.NotNull().GetAndChange(CreateStorageKey(Prefix_Account).Add(account), () => new StorageItem(new TState())); + TState state = storage.NotNull().GetInteroperable().NotNull(); OnBalanceChanging(engine, account, state, amount); state.Balance += amount; - storage = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)); - storage.Add(amount); + storage = engine.Snapshot.NotNull().GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem(BigInteger.Zero)); + storage.NotNull().Add(amount); await PostTransfer(engine, null, account, amount, StackItem.Null, callOnPayment); } @@ -131,7 +131,7 @@ internal async ContractTask Burn(ApplicationEngine engine, UInt160 account, BigI [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] public virtual BigInteger TotalSupply(DataCache snapshot) { - StorageItem storage = snapshot.TryGet(CreateStorageKey(Prefix_TotalSupply)); + StorageItem? storage = snapshot.TryGet(CreateStorageKey(Prefix_TotalSupply)); if (storage is null) return BigInteger.Zero; return storage; } @@ -159,7 +159,7 @@ private protected async ContractTask Transfer(ApplicationEngine engine, UI if (!from.Equals(engine.CallingScriptHash) && !engine.CheckWitnessInternal(from)) return false; StorageKey key_from = CreateStorageKey(Prefix_Account).Add(from); - StorageItem storage_from = engine.Snapshot.GetAndChange(key_from); + StorageItem? storage_from = engine.Snapshot?.GetAndChange(key_from); if (amount.IsZero) { if (storage_from != null) @@ -181,12 +181,12 @@ private protected async ContractTask Transfer(ApplicationEngine engine, UI { OnBalanceChanging(engine, from, state_from, -amount); if (state_from.Balance == amount) - engine.Snapshot.Delete(key_from); + engine.Snapshot.NotNull().Delete(key_from); else state_from.Balance -= amount; StorageKey key_to = CreateStorageKey(Prefix_Account).Add(to); - StorageItem storage_to = engine.Snapshot.GetAndChange(key_to, () => new StorageItem(new TState())); - TState state_to = storage_to.GetInteroperable(); + StorageItem? storage_to = engine.Snapshot.NotNull().GetAndChange(key_to, () => new StorageItem(new TState())); + TState state_to = storage_to.NotNull().GetInteroperable().NotNull(); OnBalanceChanging(engine, to, state_to, amount); state_to.Balance += amount; } @@ -208,7 +208,7 @@ private protected virtual async ContractTask PostTransfer(ApplicationEngine engi // Check if it's a wallet or smart contract - if (!callOnPayment || to is null || ContractManagement.GetContract(engine.Snapshot, to) is null) return; + if (!callOnPayment || to is null || ContractManagement.GetContract(engine.Snapshot.NotNull(), to) is null) return; // Call onNEP17Payment method diff --git a/src/Neo/SmartContract/Native/HashIndexState.cs b/src/Neo/SmartContract/Native/HashIndexState.cs index 229458ffdd..4ed2cd2f58 100644 --- a/src/Neo/SmartContract/Native/HashIndexState.cs +++ b/src/Neo/SmartContract/Native/HashIndexState.cs @@ -27,7 +27,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) Index = (uint)@struct[1].GetInteger(); } - StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { Hash.ToArray(), Index }; } diff --git a/src/Neo/SmartContract/Native/LedgerContract.cs b/src/Neo/SmartContract/Native/LedgerContract.cs index e1d9b491f2..757e664c00 100644 --- a/src/Neo/SmartContract/Native/LedgerContract.cs +++ b/src/Neo/SmartContract/Native/LedgerContract.cs @@ -38,8 +38,8 @@ internal LedgerContract() internal override ContractTask OnPersist(ApplicationEngine engine) { - if(engine.PersistingBlock == null) throw new InvalidOperationException("No persisting block"); - if(engine.Snapshot == null) throw new InvalidOperationException("No snapshot"); + if (engine.PersistingBlock == null) throw new InvalidOperationException("No persisting block"); + if (engine.Snapshot == null) throw new InvalidOperationException("No snapshot"); TransactionState[] transactions = engine.PersistingBlock.Transactions.Select(p => new TransactionState { BlockIndex = engine.PersistingBlock.Index, @@ -72,7 +72,7 @@ internal override ContractTask OnPersist(ApplicationEngine engine) internal override ContractTask PostPersist(ApplicationEngine engine) { HashIndexState? state = engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_CurrentBlock), () => new StorageItem(new HashIndexState()))?.GetInteroperable(); - if(state == null || engine.PersistingBlock == null) throw new InvalidOperationException("No persisting block"); + if (state == null || engine.PersistingBlock == null) throw new InvalidOperationException("No persisting block"); state.Hash = engine.PersistingBlock.Hash; state.Index = engine.PersistingBlock.Index; return ContractTask.CompletedTask; @@ -193,14 +193,14 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerable GetTransaction(snapshot, p)).ToArray() + // Transactions are not supposed to be null, but we need to handle the case when it is. + Transactions = state.Hashes.Select(p => GetTransaction(snapshot, p).NotNull()).ToArray() }; } @@ -285,24 +286,24 @@ public bool ContainsConflictHash(DataCache snapshot, UInt256 hash, IEnumerable if the committee has witnessed the current transaction; otherwise, . protected static bool CheckCommittee(ApplicationEngine engine) { - UInt160 committeeMultiSigAddr = NEO.GetCommitteeAddress(engine.Snapshot); + UInt160 committeeMultiSigAddr = NEO.GetCommitteeAddress(engine.Snapshot.NotNull()); return engine.CheckWitnessInternal(committeeMultiSigAddr); } @@ -223,7 +222,7 @@ private protected KeyBuilder CreateStorageKey(byte prefix) /// /// The hash of the native contract. /// The native contract with the specified hash. - public static NativeContract GetContract(UInt160 hash) + public static NativeContract? GetContract(UInt160 hash) { contractsDictionary.TryGetValue(hash, out var contract); return contract; @@ -235,7 +234,7 @@ internal async void Invoke(ApplicationEngine engine, byte version) { if (version != 0) throw new InvalidOperationException($"The native contract of version {version} is not active."); - ExecutionContext context = engine.CurrentContext; + ExecutionContext context = engine.CurrentContext.NotNull(); ContractMethodMetadata method = methods[context.InstructionPointer]; ExecutionContextState state = context.GetState(); if (!state.CallFlags.HasFlag(method.RequiredCallFlags)) @@ -243,10 +242,10 @@ internal async void Invoke(ApplicationEngine engine, byte version) engine.AddGas(method.CpuFee * engine.ExecFeeFactor + method.StorageFee * engine.StoragePrice); List parameters = new(); if (method.NeedApplicationEngine) parameters.Add(engine); - if (method.NeedSnapshot) parameters.Add(engine.Snapshot); + if (method.NeedSnapshot) parameters.Add(engine.Snapshot.NotNull()); for (int i = 0; i < method.Parameters.Length; i++) parameters.Add(engine.Convert(context.EvaluationStack.Peek(i), method.Parameters[i])); - object returnValue = method.Handler.Invoke(this, parameters.ToArray()); + object? returnValue = method.Handler.Invoke(this, parameters.ToArray()); if (returnValue is ContractTask task) { await task; diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 410792aa98..37ded4da35 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -559,7 +559,7 @@ public ECPoint[] ComputeNextBlockValidators(DataCache snapshot, ProtocolSettings [ContractMethod(CpuFee = 1 << 16, RequiredCallFlags = CallFlags.ReadStates)] private ECPoint[] GetNextBlockValidators(ApplicationEngine engine) { - return GetNextBlockValidators(engine.Snapshot, engine.ProtocolSettings.ValidatorsCount); + return GetNextBlockValidators(engine.Snapshot.NotNull(), engine.ProtocolSettings.ValidatorsCount); } /// From e1470a26ea920520acadde81eea4c0e8990e5e90 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 15:22:45 +0800 Subject: [PATCH 28/36] fix more nullable for smart contract --- src/Neo/SmartContract/Contract.cs | 4 ++-- src/Neo/SmartContract/DeployedContract.cs | 4 ++-- .../InteropParameterDescriptor.cs | 2 +- .../Native/ContractMethodAttribute.cs | 2 +- src/Neo/SmartContract/Native/NeoToken.cs | 24 ++++++++++--------- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Neo/SmartContract/Contract.cs b/src/Neo/SmartContract/Contract.cs index dc60c42d50..95ffa2121f 100644 --- a/src/Neo/SmartContract/Contract.cs +++ b/src/Neo/SmartContract/Contract.cs @@ -25,14 +25,14 @@ public class Contract /// /// The script of the contract. /// - public byte[] Script; + public byte[]? Script; /// /// The parameters of the contract. /// public ContractParameterType[] ParameterList; - private UInt160 _scriptHash; + private UInt160? _scriptHash; /// /// The hash of the contract. /// diff --git a/src/Neo/SmartContract/DeployedContract.cs b/src/Neo/SmartContract/DeployedContract.cs index 0587a029e5..1bc3ea0236 100644 --- a/src/Neo/SmartContract/DeployedContract.cs +++ b/src/Neo/SmartContract/DeployedContract.cs @@ -26,13 +26,13 @@ public class DeployedContract : Contract /// Initializes a new instance of the class with the specified . /// /// The corresponding to the contract. - public DeployedContract(ContractState contract) + public DeployedContract(ContractState? contract) { if (contract is null) throw new ArgumentNullException(nameof(contract)); Script = null; ScriptHash = contract.Hash; - ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor? descriptor = contract.Manifest.Abi.GetMethod("verify", -1); if (descriptor is null) throw new NotSupportedException("The smart contract haven't got verify method."); ParameterList = descriptor.Parameters.Select(u => u.Type).ToArray(); diff --git a/src/Neo/SmartContract/InteropParameterDescriptor.cs b/src/Neo/SmartContract/InteropParameterDescriptor.cs index 6a65beb93f..a86931c924 100644 --- a/src/Neo/SmartContract/InteropParameterDescriptor.cs +++ b/src/Neo/SmartContract/InteropParameterDescriptor.cs @@ -56,7 +56,7 @@ public class InteropParameterDescriptor /// public bool IsInterface { get; } - private static readonly Dictionary> converters = new() + private static readonly Dictionary> converters = new() { [typeof(StackItem)] = p => p, [typeof(VM.Types.Pointer)] = p => p, diff --git a/src/Neo/SmartContract/Native/ContractMethodAttribute.cs b/src/Neo/SmartContract/Native/ContractMethodAttribute.cs index 55940f2eb3..ce0e545f0a 100644 --- a/src/Neo/SmartContract/Native/ContractMethodAttribute.cs +++ b/src/Neo/SmartContract/Native/ContractMethodAttribute.cs @@ -16,7 +16,7 @@ namespace Neo.SmartContract.Native [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false)] internal class ContractMethodAttribute : Attribute { - public string Name { get; init; } + public string? Name { get; init; } public CallFlags RequiredCallFlags { get; init; } public long CpuFee { get; init; } public long StorageFee { get; init; } diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 37ded4da35..9840a46660 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -122,25 +122,26 @@ public override BigInteger TotalSupply(DataCache snapshot) internal override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount) { + if (engine.Snapshot == null) throw new InvalidOperationException(""); GasDistribution? distribution = DistributeGas(engine, account, state); if (distribution is not null) { - var list = engine.CurrentContext.GetState>(); - list.Add(distribution); + var list = engine.CurrentContext?.GetState>(); + list.NotNull().Add(distribution); } if (amount.IsZero) return; if (state.VoteTo is null) return; - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)).Add(amount); + engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_VotersCount)).NotNull().Add(amount); StorageKey key = CreateStorageKey(Prefix_Candidate).Add(state.VoteTo); - CandidateState candidate = engine.Snapshot.GetAndChange(key).GetInteroperable(); - candidate.Votes += amount; - CheckCandidate(engine.Snapshot, state.VoteTo, candidate); + CandidateState? candidate = engine.Snapshot.GetAndChange(key)?.GetInteroperable(); + candidate.NotNull().Votes += amount; + CheckCandidate(engine.Snapshot, state.VoteTo, candidate!); } - private protected override async ContractTask PostTransfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount, StackItem data, bool callOnPayment) + private protected override async ContractTask PostTransfer(ApplicationEngine engine, UInt160? from, UInt160? to, BigInteger amount, StackItem data, bool callOnPayment) { await base.PostTransfer(engine, from, to, amount, data, callOnPayment); - var list = engine.CurrentContext.GetState>(); + var list = engine.CurrentContext?.GetState>(); foreach (var distribution in list) await GAS.Mint(engine, distribution.Account, distribution.Amount, callOnPayment); } @@ -149,7 +150,7 @@ private protected override async ContractTask PostTransfer(ApplicationEngine eng { // PersistingBlock is null when running under the debugger if (engine.PersistingBlock is null) return null; - + if (engine.Snapshot == null) throw new InvalidOperationException($"{engine.Snapshot} is null"); BigInteger gas = CalculateBonus(engine.Snapshot, state, engine.PersistingBlock.Index); state.BalanceHeight = engine.PersistingBlock.Index; if (state.VoteTo is not null) @@ -222,6 +223,7 @@ private void CheckCandidate(DataCache snapshot, ECPoint pubkey, CandidateState c internal override ContractTask Initialize(ApplicationEngine engine) { + if(engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); var cachedCommittee = new CachedCommittee(engine.ProtocolSettings.StandbyCommittee.Select(p => (p, BigInteger.Zero))); engine.Snapshot.Add(CreateStorageKey(Prefix_Committee), new StorageItem(cachedCommittee)); engine.Snapshot.Add(CreateStorageKey(Prefix_VotersCount), new StorageItem(System.Array.Empty())); @@ -233,9 +235,9 @@ internal override ContractTask Initialize(ApplicationEngine engine) internal override ContractTask OnPersist(ApplicationEngine engine) { // Set next committee - if (ShouldRefreshCommittee(engine.PersistingBlock.Index, engine.ProtocolSettings.CommitteeMembersCount)) + if (ShouldRefreshCommittee(engine.PersistingBlock.NotNull().Index, engine.ProtocolSettings.CommitteeMembersCount)) { - StorageItem storageItem = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Committee)); + StorageItem? storageItem = engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_Committee)); var cachedCommittee = storageItem.GetInteroperable(); cachedCommittee.Clear(); cachedCommittee.AddRange(ComputeCommitteeMembers(engine.Snapshot, engine.ProtocolSettings)); From 81e125e05393beb322a88ec87f2eb821c2204f3f Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 16:29:51 +0800 Subject: [PATCH 29/36] add more nullable --- src/Neo/Helper.cs | 8 +++++++- src/Neo/NeoSystem.cs | 2 +- src/Neo/Persistence/SnapshotCache.cs | 4 ++-- src/Neo/Plugins/Plugin.cs | 10 +++++----- src/Neo/SmartContract/ApplicationEngine.cs | 16 ++++++++-------- .../SmartContract/ContractParametersContext.cs | 12 ++++++------ src/Neo/SmartContract/ContractState.cs | 2 +- src/Neo/SmartContract/Native/NeoToken.cs | 5 +++-- src/Neo/SmartContract/Native/OracleRequest.cs | 2 +- src/Neo/Wallets/Wallet.cs | 10 +++++----- 10 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/Neo/Helper.cs b/src/Neo/Helper.cs index 5dbc89c213..0b6b667313 100644 --- a/src/Neo/Helper.cs +++ b/src/Neo/Helper.cs @@ -320,7 +320,13 @@ internal static T NullExceptionOr(this object? obj) where T : class [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T NotNull(this T? obj) where T : class { - if (obj == null) throw new NullReferenceException($"Object {nameof(obj)} is null."); + return obj.NotNull($"Object {nameof(obj)} is null."); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static T NotNull(this T? obj, string msg) where T : class + { + if (obj == null) throw new NullReferenceException(msg); return obj; } } diff --git a/src/Neo/NeoSystem.cs b/src/Neo/NeoSystem.cs index 0f27f7cd5c..25598a83c6 100644 --- a/src/Neo/NeoSystem.cs +++ b/src/Neo/NeoSystem.cs @@ -98,7 +98,7 @@ public class NeoSystem : IDisposable private ImmutableList services = ImmutableList.Empty; private readonly IStore store; - private ChannelsConfig start_message = null; + private ChannelsConfig? start_message = null; private int suspend = 0; static NeoSystem() diff --git a/src/Neo/Persistence/SnapshotCache.cs b/src/Neo/Persistence/SnapshotCache.cs index 8f117534f1..23271ff484 100644 --- a/src/Neo/Persistence/SnapshotCache.cs +++ b/src/Neo/Persistence/SnapshotCache.cs @@ -35,9 +35,9 @@ public SnapshotCache(IReadOnlyStore store) this.snapshot = store as ISnapshot; } - protected override void AddInternal(StorageKey key, StorageItem value) + protected override void AddInternal(StorageKey key, StorageItem? value) { - snapshot?.Put(key.ToArray(), value.ToArray()); + snapshot?.Put(key.ToArray(), value?.ToArray()); } protected override void DeleteInternal(StorageKey key) diff --git a/src/Neo/Plugins/Plugin.cs b/src/Neo/Plugins/Plugin.cs index 248301af56..50a618b33c 100644 --- a/src/Neo/Plugins/Plugin.cs +++ b/src/Neo/Plugins/Plugin.cs @@ -111,22 +111,22 @@ private static void ConfigWatcher_Changed(object sender, FileSystemEventArgs e) } } - private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + private static Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args) { if (args.Name.Contains(".resources")) return null; AssemblyName an = new(args.Name); - Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name) ?? + Assembly? assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name) ?? AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == an.Name); if (assembly != null) return assembly; string filename = an.Name + ".dll"; string path = filename; - if (!File.Exists(path)) path = Combine(GetDirectoryName(System.AppContext.BaseDirectory), filename); + if (!File.Exists(path)) path = Combine(GetDirectoryName(System.AppContext.BaseDirectory)!, filename); if (!File.Exists(path)) path = Combine(PluginsDirectory, filename); - if (!File.Exists(path)) path = Combine(PluginsDirectory, args.RequestingAssembly.GetName().Name, filename); + if (!File.Exists(path)) path = Combine(PluginsDirectory, args.RequestingAssembly!.GetName().Name!, filename); if (!File.Exists(path)) return null; try @@ -160,7 +160,7 @@ private static void LoadPlugin(Assembly assembly) if (!type.IsSubclassOf(typeof(Plugin))) continue; if (type.IsAbstract) continue; - ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes); + ConstructorInfo? constructor = type.GetConstructor(Type.EmptyTypes); try { constructor?.Invoke(null); diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 6bf0ba8404..3145372b8c 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -48,9 +48,9 @@ public partial class ApplicationEngine : ExecutionEngine public static event EventHandler Log; private static readonly IList AllHardforks = Enum.GetValues(typeof(Hardfork)).Cast().ToArray(); - private static Dictionary services; + private static Dictionary? services; private readonly long gas_amount; - private Dictionary states; + private Dictionary? states; private readonly DataCache? originalSnapshot; private List? notifications; private List? disposables; @@ -212,7 +212,7 @@ private ExecutionContext CallContractInternal(UInt160 contractHash, string metho private ExecutionContext CallContractInternal(ContractState contract, ContractMethodDescriptor method, CallFlags flags, bool hasReturnValue, IReadOnlyList args) { - if (NativeContract.Policy.IsBlocked(Snapshot, contract.Hash)) + if (NativeContract.Policy.IsBlocked(Snapshot.NotNull(), contract.Hash)) throw new InvalidOperationException($"The contract {contract.Hash} has been blocked."); if (method.Safe) @@ -396,11 +396,11 @@ public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialP protected override ExecutionContext LoadToken(ushort tokenId) { ValidateCallFlags(CallFlags.ReadStates | CallFlags.AllowCall); - ContractState contract = CurrentContext.GetState().Contract; + ContractState contract = CurrentContext.NotNull().GetState().Contract; if (contract is null || tokenId >= contract.Nef.Tokens.Length) throw new InvalidOperationException(); MethodToken token = contract.Nef.Tokens[tokenId]; - if (token.ParametersCount > CurrentContext.EvaluationStack.Count) + if (token.ParametersCount > CurrentContext.NotNull().EvaluationStack.Count) throw new InvalidOperationException(); StackItem[] args = new StackItem[token.ParametersCount]; for (int i = 0; i < token.ParametersCount; i++) @@ -500,7 +500,7 @@ public override void Dispose() /// The requirements to check. internal protected void ValidateCallFlags(CallFlags requiredCallFlags) { - ExecutionContextState state = CurrentContext.GetState(); + ExecutionContextState state = CurrentContext.NotNull().GetState(); if (!state.CallFlags.HasFlag(requiredCallFlags)) throw new InvalidOperationException($"Cannot call this SYSCALL with the flag {state.CallFlags}."); } @@ -601,10 +601,10 @@ public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snaps return engine; } - public T GetState() + public T? GetState() { if (states is null) return default; - if (!states.TryGetValue(typeof(T), out object state)) return default; + if (!states.TryGetValue(typeof(T), out object? state)) return default; return (T)state; } diff --git a/src/Neo/SmartContract/ContractParametersContext.cs b/src/Neo/SmartContract/ContractParametersContext.cs index c3f1a67369..c8e606c671 100644 --- a/src/Neo/SmartContract/ContractParametersContext.cs +++ b/src/Neo/SmartContract/ContractParametersContext.cs @@ -229,16 +229,16 @@ public static ContractParametersContext FromJson(JObject json, DataCache snapsho var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"].AsString()); if (!typeof(IVerifiable).IsAssignableFrom(type)) throw new FormatException(); - var verifiable = (IVerifiable)Activator.CreateInstance(type); - byte[] data = Convert.FromBase64String(json["data"].AsString()); + var verifiable = (IVerifiable?)Activator.CreateInstance(type); + byte[] data = Convert.FromBase64String(json["data"].NotNull().AsString()); MemoryReader reader = new(data); - verifiable.DeserializeUnsigned(ref reader); + verifiable.NotNull().DeserializeUnsigned(ref reader); if (json.ContainsProperty("hash")) { - UInt256 hash = UInt256.Parse(json["hash"].GetString()); - if (hash != verifiable.Hash) throw new FormatException(); + UInt256? hash = UInt256.Parse(json["hash"].NotNull().GetString().NotNull()); + if (hash == null || hash != verifiable!.Hash) throw new FormatException(); } - ContractParametersContext context = new(snapshot, verifiable, (uint)json["network"].GetInt32()); + ContractParametersContext context = new(snapshot, verifiable!, (uint)json["network"]!.GetInt32()); foreach (var (key, value) in ((JObject)json["items"]).Properties) { context.ContextItems.Add(UInt160.Parse(key), new ContextItem((JObject)value)); diff --git a/src/Neo/SmartContract/ContractState.cs b/src/Neo/SmartContract/ContractState.cs index 83ac9d3353..7c46f13fff 100644 --- a/src/Neo/SmartContract/ContractState.cs +++ b/src/Neo/SmartContract/ContractState.cs @@ -114,7 +114,7 @@ public JObject ToJson() }; } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Array(referenceCounter, new StackItem[] { Id, (int)UpdateCounter, Hash.ToArray(), Nef.ToArray(), Manifest.ToStackItem(referenceCounter) }); } diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 9840a46660..4d66672461 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -238,7 +238,7 @@ internal override ContractTask OnPersist(ApplicationEngine engine) if (ShouldRefreshCommittee(engine.PersistingBlock.NotNull().Index, engine.ProtocolSettings.CommitteeMembersCount)) { StorageItem? storageItem = engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_Committee)); - var cachedCommittee = storageItem.GetInteroperable(); + var cachedCommittee = storageItem?.GetInteroperable(); cachedCommittee.Clear(); cachedCommittee.AddRange(ComputeCommitteeMembers(engine.Snapshot, engine.ProtocolSettings)); } @@ -291,7 +291,8 @@ private void SetGasPerBlock(ApplicationEngine engine, BigInteger gasPerBlock) if (!CheckCommittee(engine)) throw new InvalidOperationException(); uint index = engine.PersistingBlock.Index + 1; - StorageItem entry = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(index), () => new StorageItem(gasPerBlock)); + StorageItem? entry = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_GasPerBlock).AddBigEndian(index), () => new StorageItem(gasPerBlock)); + if (entry == null) throw new KeyNotFoundException("The storage entry of gas per block was not found."); entry.Set(gasPerBlock); } diff --git a/src/Neo/SmartContract/Native/OracleRequest.cs b/src/Neo/SmartContract/Native/OracleRequest.cs index d18968ef00..a3a14fe0a7 100644 --- a/src/Neo/SmartContract/Native/OracleRequest.cs +++ b/src/Neo/SmartContract/Native/OracleRequest.cs @@ -68,7 +68,7 @@ public void FromStackItem(StackItem stackItem) UserData = array[6].GetSpan().ToArray(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Array(referenceCounter) { diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index 6e1dc05dd4..3677b6ed23 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -413,9 +413,9 @@ private static Signer[] GetSigners(UInt160 sender, Signer[] cosigners) public virtual WalletAccount Import(X509Certificate2 cert) { byte[] privateKey; - using (ECDsa ecdsa = cert.GetECDsaPrivateKey()) + using (ECDsa? ecdsa = cert.GetECDsaPrivateKey()) { - privateKey = ecdsa.ExportParameters(true).D; + privateKey = ecdsa.NotNull().ExportParameters(true).D.NotNull(); } WalletAccount account = CreateAccount(privateKey); Array.Clear(privateKey, 0, privateKey.Length); @@ -553,7 +553,7 @@ public Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory scri return MakeTransaction(snapshot, script, cosigners ?? Array.Empty(), attributes ?? Array.Empty(), balances_gas, maxGas, persistingBlock: persistingBlock); } - private Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, Signer[] cosigners, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas, long maxGas = ApplicationEngine.TestModeGas, Block persistingBlock = null) + private Transaction MakeTransaction(DataCache snapshot, ReadOnlyMemory script, Signer[] cosigners, TransactionAttribute[] attributes, List<(UInt160 Account, BigInteger Value)> balances_gas, long maxGas = ApplicationEngine.TestModeGas, Block? persistingBlock = null) { Random rand = new(); foreach (var (account, value) in balances_gas) @@ -697,7 +697,7 @@ public bool Sign(ContractParametersContext context) { account = GetAccount(point); if (account == null || account.HasKey != true) continue; - KeyPair key = account.GetKey(); + KeyPair key = account.GetKey().NotNull(); byte[] signature = context.Verifiable.Sign(key, context.Network); fSuccess |= context.AddSignature(multiSigContract, key.PublicKey, signature); if (fSuccess) m--; @@ -708,7 +708,7 @@ public bool Sign(ContractParametersContext context) else if (account.HasKey) { // Try to sign with regular accounts - KeyPair key = account.GetKey(); + KeyPair key = account.GetKey().NotNull($"Can not get the key pair from account {account}"); byte[] signature = context.Verifiable.Sign(key, context.Network); fSuccess |= context.AddSignature(account.Contract, key.PublicKey, signature); continue; From 113d90d7c3609befc56c795d937643f5c57a4da6 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 17:32:44 +0800 Subject: [PATCH 30/36] null wallet --- src/Neo/Wallets/Wallet.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index 3677b6ed23..5aa6bcd897 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -86,7 +86,7 @@ public abstract class Wallet /// The contract of the account. /// The private key of the account. /// The created account. - public abstract WalletAccount CreateAccount(Contract contract, KeyPair key = null); + public abstract WalletAccount CreateAccount(Contract contract, KeyPair? key = null); /// /// Creates a watch-only account for the wallet. @@ -165,7 +165,7 @@ public WalletAccount CreateAccount() /// The contract of the account. /// The private key of the account. /// The created account. - public WalletAccount CreateAccount(Contract contract, byte[] privateKey) + public WalletAccount CreateAccount(Contract contract, byte[]? privateKey) { if (privateKey == null) return CreateAccount(contract); return CreateAccount(contract, new KeyPair(privateKey)); @@ -245,8 +245,8 @@ public WalletAccount CreateAccount(Contract contract, byte[] privateKey) /// /// Gets the default account of the wallet. /// - /// The default account of the wallet. - public virtual WalletAccount GetDefaultAccount() + /// The default account of the wallet. Nullable. + public virtual WalletAccount? GetDefaultAccount() { WalletAccount? first = null; foreach (WalletAccount account in GetAccounts()) @@ -254,6 +254,8 @@ public virtual WalletAccount GetDefaultAccount() if (account.IsDefault) return account; if (first == null) first = account; } + // it is possible that even if we searched the entire wallet, + // we could not find any account return first; } From ac031b8eb07321851a3741c0396ba510760a4b25 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 17:33:03 +0800 Subject: [PATCH 31/36] nullable Iapplicationengineprovider --- src/Neo/SmartContract/IApplicationEngineProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/SmartContract/IApplicationEngineProvider.cs b/src/Neo/SmartContract/IApplicationEngineProvider.cs index 36c16dd0c6..d39286fda8 100644 --- a/src/Neo/SmartContract/IApplicationEngineProvider.cs +++ b/src/Neo/SmartContract/IApplicationEngineProvider.cs @@ -30,6 +30,6 @@ public interface IApplicationEngineProvider /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic); + ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic); } } From 44c45286769e82d223a09b15557f368f02f90672 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 17:33:12 +0800 Subject: [PATCH 32/36] nullable applicationengine --- src/Neo/SmartContract/ApplicationEngine.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 3145372b8c..7bd417d747 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -156,7 +156,7 @@ public UInt160? CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic) { this.Trigger = trigger; this.ScriptContainer = container; @@ -203,9 +203,9 @@ internal void Throw(Exception ex) private ExecutionContext CallContractInternal(UInt160 contractHash, string method, CallFlags flags, bool hasReturnValue, StackItem[] args) { - ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); + var contract = NativeContract.ContractManagement.GetContract(Snapshot.NotNull(), contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Length); + var md = contract.Manifest.Abi.GetMethod(method, args.Length); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Length} parameter(s) doesn't exist in the contract {contractHash}."); return CallContractInternal(contract, md, flags, hasReturnValue, args); } @@ -320,7 +320,7 @@ protected override void ContextUnloaded(ExecutionContext context) /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock = null, ProtocolSettings? settings = null, long gas = TestModeGas, IDiagnostic? diagnostic = null) { return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -383,8 +383,8 @@ public ExecutionContext LoadContract(ContractState contract, ContractMethodDescr public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action? configureState = null) { // Create and configure context - ExecutionContext context = CreateContext(script, rvcount, initialPosition); - ExecutionContextState state = context.GetState(); + var context = CreateContext(script, rvcount, initialPosition); + var state = context.GetState(); state.Snapshot = Snapshot?.CreateSnapshot(); configureState?.Invoke(state); @@ -507,7 +507,7 @@ internal protected void ValidateCallFlags(CallFlags requiredCallFlags) protected override void OnSysCall(uint method) { - OnSysCall(services[method]); + OnSysCall(services.NotNull()[method]); } /// @@ -523,8 +523,8 @@ protected virtual void OnSysCall(InteropDescriptor descriptor) for (int i = 0; i < parameters.Length; i++) parameters[i] = Convert(Pop(), descriptor.Parameters[i]); - object returnValue = descriptor.Handler.Invoke(this, parameters); - if (descriptor.Handler.ReturnType != typeof(void)) + object? returnValue = descriptor.Handler.Invoke(this, parameters); + if (returnValue != null && descriptor.Handler.ReturnType != typeof(void)) Push(Convert(returnValue)); } @@ -592,7 +592,7 @@ private static InteropDescriptor Register(string name, string handler, long fixe /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable container = null, Block persistingBlock = null, ProtocolSettings settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic diagnostic = null) + public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable? container = null, Block? persistingBlock = null, ProtocolSettings? settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic? diagnostic = null) { persistingBlock ??= CreateDummyBlock(snapshot, settings ?? ProtocolSettings.Default); ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, persistingBlock, settings, gas, diagnostic); From 292544502059758d5fab5fb7a5e305c8186f765f Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 17:33:25 +0800 Subject: [PATCH 33/36] Revert "nullable applicationengine" This reverts commit 44c45286769e82d223a09b15557f368f02f90672. --- src/Neo/SmartContract/ApplicationEngine.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 7bd417d747..3145372b8c 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -156,7 +156,7 @@ public UInt160? CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic) + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) { this.Trigger = trigger; this.ScriptContainer = container; @@ -203,9 +203,9 @@ internal void Throw(Exception ex) private ExecutionContext CallContractInternal(UInt160 contractHash, string method, CallFlags flags, bool hasReturnValue, StackItem[] args) { - var contract = NativeContract.ContractManagement.GetContract(Snapshot.NotNull(), contractHash); + ContractState? contract = NativeContract.ContractManagement.GetContract(Snapshot, contractHash); if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}"); - var md = contract.Manifest.Abi.GetMethod(method, args.Length); + ContractMethodDescriptor? md = contract.Manifest.Abi.GetMethod(method, args.Length); if (md is null) throw new InvalidOperationException($"Method \"{method}\" with {args.Length} parameter(s) doesn't exist in the contract {contractHash}."); return CallContractInternal(contract, md, flags, hasReturnValue, args); } @@ -320,7 +320,7 @@ protected override void ContextUnloaded(ExecutionContext context) /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock = null, ProtocolSettings? settings = null, long gas = TestModeGas, IDiagnostic? diagnostic = null) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) { return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -383,8 +383,8 @@ public ExecutionContext LoadContract(ContractState contract, ContractMethodDescr public ExecutionContext LoadScript(Script script, int rvcount = -1, int initialPosition = 0, Action? configureState = null) { // Create and configure context - var context = CreateContext(script, rvcount, initialPosition); - var state = context.GetState(); + ExecutionContext context = CreateContext(script, rvcount, initialPosition); + ExecutionContextState state = context.GetState(); state.Snapshot = Snapshot?.CreateSnapshot(); configureState?.Invoke(state); @@ -507,7 +507,7 @@ internal protected void ValidateCallFlags(CallFlags requiredCallFlags) protected override void OnSysCall(uint method) { - OnSysCall(services.NotNull()[method]); + OnSysCall(services[method]); } /// @@ -523,8 +523,8 @@ protected virtual void OnSysCall(InteropDescriptor descriptor) for (int i = 0; i < parameters.Length; i++) parameters[i] = Convert(Pop(), descriptor.Parameters[i]); - object? returnValue = descriptor.Handler.Invoke(this, parameters); - if (returnValue != null && descriptor.Handler.ReturnType != typeof(void)) + object returnValue = descriptor.Handler.Invoke(this, parameters); + if (descriptor.Handler.ReturnType != typeof(void)) Push(Convert(returnValue)); } @@ -592,7 +592,7 @@ private static InteropDescriptor Register(string name, string handler, long fixe /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable? container = null, Block? persistingBlock = null, ProtocolSettings? settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic? diagnostic = null) + public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable container = null, Block persistingBlock = null, ProtocolSettings settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic diagnostic = null) { persistingBlock ??= CreateDummyBlock(snapshot, settings ?? ProtocolSettings.Default); ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, persistingBlock, settings, gas, diagnostic); From cebbec3f0262c56b047877f1c4d799f26bc542fb Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 18:09:42 +0800 Subject: [PATCH 34/36] fix more nullable, 370 warning to go --- src/Neo/Helper.cs | 2 +- .../Ledger/Blockchain.ApplicationExecuted.cs | 2 +- src/Neo/Ledger/Blockchain.cs | 2 +- src/Neo/Persistence/ClonedCache.cs | 1 + .../ApplicationEngine.Contract.cs | 12 +++--- src/Neo/SmartContract/ApplicationEngine.cs | 37 +++++++++++-------- src/Neo/SmartContract/Helper.cs | 8 ++-- src/Neo/SmartContract/JsonSerializer.cs | 9 +++-- src/Neo/SmartContract/Native/AccountState.cs | 2 +- .../SmartContract/Native/InteroperableList.cs | 6 +-- src/Neo/SmartContract/Native/NeoToken.cs | 6 +-- .../SmartContract/Native/OracleContract.cs | 5 ++- .../SmartContract/Native/RoleManagement.cs | 2 +- .../SmartContract/Native/TransactionState.cs | 2 +- src/Neo/SmartContract/Native/TrimmedBlock.cs | 3 +- src/Neo/SmartContract/NotifyEventArgs.cs | 2 +- src/Neo/VM/Helper.cs | 2 +- 17 files changed, 57 insertions(+), 46 deletions(-) diff --git a/src/Neo/Helper.cs b/src/Neo/Helper.cs index 0b6b667313..fb91762e0d 100644 --- a/src/Neo/Helper.cs +++ b/src/Neo/Helper.cs @@ -320,7 +320,7 @@ internal static T NullExceptionOr(this object? obj) where T : class [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T NotNull(this T? obj) where T : class { - return obj.NotNull($"Object {nameof(obj)} is null."); + return obj.NotNull($"Object {nameof(obj)} is null."); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs b/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs index f55596a267..164970ab51 100644 --- a/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs +++ b/src/Neo/Ledger/Blockchain.ApplicationExecuted.cs @@ -40,7 +40,7 @@ partial class ApplicationExecuted /// /// The exception that caused the execution to terminate abnormally. This field could be if the execution ends normally. /// - public Exception Exception { get; } + public Exception? Exception { get; } /// /// GAS spent to execute. diff --git a/src/Neo/Ledger/Blockchain.cs b/src/Neo/Ledger/Blockchain.cs index 1927ae8dd6..0323fd01d3 100644 --- a/src/Neo/Ledger/Blockchain.cs +++ b/src/Neo/Ledger/Blockchain.cs @@ -530,7 +530,7 @@ public BlockchainMailbox(Settings settings, Config config) { } - internal protected override bool IsHighPriority(object message) + protected internal override bool IsHighPriority(object message) { return message switch { diff --git a/src/Neo/Persistence/ClonedCache.cs b/src/Neo/Persistence/ClonedCache.cs index e2629e385d..117270089b 100644 --- a/src/Neo/Persistence/ClonedCache.cs +++ b/src/Neo/Persistence/ClonedCache.cs @@ -11,6 +11,7 @@ using Neo.SmartContract; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Neo.Persistence { diff --git a/src/Neo/SmartContract/ApplicationEngine.Contract.cs b/src/Neo/SmartContract/ApplicationEngine.Contract.cs index 5e45ba4645..ca367cff9f 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Contract.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Contract.cs @@ -93,10 +93,10 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl /// The version of the native contract to be called. protected internal void CallNativeContract(byte version) { - NativeContract contract = NativeContract.GetContract(CurrentScriptHash); + NativeContract? contract = NativeContract.GetContract(CurrentScriptHash.NotNull()); if (contract is null) throw new InvalidOperationException("It is not allowed to use \"System.Contract.CallNative\" directly."); - if (!contract.IsActive(ProtocolSettings, NativeContract.Ledger.CurrentIndex(Snapshot))) + if (!contract.IsActive(ProtocolSettings, NativeContract.Ledger.CurrentIndex(Snapshot.NotNull()))) throw new InvalidOperationException($"The native contract {contract.Name} is not active."); contract.Invoke(this, version); } @@ -108,7 +108,7 @@ protected internal void CallNativeContract(byte version) /// The of the current context. protected internal CallFlags GetCallFlags() { - var state = CurrentContext.GetState(); + var state = CurrentContext.NotNull().GetState(); return state.CallFlags; } @@ -118,7 +118,7 @@ protected internal CallFlags GetCallFlags() /// /// The public key of the account. /// The hash of the account. - internal protected UInt160 CreateStandardAccount(ECPoint pubKey) + protected internal UInt160 CreateStandardAccount(ECPoint pubKey) { long fee = IsHardforkEnabled(Hardfork.HF_Aspidochelone) ? CheckSigPrice @@ -155,7 +155,7 @@ protected internal async void NativeOnPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) + if (contract.IsActive(ProtocolSettings, PersistingBlock.NotNull().Index)) await contract.OnPersist(this); } } @@ -177,7 +177,7 @@ protected internal async void NativePostPersist() throw new InvalidOperationException(); foreach (NativeContract contract in NativeContract.Contracts) { - if (contract.IsActive(ProtocolSettings, PersistingBlock.Index)) + if (contract.IsActive(ProtocolSettings, PersistingBlock.NotNull().Index)) await contract.PostPersist(this); } } diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index 3145372b8c..acf0cb236f 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -19,6 +19,7 @@ using Neo.VM.Types; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Numerics; using System.Reflection; @@ -71,9 +72,10 @@ public partial class ApplicationEngine : ExecutionEngine public static IReadOnlyDictionary Services => services; /// - /// The diagnostic used by the engine. This property can be . + /// The diagnostic used by the engine. + /// This property can be . /// - public IDiagnostic Diagnostic { get; } + public IDiagnostic? Diagnostic { get; } private List Disposables => disposables ??= new List(); @@ -83,7 +85,8 @@ public partial class ApplicationEngine : ExecutionEngine public TriggerType Trigger { get; } /// - /// The container that containing the executed script. This field could be if the contract is invoked by system. + /// The container that containing the executed script. + /// This field could be if the contract is invoked by system. /// public IVerifiable? ScriptContainer { get; } @@ -114,9 +117,10 @@ public partial class ApplicationEngine : ExecutionEngine public long GasLeft => gas_amount - GasConsumed; /// - /// The exception that caused the execution to terminate abnormally. This field could be if no exception is thrown. + /// The exception that caused the execution to terminate abnormally. + /// This field could be if no exception is thrown. /// - public Exception FaultException { get; private set; } + public Exception? FaultException { get; private set; } /// /// The script hash of the current context. This field could be if no context is loaded to the engine. @@ -124,7 +128,8 @@ public partial class ApplicationEngine : ExecutionEngine public UInt160? CurrentScriptHash => CurrentContext?.GetScriptHash(); /// - /// The script hash of the calling contract. This field could be if the current context is the entry context. + /// The script hash of the calling contract. + /// This field could be if the current context is the entry context. /// public UInt160? CallingScriptHash { @@ -137,7 +142,8 @@ public UInt160? CallingScriptHash } /// - /// The script hash of the entry context. This field could be if no context is loaded to the engine. + /// The script hash of the entry context. + /// This field could be if no context is loaded to the engine. /// public UInt160? EntryScriptHash => EntryContext?.GetScriptHash(); @@ -156,7 +162,7 @@ public UInt160? CallingScriptHash /// The used by the engine. /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . - protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block persistingBlock, ProtocolSettings settings, long gas, IDiagnostic diagnostic) + protected unsafe ApplicationEngine(TriggerType trigger, IVerifiable? container, DataCache? snapshot, Block? persistingBlock, ProtocolSettings? settings, long gas, IDiagnostic? diagnostic) { this.Trigger = trigger; this.ScriptContainer = container; @@ -320,7 +326,7 @@ protected override void ContextUnloaded(ExecutionContext context) /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block persistingBlock = null, ProtocolSettings settings = null, long gas = TestModeGas, IDiagnostic diagnostic = null) + public static ApplicationEngine Create(TriggerType trigger, IVerifiable? container, DataCache snapshot, Block? persistingBlock = null, ProtocolSettings? settings = null, long gas = TestModeGas, IDiagnostic? diagnostic = null) { return Provider?.Create(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic) ?? new ApplicationEngine(trigger, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -498,7 +504,7 @@ public override void Dispose() /// Determines whether the of the current context meets the specified requirements. /// /// The requirements to check. - internal protected void ValidateCallFlags(CallFlags requiredCallFlags) + protected internal void ValidateCallFlags(CallFlags requiredCallFlags) { ExecutionContextState state = CurrentContext.NotNull().GetState(); if (!state.CallFlags.HasFlag(requiredCallFlags)) @@ -507,7 +513,7 @@ internal protected void ValidateCallFlags(CallFlags requiredCallFlags) protected override void OnSysCall(uint method) { - OnSysCall(services[method]); + OnSysCall(services![method]); } /// @@ -523,7 +529,7 @@ protected virtual void OnSysCall(InteropDescriptor descriptor) for (int i = 0; i < parameters.Length; i++) parameters[i] = Convert(Pop(), descriptor.Parameters[i]); - object returnValue = descriptor.Handler.Invoke(this, parameters); + object? returnValue = descriptor.Handler.Invoke(this, parameters); if (descriptor.Handler.ReturnType != typeof(void)) Push(Convert(returnValue)); } @@ -566,8 +572,9 @@ private static Block CreateDummyBlock(DataCache snapshot, ProtocolSettings setti private static InteropDescriptor Register(string name, string handler, long fixedPrice, CallFlags requiredCallFlags) { + // this should not be null, otherwise the engine will not work properly MethodInfo method = typeof(ApplicationEngine).GetMethod(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) - ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).GetMethod; + ?? typeof(ApplicationEngine).GetProperty(handler, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)!.GetMethod!; InteropDescriptor descriptor = new() { Name = name, @@ -592,7 +599,7 @@ private static InteropDescriptor Register(string name, string handler, long fixe /// The maximum gas used in this execution. The execution will fail when the gas is exhausted. /// The diagnostic to be used by the . /// The engine instance created. - public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable container = null, Block persistingBlock = null, ProtocolSettings settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic diagnostic = null) + public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snapshot, IVerifiable? container = null, Block? persistingBlock = null, ProtocolSettings? settings = null, int offset = 0, long gas = TestModeGas, IDiagnostic? diagnostic = null) { persistingBlock ??= CreateDummyBlock(snapshot, settings ?? ProtocolSettings.Default); ApplicationEngine engine = Create(TriggerType.Application, container, snapshot, persistingBlock, settings, gas, diagnostic); @@ -608,7 +615,7 @@ public static ApplicationEngine Run(ReadOnlyMemory script, DataCache snaps return (T)state; } - public void SetState(T state) + public void SetState([NotNull] T state) { states ??= new Dictionary(); states[typeof(T)] = state; diff --git a/src/Neo/SmartContract/Helper.cs b/src/Neo/SmartContract/Helper.cs index 5045c74717..64ca80eea9 100644 --- a/src/Neo/SmartContract/Helper.cs +++ b/src/Neo/SmartContract/Helper.cs @@ -142,7 +142,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out /// The minimum number of correct signatures that need to be provided in order for the verification to pass. /// The public keys in the account. /// if the contract is a multi-signature contract; otherwise, . - public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out ECPoint[] points) + public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out ECPoint[]? points) { List list = new(); if (IsMultiSigContract(script, out m, out _, list)) @@ -157,7 +157,7 @@ public static bool IsMultiSigContract(ReadOnlySpan script, out int m, out } } - private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List points) + private static bool IsMultiSigContract(ReadOnlySpan script, out int m, out int n, List? points) { m = 0; n = 0; int i = 0; @@ -320,9 +320,9 @@ internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings { if (witness.VerificationScript.Length == 0) { - ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash); + ContractState? cs = NativeContract.ContractManagement.GetContract(snapshot, hash); if (cs is null) return false; - ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify", -1); + ContractMethodDescriptor? md = cs.Manifest.Abi.GetMethod("verify", -1); if (md?.ReturnType != ContractParameterType.Boolean) return false; engine.LoadContract(cs, md, CallFlags.ReadOnly); } diff --git a/src/Neo/SmartContract/JsonSerializer.cs b/src/Neo/SmartContract/JsonSerializer.cs index 7de12e9fa0..b1d0efa079 100644 --- a/src/Neo/SmartContract/JsonSerializer.cs +++ b/src/Neo/SmartContract/JsonSerializer.cs @@ -36,7 +36,7 @@ public static class JsonSerializer /// /// The to serialize. /// The serialized object. - public static JToken Serialize(StackItem item) + public static JToken? Serialize(StackItem item) { switch (item) { @@ -68,7 +68,8 @@ public static JToken Serialize(StackItem item) { if (!(entry.Key is ByteString)) throw new FormatException(); - var key = entry.Key.GetString(); + // we can not have a null key + var key = entry.Key.GetString().NotNull(); var value = Serialize(entry.Value); ret[key] = value; @@ -165,13 +166,13 @@ public static byte[] SerializeToByteArray(StackItem item, uint maxSize) /// The limits for the deserialization. /// The used by the . /// The deserialized . - public static StackItem Deserialize(ApplicationEngine engine, JToken json, ExecutionEngineLimits limits, ReferenceCounter referenceCounter = null) + public static StackItem Deserialize(ApplicationEngine engine, JToken json, ExecutionEngineLimits limits, ReferenceCounter? referenceCounter = null) { uint maxStackSize = limits.MaxStackSize; return Deserialize(engine, json, ref maxStackSize, referenceCounter); } - private static StackItem Deserialize(ApplicationEngine engine, JToken? json, ref uint maxStackSize, ReferenceCounter referenceCounter) + private static StackItem Deserialize(ApplicationEngine engine, JToken? json, ref uint maxStackSize, ReferenceCounter? referenceCounter) { if (maxStackSize-- == 0) throw new FormatException(); switch (json) diff --git a/src/Neo/SmartContract/Native/AccountState.cs b/src/Neo/SmartContract/Native/AccountState.cs index 031b37f8eb..cc0d0b056a 100644 --- a/src/Neo/SmartContract/Native/AccountState.cs +++ b/src/Neo/SmartContract/Native/AccountState.cs @@ -30,7 +30,7 @@ public virtual void FromStackItem(StackItem stackItem) Balance = ((Struct)stackItem)[0].GetInteger(); } - public virtual StackItem ToStackItem(ReferenceCounter referenceCounter) + public virtual StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { Balance }; } diff --git a/src/Neo/SmartContract/Native/InteroperableList.cs b/src/Neo/SmartContract/Native/InteroperableList.cs index e118db7621..178c6be236 100644 --- a/src/Neo/SmartContract/Native/InteroperableList.cs +++ b/src/Neo/SmartContract/Native/InteroperableList.cs @@ -19,7 +19,7 @@ namespace Neo.SmartContract.Native { abstract class InteroperableList : IList, IInteroperable { - private List list; + private List? list; private List List => list ??= new(); public T this[int index] { get => List[index]; set => List[index] = value; } @@ -40,7 +40,7 @@ abstract class InteroperableList : IList, IInteroperable public void Sort() => List.Sort(); protected abstract T ElementFromStackItem(StackItem item); - protected abstract StackItem ElementToStackItem(T element, ReferenceCounter referenceCounter); + protected abstract StackItem ElementToStackItem(T element, ReferenceCounter? referenceCounter); public void FromStackItem(StackItem stackItem) { @@ -51,7 +51,7 @@ public void FromStackItem(StackItem stackItem) } } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Array(referenceCounter, this.Select(p => ElementToStackItem(p, referenceCounter))); } diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 4d66672461..9e094946e3 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -223,7 +223,7 @@ private void CheckCandidate(DataCache snapshot, ECPoint pubkey, CandidateState c internal override ContractTask Initialize(ApplicationEngine engine) { - if(engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); + if (engine.Snapshot == null) throw new InvalidOperationException("The snapshot is null."); var cachedCommittee = new CachedCommittee(engine.ProtocolSettings.StandbyCommittee.Select(p => (p, BigInteger.Zero))); engine.Snapshot.Add(CreateStorageKey(Prefix_Committee), new StorageItem(cachedCommittee)); engine.Snapshot.Add(CreateStorageKey(Prefix_VotersCount), new StorageItem(System.Array.Empty())); @@ -606,7 +606,7 @@ public override void FromStackItem(StackItem stackItem) LastGasPerVote = @struct[3].GetInteger(); } - public override StackItem ToStackItem(ReferenceCounter referenceCounter) + public override StackItem ToStackItem(ReferenceCounter? referenceCounter) { Struct @struct = (Struct)base.ToStackItem(referenceCounter); @struct.Add(BalanceHeight); @@ -645,7 +645,7 @@ protected override (ECPoint, BigInteger) ElementFromStackItem(StackItem item) return (ECPoint.DecodePoint(@struct[0].GetSpan(), ECCurve.Secp256r1), @struct[1].GetInteger()); } - protected override StackItem ElementToStackItem((ECPoint PublicKey, BigInteger Votes) element, ReferenceCounter referenceCounter) + protected override StackItem ElementToStackItem((ECPoint PublicKey, BigInteger Votes) element, ReferenceCounter? referenceCounter) { return new Struct(referenceCounter) { element.PublicKey.ToArray(), element.Votes }; } diff --git a/src/Neo/SmartContract/Native/OracleContract.cs b/src/Neo/SmartContract/Native/OracleContract.cs index 04729ec148..915df67aa9 100644 --- a/src/Neo/SmartContract/Native/OracleContract.cs +++ b/src/Neo/SmartContract/Native/OracleContract.cs @@ -184,6 +184,7 @@ private static byte[] GetUrlHash(string url) internal override ContractTask Initialize(ApplicationEngine engine) { + if (engine.Snapshot == null) throw new NullReferenceException("engine.Snapshot is null"); engine.Snapshot.Add(CreateStorageKey(Prefix_RequestId), new StorageItem(BigInteger.Zero)); engine.Snapshot.Add(CreateStorageKey(Prefix_Price), new StorageItem(0_50000000)); return ContractTask.CompletedTask; @@ -253,6 +254,8 @@ private async ContractTask Request(ApplicationEngine engine, string url, string? item_id.Add(1); //Put the request to storage + // CallingScriptHash can not be null, otherwise it throw exception anyway. + if (engine.CallingScriptHash == null) throw new NullReferenceException("engine.CallingScriptHash is null"); if (ContractManagement.GetContract(engine.Snapshot, engine.CallingScriptHash) is null) throw new InvalidOperationException("The calling contract is not deployed"); engine.Snapshot.Add(CreateStorageKey(Prefix_Request).AddBigEndian(id), new StorageItem(new OracleRequest @@ -292,7 +295,7 @@ protected override ulong ElementFromStackItem(StackItem item) return (ulong)item.GetInteger(); } - protected override StackItem ElementToStackItem(ulong element, ReferenceCounter referenceCounter) + protected override StackItem ElementToStackItem(ulong element, ReferenceCounter? referenceCounter) { return element; } diff --git a/src/Neo/SmartContract/Native/RoleManagement.cs b/src/Neo/SmartContract/Native/RoleManagement.cs index 1c2fa0a299..ead9224400 100644 --- a/src/Neo/SmartContract/Native/RoleManagement.cs +++ b/src/Neo/SmartContract/Native/RoleManagement.cs @@ -102,7 +102,7 @@ protected override ECPoint ElementFromStackItem(StackItem item) return ECPoint.DecodePoint(item.GetSpan(), ECCurve.Secp256r1); } - protected override StackItem ElementToStackItem(ECPoint element, ReferenceCounter referenceCounter) + protected override StackItem ElementToStackItem(ECPoint element, ReferenceCounter? referenceCounter) { return element.ToArray(); } diff --git a/src/Neo/SmartContract/Native/TransactionState.cs b/src/Neo/SmartContract/Native/TransactionState.cs index 4facb8d1f4..7d2f24b8aa 100644 --- a/src/Neo/SmartContract/Native/TransactionState.cs +++ b/src/Neo/SmartContract/Native/TransactionState.cs @@ -74,7 +74,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) State = (VMState)(byte)@struct[2].GetInteger(); } - StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) { if (Transaction is null) return new Struct(referenceCounter) { BlockIndex }; diff --git a/src/Neo/SmartContract/Native/TrimmedBlock.cs b/src/Neo/SmartContract/Native/TrimmedBlock.cs index 4cc4c39c0f..5c5b2c2a9a 100644 --- a/src/Neo/SmartContract/Native/TrimmedBlock.cs +++ b/src/Neo/SmartContract/Native/TrimmedBlock.cs @@ -15,7 +15,6 @@ using Neo.VM.Types; using System; using System.IO; -using System.Linq; namespace Neo.SmartContract.Native { @@ -79,7 +78,7 @@ void IInteroperable.FromStackItem(StackItem stackItem) throw new NotSupportedException(); } - StackItem IInteroperable.ToStackItem(ReferenceCounter referenceCounter) + StackItem IInteroperable.ToStackItem(ReferenceCounter? referenceCounter) { return new VM.Types.Array(referenceCounter, new StackItem[] { diff --git a/src/Neo/SmartContract/NotifyEventArgs.cs b/src/Neo/SmartContract/NotifyEventArgs.cs index 0a509101c1..e4860113b7 100644 --- a/src/Neo/SmartContract/NotifyEventArgs.cs +++ b/src/Neo/SmartContract/NotifyEventArgs.cs @@ -63,7 +63,7 @@ public void FromStackItem(StackItem stackItem) throw new NotSupportedException(); } - public StackItem ToStackItem(ReferenceCounter referenceCounter) + public StackItem ToStackItem(ReferenceCounter? referenceCounter) { return new Array(referenceCounter) { diff --git a/src/Neo/VM/Helper.cs b/src/Neo/VM/Helper.cs index e303ba1e53..3b3e86c695 100644 --- a/src/Neo/VM/Helper.cs +++ b/src/Neo/VM/Helper.cs @@ -36,7 +36,7 @@ public static class Helper /// The to be used. /// The elements of the array. /// The same instance as . - public static ScriptBuilder CreateArray(this ScriptBuilder builder, IReadOnlyList list = null) + public static ScriptBuilder CreateArray(this ScriptBuilder builder, IReadOnlyList? list = null) { if (list is null || list.Count == 0) return builder.Emit(OpCode.NEWARRAY0); From e975e21cda2c146659062634c23e83691f87c93e Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 18:38:21 +0800 Subject: [PATCH 35/36] 290 warning to go. --- src/Neo/ProtocolSettings.cs | 4 ++-- .../SmartContract/ApplicationEngine.Crypto.cs | 4 ++-- .../ApplicationEngine.Runtime.cs | 5 +++-- src/Neo/SmartContract/ApplicationEngine.cs | 10 +++++----- .../ContractParametersContext.cs | 17 +++++++++-------- src/Neo/SmartContract/Native/NeoToken.cs | 4 ++-- src/Neo/SmartContract/Native/OracleRequest.cs | 10 +++++++--- .../SmartContract/Native/PolicyContract.cs | 19 ++++++++++++++----- src/Neo/Wallets/Wallet.cs | 7 +++++-- 9 files changed, 49 insertions(+), 31 deletions(-) diff --git a/src/Neo/ProtocolSettings.cs b/src/Neo/ProtocolSettings.cs index defbab9994..02fc60be60 100644 --- a/src/Neo/ProtocolSettings.cs +++ b/src/Neo/ProtocolSettings.cs @@ -94,7 +94,7 @@ public record ProtocolSettings /// public ulong InitialGasDistribution { get; init; } - private IReadOnlyList _standbyValidators; + private IReadOnlyList? _standbyValidators; /// /// The public keys of the standby validators. /// @@ -151,7 +151,7 @@ public static ProtocolSettings Load(IConfigurationSection section) : Default.StandbyCommittee, ValidatorsCount = section.GetValue("ValidatorsCount", Default.ValidatorsCount), SeedList = section.GetSection("SeedList").Exists() - ? section.GetSection("SeedList").GetChildren().Select(p => p.Get()).ToArray() + ? section.GetSection("SeedList").GetChildren().Select(p => p.Get()!).ToArray() : Default.SeedList, MillisecondsPerBlock = section.GetValue("MillisecondsPerBlock", Default.MillisecondsPerBlock), MaxTransactionsPerBlock = section.GetValue("MaxTransactionsPerBlock", Default.MaxTransactionsPerBlock), diff --git a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs index 1a8b2c7d6d..0fdcde2698 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Crypto.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Crypto.cs @@ -46,7 +46,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) { try { - return Crypto.VerifySignature(ScriptContainer.GetSignData(ProtocolSettings.Network), signature, pubkey, ECCurve.Secp256r1); + return Crypto.VerifySignature(ScriptContainer.NotNull().GetSignData(ProtocolSettings.Network), signature, pubkey, ECCurve.Secp256r1); } catch (ArgumentException) { @@ -63,7 +63,7 @@ protected internal bool CheckSig(byte[] pubkey, byte[] signature) /// if the signatures are valid; otherwise, . protected internal bool CheckMultisig(byte[][] pubkeys, byte[][] signatures) { - byte[] message = ScriptContainer.GetSignData(ProtocolSettings.Network); + byte[] message = ScriptContainer.NotNull().GetSignData(ProtocolSettings.Network); int m = signatures.Length, n = pubkeys.Length; if (n == 0 || m == 0 || m > n) throw new ArgumentException(); AddGas(CheckSigPrice * n * ExecFeeFactor); diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index a9a84bd7a0..44c560d6f1 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -377,6 +377,7 @@ protected internal void RuntimeNotify(byte[] eventName, Array state) protected internal void RuntimeNotifyV1(byte[] eventName, Array state) { if (eventName.Length > MaxEventName) throw new ArgumentException(null, nameof(eventName)); + if (CurrentContext == null) throw new NullReferenceException("CurrentContext is null."); if (CurrentContext.GetState().Contract is null) throw new InvalidOperationException("Notifications are not allowed in dynamic scripts."); using MemoryStream ms = new(MaxNotificationSize); @@ -395,8 +396,8 @@ protected internal void SendNotification(UInt160 hash, string eventName, Array s { NotifyEventArgs notification = new(ScriptContainer, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); Notify?.Invoke(this, notification); - notifications ??= new List(); - notifications.Add(notification); + _notifications ??= new List(); + _notifications.Add(notification); CurrentContext.GetState().NotificationCount++; } diff --git a/src/Neo/SmartContract/ApplicationEngine.cs b/src/Neo/SmartContract/ApplicationEngine.cs index acf0cb236f..27a325c793 100644 --- a/src/Neo/SmartContract/ApplicationEngine.cs +++ b/src/Neo/SmartContract/ApplicationEngine.cs @@ -53,7 +53,7 @@ public partial class ApplicationEngine : ExecutionEngine private readonly long gas_amount; private Dictionary? states; private readonly DataCache? originalSnapshot; - private List? notifications; + private List? _notifications; private List? disposables; private readonly Dictionary invocationCounter = new(); private readonly Dictionary contractTasks = new(); @@ -150,7 +150,7 @@ public UInt160? CallingScriptHash /// /// The notifications sent during the execution. /// - public IReadOnlyList Notifications => notifications ?? (IReadOnlyList)Array.Empty(); + public IReadOnlyList Notifications => _notifications ?? (IReadOnlyList)Array.Empty(); /// /// Initializes a new instance of the class. @@ -198,7 +198,7 @@ protected internal void AddGas(long gas) protected override void OnFault(Exception ex) { FaultException = ex; - notifications = null; + _notifications = null; base.OnFault(ex); } @@ -302,8 +302,8 @@ protected override void ContextUnloaded(ExecutionContext context) } else { - if (notifications != null && state.NotificationCount > 0) - notifications.RemoveRange(notifications.Count - state.NotificationCount, state.NotificationCount); + if (_notifications != null && state.NotificationCount > 0) + _notifications.RemoveRange(_notifications.Count - state.NotificationCount, state.NotificationCount); } } Diagnostic?.ContextUnloaded(context); diff --git a/src/Neo/SmartContract/ContractParametersContext.cs b/src/Neo/SmartContract/ContractParametersContext.cs index c8e606c671..41f0645fa3 100644 --- a/src/Neo/SmartContract/ContractParametersContext.cs +++ b/src/Neo/SmartContract/ContractParametersContext.cs @@ -31,7 +31,7 @@ public class ContractParametersContext { private class ContextItem { - public readonly byte[] Script; + public readonly byte[]? Script; public readonly ContractParameter[] Parameters; public readonly Dictionary Signatures; @@ -44,12 +44,12 @@ public ContextItem(Contract contract) public ContextItem(JObject json) { - this.Script = Convert.FromBase64String(json["script"].AsString()); + this.Script = Convert.FromBase64String(json["script"].NotNull().AsString()); this.Parameters = ((JArray)json["parameters"]).Select(p => ContractParameter.FromJson((JObject)p)).ToArray(); this.Signatures = ((JObject)json["signatures"]).Properties.Select(p => new { PublicKey = ECPoint.Parse(p.Key, ECCurve.Secp256r1), - Signature = Convert.FromBase64String(p.Value.AsString()) + Signature = Convert.FromBase64String(p.Value.NotNull().AsString()) }).ToDictionary(p => p.PublicKey, p => p.Signature); } @@ -60,7 +60,7 @@ public JObject ToJson() json["parameters"] = new JArray(Parameters.Select(p => p.ToJson())); json["signatures"] = new JObject(); foreach (var signature in Signatures) - json["signatures"][signature.Key.ToString()] = Convert.ToBase64String(signature.Value); + json["signatures"]![signature.Key.ToString()] = Convert.ToBase64String(signature.Value); return json; } } @@ -156,9 +156,9 @@ public bool Add(Contract contract, params object[] parameters) /// if the signature is added successfully; otherwise, . public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) { - if (IsMultiSigContract(contract.Script, out _, out ECPoint[] points)) + if (IsMultiSigContract(contract.Script, out _, out ECPoint[]? points)) { - if (!points.Contains(pubkey)) return false; + if (points == null || !points.Contains(pubkey)) return false; ContextItem? item = CreateItem(contract); if (item == null) return false; if (item.Parameters.All(p => p.Value != null)) return false; @@ -226,7 +226,7 @@ public bool AddSignature(Contract contract, ECPoint pubkey, byte[] signature) /// The converted context. public static ContractParametersContext FromJson(JObject json, DataCache snapshot) { - var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"].AsString()); + var type = typeof(ContractParametersContext).GetTypeInfo().Assembly.GetType(json["type"].NotNull().AsString()); if (!typeof(IVerifiable).IsAssignableFrom(type)) throw new FormatException(); var verifiable = (IVerifiable?)Activator.CreateInstance(type); @@ -327,7 +327,8 @@ public Witness[] GetWitnesses() /// The parsed context. public static ContractParametersContext Parse(string value, DataCache snapshot) { - return FromJson((JObject)JToken.Parse(value), snapshot); + // when we use this fromJson, we use it as Parse always success. + return FromJson((JObject)JToken.Parse(value).NotNull(), snapshot); } /// diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs index 9e094946e3..2e1488acf7 100644 --- a/src/Neo/SmartContract/Native/NeoToken.cs +++ b/src/Neo/SmartContract/Native/NeoToken.cs @@ -239,8 +239,8 @@ internal override ContractTask OnPersist(ApplicationEngine engine) { StorageItem? storageItem = engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_Committee)); var cachedCommittee = storageItem?.GetInteroperable(); - cachedCommittee.Clear(); - cachedCommittee.AddRange(ComputeCommitteeMembers(engine.Snapshot, engine.ProtocolSettings)); + cachedCommittee?.Clear(); + cachedCommittee?.AddRange(ComputeCommitteeMembers(engine.Snapshot, engine.ProtocolSettings)); } return ContractTask.CompletedTask; } diff --git a/src/Neo/SmartContract/Native/OracleRequest.cs b/src/Neo/SmartContract/Native/OracleRequest.cs index a3a14fe0a7..50ace64d87 100644 --- a/src/Neo/SmartContract/Native/OracleRequest.cs +++ b/src/Neo/SmartContract/Native/OracleRequest.cs @@ -38,8 +38,9 @@ public class OracleRequest : IInteroperable /// /// The filter for the response. + /// Can be null. /// - public string Filter; + public string? Filter; /// /// The hash of the callback contract. @@ -61,10 +62,13 @@ public void FromStackItem(StackItem stackItem) Array array = (Array)stackItem; OriginalTxid = new UInt256(array[0].GetSpan()); GasForResponse = (long)array[1].GetInteger(); - Url = array[2].GetString(); + // must contain a valid Url + Url = array[2].NotNull().GetString().NotNull(); + // Filter can be null based on ToStackItem Filter = array[3].GetString(); CallbackContract = new UInt160(array[4].GetSpan()); - CallbackMethod = array[5].GetString(); + // must contain a valid callback method + CallbackMethod = array[5].NotNull().GetString().NotNull(); UserData = array[6].GetSpan().ToArray(); } diff --git a/src/Neo/SmartContract/Native/PolicyContract.cs b/src/Neo/SmartContract/Native/PolicyContract.cs index c633cb7309..f4d82df739 100644 --- a/src/Neo/SmartContract/Native/PolicyContract.cs +++ b/src/Neo/SmartContract/Native/PolicyContract.cs @@ -70,6 +70,7 @@ internal PolicyContract() internal override ContractTask Initialize(ApplicationEngine engine) { + if (engine.Snapshot == null) throw new NullReferenceException("Snapshot is null"); engine.Snapshot.Add(CreateStorageKey(Prefix_FeePerByte), new StorageItem(DefaultFeePerByte)); engine.Snapshot.Add(CreateStorageKey(Prefix_ExecFeeFactor), new StorageItem(DefaultExecFeeFactor)); engine.Snapshot.Add(CreateStorageKey(Prefix_StoragePrice), new StorageItem(DefaultStoragePrice)); @@ -119,7 +120,7 @@ public uint GetStoragePrice(DataCache snapshot) public uint GetAttributeFee(DataCache snapshot, byte attributeType) { if (!Enum.IsDefined(typeof(TransactionAttributeType), attributeType)) throw new InvalidOperationException(); - StorageItem entry = snapshot.TryGet(CreateStorageKey(Prefix_AttributeFee).Add(attributeType)); + StorageItem? entry = snapshot.TryGet(CreateStorageKey(Prefix_AttributeFee).Add(attributeType)); if (entry == null) return DefaultAttributeFee; return (uint)(BigInteger)entry; @@ -144,7 +145,7 @@ private void SetAttributeFee(ApplicationEngine engine, byte attributeType, uint if (value > MaxAttributeFee) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_AttributeFee).Add(attributeType), () => new StorageItem(DefaultAttributeFee)).Set(value); + engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_AttributeFee).Add(attributeType), () => new StorageItem(DefaultAttributeFee))?.Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -152,7 +153,7 @@ private void SetFeePerByte(ApplicationEngine engine, long value) { if (value < 0 || value > 1_00000000) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_FeePerByte)).Set(value); + engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_FeePerByte))?.Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -160,7 +161,7 @@ private void SetExecFeeFactor(ApplicationEngine engine, uint value) { if (value == 0 || value > MaxExecFeeFactor) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_ExecFeeFactor)).Set(value); + engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_ExecFeeFactor))?.Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] @@ -168,12 +169,13 @@ private void SetStoragePrice(ApplicationEngine engine, uint value) { if (value == 0 || value > MaxStoragePrice) throw new ArgumentOutOfRangeException(nameof(value)); if (!CheckCommittee(engine)) throw new InvalidOperationException(); - engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_StoragePrice)).Set(value); + engine.Snapshot?.GetAndChange(CreateStorageKey(Prefix_StoragePrice))?.Set(value); } [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States)] private bool BlockAccount(ApplicationEngine engine, UInt160 account) { + if (engine.Snapshot == null) throw new NullReferenceException("Snapshot is null"); if (!CheckCommittee(engine)) throw new InvalidOperationException(); return BlockAccount(engine.Snapshot, account); } @@ -194,6 +196,13 @@ private bool UnblockAccount(ApplicationEngine engine, UInt160 account) { if (!CheckCommittee(engine)) throw new InvalidOperationException(); +/* Unmerged change from project 'Neo(net7.0)' +Before: + if(engine.Snapshot == null) throw new NullReferenceException("Snapshot is null"); +After: + if (engine.Snapshot == null) throw new NullReferenceException("Snapshot is null"); +*/ + if (engine.Snapshot == null) throw new NullReferenceException("Snapshot is null"); var key = CreateStorageKey(Prefix_BlockedAccount).Add(account); if (!engine.Snapshot.Contains(key)) return false; diff --git a/src/Neo/Wallets/Wallet.cs b/src/Neo/Wallets/Wallet.cs index 5aa6bcd897..c506fd53c4 100644 --- a/src/Neo/Wallets/Wallet.cs +++ b/src/Neo/Wallets/Wallet.cs @@ -693,9 +693,12 @@ public bool Sign(ContractParametersContext context) Contract? multiSigContract = account.Contract; if (multiSigContract != null && - IsMultiSigContract(multiSigContract.Script, out int m, out ECPoint[] points)) + IsMultiSigContract(multiSigContract.Script, out int m, out ECPoint[]? points)) { - foreach (var point in points) + // though this can be null, not sure what the behavior should be + // TODO: Check the original behavior, + // TODO: if it should be null, then we should throw an exception + foreach (var point in points ?? Array.Empty()) { account = GetAccount(point); if (account == null || account.HasKey != true) continue; From a75b502f39ff4332a225ed1473ec3dc3f779be52 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Fri, 9 Feb 2024 18:49:49 +0800 Subject: [PATCH 36/36] format --- src/Neo/SmartContract/Native/PolicyContract.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Neo/SmartContract/Native/PolicyContract.cs b/src/Neo/SmartContract/Native/PolicyContract.cs index f4d82df739..9ed491dd40 100644 --- a/src/Neo/SmartContract/Native/PolicyContract.cs +++ b/src/Neo/SmartContract/Native/PolicyContract.cs @@ -196,12 +196,6 @@ private bool UnblockAccount(ApplicationEngine engine, UInt160 account) { if (!CheckCommittee(engine)) throw new InvalidOperationException(); -/* Unmerged change from project 'Neo(net7.0)' -Before: - if(engine.Snapshot == null) throw new NullReferenceException("Snapshot is null"); -After: - if (engine.Snapshot == null) throw new NullReferenceException("Snapshot is null"); -*/ if (engine.Snapshot == null) throw new NullReferenceException("Snapshot is null"); var key = CreateStorageKey(Prefix_BlockedAccount).Add(account); if (!engine.Snapshot.Contains(key)) return false;