From db93c4306f8e8aee2f1b346e49259863ca48aad0 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 4 Jun 2025 00:02:31 +0200 Subject: [PATCH 1/2] Style MPT --- .../Cryptography/MPTTrie/Cache.cs | 38 +++++----- .../Cryptography/MPTTrie/Node.Branch.cs | 10 +-- .../Cryptography/MPTTrie/Node.Hash.cs | 2 +- .../Cryptography/MPTTrie/Node.Leaf.cs | 2 +- .../Cryptography/MPTTrie/Node.cs | 70 +++++++------------ .../Cryptography/MPTTrie/Trie.Delete.cs | 10 +-- .../Cryptography/MPTTrie/Trie.Find.cs | 28 ++++---- .../Cryptography/MPTTrie/Trie.Get.cs | 4 +- .../Cryptography/MPTTrie/Trie.Proof.cs | 8 +-- .../Cryptography/MPTTrie/Trie.Put.cs | 8 +-- .../Cryptography/MPTTrie/Trie.cs | 3 +- .../GlobalSuppressions.cs | 8 +++ 12 files changed, 90 insertions(+), 101 deletions(-) create mode 100644 src/Neo.Cryptography.MPTTrie/GlobalSuppressions.cs diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Cache.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Cache.cs index bef1a68034..0e705f1ee8 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Cache.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Cache.cs @@ -32,23 +32,23 @@ private class Trackable public TrackState State; } - private readonly IStoreSnapshot store; - private readonly byte prefix; - private readonly Dictionary cache = new Dictionary(); + private readonly IStoreSnapshot _store; + private readonly byte _prefix; + private readonly Dictionary _cache = []; public Cache(IStoreSnapshot store, byte prefix) { - this.store = store; - this.prefix = prefix; + _store = store; + _prefix = prefix; } private byte[] Key(UInt256 hash) { byte[] buffer = new byte[UInt256.Length + 1]; - using (MemoryStream ms = new MemoryStream(buffer, true)) - using (BinaryWriter writer = new BinaryWriter(ms)) + using (var ms = new MemoryStream(buffer, true)) + using (var writer = new BinaryWriter(ms)) { - writer.Write(prefix); + writer.Write(_prefix); hash.Serialize(writer); } return buffer; @@ -56,13 +56,13 @@ private byte[] Key(UInt256 hash) public Node Resolve(UInt256 hash) { - if (cache.TryGetValue(hash, out Trackable t)) + if (_cache.TryGetValue(hash, out var t)) { return t.Node?.Clone(); } - var n = store.TryGet(Key(hash), out var data) ? data.AsSerializable() : null; - cache.Add(hash, new Trackable + var n = _store.TryGet(Key(hash), out var data) ? data.AsSerializable() : null; + _cache.Add(hash, new Trackable { Node = n, State = TrackState.None, @@ -76,14 +76,14 @@ public void PutNode(Node np) if (n is null) { np.Reference = 1; - cache[np.Hash] = new Trackable + _cache[np.Hash] = new Trackable { Node = np.Clone(), State = TrackState.Added, }; return; } - var entry = cache[np.Hash]; + var entry = _cache[np.Hash]; entry.Node.Reference++; entry.State = TrackState.Changed; } @@ -94,12 +94,12 @@ public void DeleteNode(UInt256 hash) if (n is null) return; if (1 < n.Reference) { - var entry = cache[hash]; + var entry = _cache[hash]; entry.Node.Reference--; entry.State = TrackState.Changed; return; } - cache[hash] = new Trackable + _cache[hash] = new Trackable { Node = null, State = TrackState.Deleted, @@ -108,20 +108,20 @@ public void DeleteNode(UInt256 hash) public void Commit() { - foreach (var item in cache) + foreach (var item in _cache) { switch (item.Value.State) { case TrackState.Added: case TrackState.Changed: - store.Put(Key(item.Key), item.Value.Node.ToArray()); + _store.Put(Key(item.Key), item.Value.Node.ToArray()); break; case TrackState.Deleted: - store.Delete(Key(item.Key)); + _store.Delete(Key(item.Key)); break; } } - cache.Clear(); + _cache.Clear(); } } } diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Branch.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Branch.cs index afc9bee04d..086e50dcb2 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Branch.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Branch.cs @@ -27,7 +27,7 @@ public static Node NewBranch() Reference = 1, Children = new Node[BranchChildCount], }; - for (int i = 0; i < BranchChildCount; i++) + for (var i = 0; i < BranchChildCount; i++) { n.Children[i] = new Node(); } @@ -38,8 +38,8 @@ protected int BranchSize { get { - int size = 0; - for (int i = 0; i < BranchChildCount; i++) + var size = 0; + for (var i = 0; i < BranchChildCount; i++) { size += Children[i].SizeAsChild; } @@ -49,7 +49,7 @@ protected int BranchSize private void SerializeBranch(BinaryWriter writer) { - for (int i = 0; i < BranchChildCount; i++) + for (var i = 0; i < BranchChildCount; i++) { Children[i].SerializeAsChild(writer); } @@ -58,7 +58,7 @@ private void SerializeBranch(BinaryWriter writer) private void DeserializeBranch(ref MemoryReader reader) { Children = new Node[BranchChildCount]; - for (int i = 0; i < BranchChildCount; i++) + for (var i = 0; i < BranchChildCount; i++) { var n = new Node(); n.Deserialize(ref reader); diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Hash.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Hash.cs index 25a310bebc..8dd8d7aa42 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Hash.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Hash.cs @@ -20,7 +20,7 @@ partial class Node { public static Node NewHash(UInt256 hash) { - if (hash is null) throw new ArgumentNullException(nameof(NewHash)); + ArgumentNullException.ThrowIfNull(hash); var n = new Node { type = NodeType.HashNode, diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Leaf.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Leaf.cs index b79c91f72d..98edd79d07 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Leaf.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.Leaf.cs @@ -24,7 +24,7 @@ partial class Node public static Node NewLeaf(byte[] value) { - if (value is null) throw new ArgumentNullException(nameof(value)); + ArgumentNullException.ThrowIfNull(value); var n = new Node { type = NodeType.LeafNode, diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.cs index dc8f4a2c43..4db6f5e969 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Node.cs @@ -28,22 +28,16 @@ public int Size { get { - int size = sizeof(NodeType); - switch (type) + var size = sizeof(NodeType); + return type switch { - case NodeType.BranchNode: - return size + BranchSize + Reference.GetVarSize(); - case NodeType.ExtensionNode: - return size + ExtensionSize + Reference.GetVarSize(); - case NodeType.LeafNode: - return size + LeafSize + Reference.GetVarSize(); - case NodeType.HashNode: - return size + HashSize; - case NodeType.Empty: - return size; - default: - throw new InvalidOperationException($"{nameof(Node)} Cannt get size, unsupport type"); - } + NodeType.BranchNode => size + BranchSize + Reference.GetVarSize(), + NodeType.ExtensionNode => size + ExtensionSize + Reference.GetVarSize(), + NodeType.LeafNode => size + LeafSize + Reference.GetVarSize(), + NodeType.HashNode => size + HashSize, + NodeType.Empty => size, + _ => throw new InvalidOperationException($"{nameof(Node)} Cannt get size, unsupport type"), + }; } } @@ -61,18 +55,12 @@ public int SizeAsChild { get { - switch (type) + return type switch { - case NodeType.BranchNode: - case NodeType.ExtensionNode: - case NodeType.LeafNode: - return NewHash(Hash).Size; - case NodeType.HashNode: - case NodeType.Empty: - return Size; - default: - throw new InvalidOperationException(nameof(Node)); - } + NodeType.BranchNode or NodeType.ExtensionNode or NodeType.LeafNode => NewHash(Hash).Size, + NodeType.HashNode or NodeType.Empty => Size, + _ => throw new InvalidOperationException(nameof(Node)), + }; } } @@ -128,8 +116,8 @@ public void Serialize(BinaryWriter writer) public byte[] ToArrayWithoutReference() { - using MemoryStream ms = new MemoryStream(); - using BinaryWriter writer = new BinaryWriter(ms, Utility.StrictUTF8, true); + using var ms = new MemoryStream(); + using var writer = new BinaryWriter(ms, Utility.StrictUTF8, true); SerializeWithoutReference(writer); writer.Flush(); @@ -165,22 +153,16 @@ public void Deserialize(ref MemoryReader reader) private Node CloneAsChild() { - switch (type) + return type switch { - case NodeType.BranchNode: - case NodeType.ExtensionNode: - case NodeType.LeafNode: - return new Node - { - type = NodeType.HashNode, - hash = Hash, - }; - case NodeType.HashNode: - case NodeType.Empty: - return Clone(); - default: - throw new InvalidOperationException(nameof(Clone)); - } + NodeType.BranchNode or NodeType.ExtensionNode or NodeType.LeafNode => new Node + { + type = NodeType.HashNode, + hash = Hash, + }, + NodeType.HashNode or NodeType.Empty => Clone(), + _ => throw new InvalidOperationException(nameof(Clone)), + }; } public Node Clone() @@ -194,7 +176,7 @@ public Node Clone() Reference = Reference, Children = new Node[BranchChildCount], }; - for (int i = 0; i < BranchChildCount; i++) + for (var i = 0; i < BranchChildCount; i++) { n.Children[i] = Children[i].CloneAsChild(); } diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Delete.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Delete.cs index 15f06ed8fa..46a8860eba 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Delete.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Delete.cs @@ -79,8 +79,8 @@ private bool TryDelete(ref Node node, ReadOnlySpan path) } if (!result) return false; if (!_full) _cache.DeleteNode(oldHash); - List childrenIndexes = new List(Node.BranchChildCount); - for (int i = 0; i < Node.BranchChildCount; i++) + var childrenIndexes = new List(Node.BranchChildCount); + for (var i = 0; i < Node.BranchChildCount; i++) { if (node.Children[i].IsEmpty) continue; childrenIndexes.Add((byte)i); @@ -112,7 +112,7 @@ private bool TryDelete(ref Node node, ReadOnlySpan path) node = lastChild; return true; } - node = Node.NewExtension(childrenIndexes.ToArray(), lastChild); + node = Node.NewExtension([.. childrenIndexes], lastChild); _cache.PutNode(node); return true; } @@ -122,8 +122,8 @@ private bool TryDelete(ref Node node, ReadOnlySpan path) } case NodeType.HashNode: { - var newNode = _cache.Resolve(node.Hash); - if (newNode is null) throw new InvalidOperationException("Internal error, can't resolve hash when mpt delete"); + var newNode = _cache.Resolve(node.Hash) + ?? throw new InvalidOperationException("Internal error, can't resolve hash when mpt delete"); node = newNode; return TryDelete(ref node, path); } diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Find.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Find.cs index 4becbd2496..17ef61807a 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Find.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Find.cs @@ -26,7 +26,7 @@ private ReadOnlySpan Seek(ref Node node, ReadOnlySpan path, out Node if (path.IsEmpty) { start = node; - return ReadOnlySpan.Empty; + return []; } break; } @@ -34,8 +34,8 @@ private ReadOnlySpan Seek(ref Node node, ReadOnlySpan path, out Node break; case NodeType.HashNode: { - var newNode = _cache.Resolve(node.Hash); - if (newNode is null) throw new InvalidOperationException("Internal error, can't resolve hash when mpt seek"); + var newNode = _cache.Resolve(node.Hash) + ?? throw new InvalidOperationException("Internal error, can't resolve hash when mpt seek"); node = newNode; return Seek(ref node, path, out start); } @@ -44,7 +44,7 @@ private ReadOnlySpan Seek(ref Node node, ReadOnlySpan path, out Node if (path.IsEmpty) { start = node; - return ReadOnlySpan.Empty; + return []; } return new([.. path[..1], .. Seek(ref node.Children[path[0]], path[1..], out start)]); } @@ -68,14 +68,14 @@ private ReadOnlySpan Seek(ref Node node, ReadOnlySpan path, out Node } } start = null; - return ReadOnlySpan.Empty; + return []; } public IEnumerable<(ReadOnlyMemory Key, ReadOnlyMemory Value)> Find(ReadOnlySpan prefix, byte[] from = null) { var path = ToNibbles(prefix); - int offset = 0; - if (from is null) from = Array.Empty(); + var offset = 0; + from ??= []; if (0 < from.Length) { if (!from.AsSpan().StartsWith(prefix)) @@ -84,12 +84,12 @@ private ReadOnlySpan Seek(ref Node node, ReadOnlySpan path, out Node } if (path.Length > Node.MaxKeyLength || from.Length > Node.MaxKeyLength) throw new ArgumentException("exceeds limit"); - path = Seek(ref _root, path, out Node start).ToArray(); + path = Seek(ref _root, path, out var start).ToArray(); if (from.Length > 0) { - for (int i = 0; i < from.Length && i < path.Length; i++) + for (var i = 0; i < from.Length && i < path.Length; i++) { - if (path[i] < from[i]) return Enumerable.Empty<(ReadOnlyMemory, ReadOnlyMemory)>(); + if (path[i] < from[i]) return []; if (path[i] > from[i]) { offset = from.Length; @@ -120,8 +120,8 @@ private ReadOnlySpan Seek(ref Node node, ReadOnlySpan path, out Node break; case NodeType.HashNode: { - var newNode = _cache.Resolve(node.Hash); - if (newNode is null) throw new InvalidOperationException("Internal error, can't resolve hash when mpt find"); + var newNode = _cache.Resolve(node.Hash) + ?? throw new InvalidOperationException("Internal error, can't resolve hash when mpt find"); node = newNode; foreach (var item in Travers(node, path, from, offset)) yield return item; @@ -131,7 +131,7 @@ private ReadOnlySpan Seek(ref Node node, ReadOnlySpan path, out Node { if (offset < from.Length) { - for (int i = 0; i < Node.BranchChildCount - 1; i++) + for (var i = 0; i < Node.BranchChildCount - 1; i++) { if (from[offset] < i) { @@ -149,7 +149,7 @@ private ReadOnlySpan Seek(ref Node node, ReadOnlySpan path, out Node { foreach (var item in Travers(node.Children[Node.BranchChildCount - 1], path, from, offset)) yield return item; - for (int i = 0; i < Node.BranchChildCount - 1; i++) + for (var i = 0; i < Node.BranchChildCount - 1; i++) { foreach (var item in Travers(node.Children[i], [.. path, .. new byte[] { (byte)i }], from, offset)) yield return item; diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Get.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Get.cs index 3193637087..e23a66c224 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Get.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Get.cs @@ -61,8 +61,8 @@ private bool TryGet(ref Node node, ReadOnlySpan path, out ReadOnlySpan path, HashSet se break; case NodeType.HashNode: { - var newNode = _cache.Resolve(node.Hash); - if (newNode is null) throw new InvalidOperationException("Internal error, can't resolve hash when mpt getproof"); + var newNode = _cache.Resolve(node.Hash) + ?? throw new InvalidOperationException("Internal error, can't resolve hash when mpt getproof"); node = newNode; return GetProof(ref node, path, set); } @@ -75,7 +75,7 @@ private bool GetProof(ref Node node, ReadOnlySpan path, HashSet se private static byte[] Key(byte[] hash) { - byte[] buffer = new byte[hash.Length + 1]; + var buffer = new byte[hash.Length + 1]; buffer[0] = Prefix; Buffer.BlockCopy(hash, 0, buffer, 1, hash.Length); return buffer; @@ -84,7 +84,7 @@ private static byte[] Key(byte[] hash) public static byte[] VerifyProof(UInt256 root, byte[] key, HashSet proof) { using var memoryStore = new MemoryStore(); - foreach (byte[] data in proof) + foreach (var data in proof) memoryStore.Put(Key(Crypto.Hash256(data)), [.. data, .. new byte[] { 1 }]); using var snapshot = memoryStore.GetSnapshot(); var trie = new Trie(snapshot, root, false); diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Put.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Put.cs index 409bbf2d15..475e2804a3 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Put.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.Put.cs @@ -18,7 +18,7 @@ partial class Trie private static ReadOnlySpan CommonPrefix(ReadOnlySpan a, ReadOnlySpan b) { var minLen = a.Length <= b.Length ? a.Length : b.Length; - int i = 0; + var i = 0; if (a.Length != 0 && b.Length != 0) { for (i = 0; i < minLen; i++) @@ -77,7 +77,7 @@ private void Put(ref Node node, ReadOnlySpan path, Node val) var pathRemain = path[prefix.Length..]; var keyRemain = node.Key.Span[prefix.Length..]; var child = Node.NewBranch(); - Node grandChild = new Node(); + var grandChild = new Node(); if (keyRemain.Length == 1) { child.Children[keyRemain[0]] = node.Next; @@ -145,8 +145,8 @@ private void Put(ref Node node, ReadOnlySpan path, Node val) } case NodeType.HashNode: { - Node newNode = _cache.Resolve(node.Hash); - if (newNode is null) throw new InvalidOperationException("Internal error, can't resolve hash when mpt put"); + var newNode = _cache.Resolve(node.Hash) + ?? throw new InvalidOperationException("Internal error, can't resolve hash when mpt put"); node = newNode; Put(ref node, path, val); break; diff --git a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.cs b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.cs index 7a48f2dc0a..88a16e95e9 100644 --- a/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.cs +++ b/src/Neo.Cryptography.MPTTrie/Cryptography/MPTTrie/Trie.cs @@ -18,14 +18,13 @@ public partial class Trie { private const byte Prefix = 0xf0; private readonly bool _full; - private readonly IStoreSnapshot _store; private Node _root; private readonly Cache _cache; public Node Root => _root; public Trie(IStoreSnapshot store, UInt256 root, bool full_state = false) { - _store = store ?? throw new ArgumentNullException(nameof(store)); + ArgumentNullException.ThrowIfNull(store); _cache = new Cache(store, Prefix); _root = root is null ? new Node() : Node.NewHash(root); _full = full_state; diff --git a/src/Neo.Cryptography.MPTTrie/GlobalSuppressions.cs b/src/Neo.Cryptography.MPTTrie/GlobalSuppressions.cs new file mode 100644 index 0000000000..5253c64ce2 --- /dev/null +++ b/src/Neo.Cryptography.MPTTrie/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Style", "IDE0290:Use primary constructor", Justification = "Not required", Scope = "module")] From 9b7c800e3592605196b05da0bd56b5ecee37602b Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Wed, 4 Jun 2025 13:44:29 +0200 Subject: [PATCH 2/2] format --- src/Neo.Cryptography.MPTTrie/GlobalSuppressions.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Neo.Cryptography.MPTTrie/GlobalSuppressions.cs b/src/Neo.Cryptography.MPTTrie/GlobalSuppressions.cs index 5253c64ce2..069150354c 100644 --- a/src/Neo.Cryptography.MPTTrie/GlobalSuppressions.cs +++ b/src/Neo.Cryptography.MPTTrie/GlobalSuppressions.cs @@ -1,7 +1,13 @@ -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. +// Copyright (C) 2015-2025 The Neo Project. +// +// GlobalSuppressions.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. using System.Diagnostics.CodeAnalysis;