Skip to content

Commit 9004da9

Browse files
authored
enable nullable for MPTrie (#4173)
1 parent 07a208a commit 9004da9

File tree

12 files changed

+40
-25
lines changed

12 files changed

+40
-25
lines changed

src/Neo.Cryptography.MPTTrie/Cache.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
using Neo.Persistence;
1414
using System;
1515
using System.Collections.Generic;
16-
using System.IO;
17-
using System.Security.Policy;
1816

1917
namespace Neo.Cryptography.MPTTrie
2018
{
@@ -28,9 +26,9 @@ private enum TrackState : byte
2826
Deleted
2927
}
3028

31-
private class Trackable(Node node, TrackState state)
29+
private class Trackable(Node? node, TrackState state)
3230
{
33-
public Node Node { get; internal set; } = node;
31+
public Node? Node { get; internal set; } = node;
3432
public TrackState State { get; internal set; } = state;
3533
}
3634

@@ -52,7 +50,7 @@ private byte[] Key(UInt256 hash)
5250
return buffer;
5351
}
5452

55-
public Node Resolve(UInt256 hash) => ResolveInternal(hash).Node?.Clone();
53+
public Node? Resolve(UInt256 hash) => ResolveInternal(hash).Node?.Clone();
5654

5755
private Trackable ResolveInternal(UInt256 hash)
5856
{

src/Neo.Cryptography.MPTTrie/Neo.Cryptography.MPTTrie.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<TargetFramework>net9.0</TargetFramework>
55
<PackageId>Neo.Cryptography.MPT</PackageId>
66
<RootNamespace>Neo.Cryptography.MPTTrie</RootNamespace>
7+
<Nullable>enable</Nullable>
78
</PropertyGroup>
89

910
<ItemGroup>

src/Neo.Cryptography.MPTTrie/Node.Branch.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Neo.Cryptography.MPTTrie
1717
partial class Node
1818
{
1919
public const int BranchChildCount = 17;
20-
public Node[] Children { get; internal set; }
20+
public Node[] Children { get; internal set; } = [];
2121

2222
public static Node NewBranch()
2323
{

src/Neo.Cryptography.MPTTrie/Node.Extension.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ partial class Node
2222
public const int MaxKeyLength = (ApplicationEngine.MaxStorageKeySize + sizeof(int)) * 2;
2323
public ReadOnlyMemory<byte> Key { get; set; } = ReadOnlyMemory<byte>.Empty;
2424

25-
internal Node _next;
25+
// Not null when Type is ExtensionNode, null if not ExtensionNode
26+
internal Node? _next;
2627

27-
public Node Next
28+
// Not null when Type is ExtensionNode, null if not ExtensionNode
29+
public Node? Next
2830
{
2931
get => _next;
3032
set { _next = value; }
@@ -46,10 +48,20 @@ public static Node NewExtension(byte[] key, Node next)
4648
};
4749
}
4850

49-
protected int ExtensionSize => Key.GetVarSize() + Next.SizeAsChild;
51+
protected int ExtensionSize
52+
{
53+
get
54+
{
55+
if (Next is null)
56+
throw new InvalidOperationException("ExtensionSize but not extension node");
57+
return Key.GetVarSize() + Next.SizeAsChild;
58+
}
59+
}
5060

5161
private void SerializeExtension(BinaryWriter writer)
5262
{
63+
if (Next is null)
64+
throw new InvalidOperationException("SerializeExtension but not extension node");
5365
writer.WriteVarBytes(Key.Span);
5466
Next.SerializeAsChild(writer);
5567
}

src/Neo.Cryptography.MPTTrie/Node.Hash.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public static Node NewHash(UInt256 hash)
3232

3333
private void SerializeHash(BinaryWriter writer)
3434
{
35+
if (_hash is null)
36+
throw new InvalidOperationException("SerializeHash but not hash node");
3537
writer.Write(_hash);
3638
}
3739

src/Neo.Cryptography.MPTTrie/Node.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace Neo.Cryptography.MPTTrie
1818
{
1919
public partial class Node : ISerializable
2020
{
21-
private UInt256 _hash;
21+
private UInt256? _hash;
2222
public int Reference { get; internal set; }
2323
public UInt256 Hash => _hash ??= new UInt256(Crypto.Hash256(ToArrayWithoutReference()));
2424
public NodeType Type { get; internal set; }
@@ -185,7 +185,7 @@ public Node Clone()
185185
{
186186
Type = Type,
187187
Key = Key,
188-
Next = Next.CloneAsChild(),
188+
Next = Next!.CloneAsChild(), // Next not null if ExtensionNode
189189
Reference = Reference,
190190
};
191191
case NodeType.LeafNode:

src/Neo.Cryptography.MPTTrie/Trie.Delete.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ private bool TryDelete(ref Node node, ReadOnlySpan<byte> path)
4545
if (path.StartsWith(node.Key.Span))
4646
{
4747
var oldHash = node.Hash;
48-
var result = TryDelete(ref node._next, path[node.Key.Length..]);
48+
var result = TryDelete(ref node._next!, path[node.Key.Length..]);
4949
if (!result) return false;
5050
if (!_full) _cache.DeleteNode(oldHash);
51-
if (node.Next.IsEmpty)
51+
if (node.Next!.IsEmpty)
5252
{
5353
node = node.Next;
5454
return true;

src/Neo.Cryptography.MPTTrie/Trie.Find.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Neo.Cryptography.MPTTrie
1717
{
1818
partial class Trie
1919
{
20-
private ReadOnlySpan<byte> Seek(ref Node node, ReadOnlySpan<byte> path, out Node start)
20+
private ReadOnlySpan<byte> Seek(ref Node node, ReadOnlySpan<byte> path, out Node? start)
2121
{
2222
switch (node.Type)
2323
{
@@ -57,7 +57,7 @@ private ReadOnlySpan<byte> Seek(ref Node node, ReadOnlySpan<byte> path, out Node
5757
}
5858
if (path.StartsWith(node.Key.Span))
5959
{
60-
return new([.. node.Key.Span, .. Seek(ref node._next, path[node.Key.Length..], out start)]);
60+
return new([.. node.Key.Span, .. Seek(ref node._next!, path[node.Key.Length..], out start)]);
6161
}
6262
if (node.Key.Span.StartsWith(path))
6363
{
@@ -71,7 +71,7 @@ private ReadOnlySpan<byte> Seek(ref Node node, ReadOnlySpan<byte> path, out Node
7171
return [];
7272
}
7373

74-
public IEnumerable<(ReadOnlyMemory<byte> Key, ReadOnlyMemory<byte> Value)> Find(ReadOnlySpan<byte> prefix, byte[] from = null)
74+
public IEnumerable<(ReadOnlyMemory<byte> Key, ReadOnlyMemory<byte> Value)> Find(ReadOnlySpan<byte> prefix, byte[]? from = null)
7575
{
7676
var path = ToNibbles(prefix);
7777
var offset = 0;
@@ -104,7 +104,7 @@ private ReadOnlySpan<byte> Seek(ref Node node, ReadOnlySpan<byte> path, out Node
104104
return Travers(start, path, from, offset).Select(p => (new ReadOnlyMemory<byte>(FromNibbles(p.Key.Span)), p.Value));
105105
}
106106

107-
private IEnumerable<(ReadOnlyMemory<byte> Key, ReadOnlyMemory<byte> Value)> Travers(Node node, byte[] path, byte[] from, int offset)
107+
private IEnumerable<(ReadOnlyMemory<byte> Key, ReadOnlyMemory<byte> Value)> Travers(Node? node, byte[] path, byte[] from, int offset)
108108
{
109109
if (node is null) yield break;
110110
if (offset < 0) throw new InvalidOperationException("invalid offset");

src/Neo.Cryptography.MPTTrie/Trie.Get.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
using System;
1313
using System.Collections.Generic;
14+
using System.Diagnostics.CodeAnalysis;
1415

1516
namespace Neo.Cryptography.MPTTrie
1617
{
@@ -30,7 +31,7 @@ public byte[] this[byte[] key]
3031
}
3132
}
3233

33-
public bool TryGetValue(byte[] key, out byte[] value)
34+
public bool TryGetValue(byte[] key, [NotNullWhen(true)] out byte[]? value)
3435
{
3536
value = default;
3637
var path = ToNibbles(key);
@@ -78,7 +79,7 @@ private bool TryGet(ref Node node, ReadOnlySpan<byte> path, out ReadOnlySpan<byt
7879
{
7980
if (path.StartsWith(node.Key.Span))
8081
{
81-
return TryGet(ref node._next, path[node.Key.Length..], out value);
82+
return TryGet(ref node._next!, path[node.Key.Length..], out value);
8283
}
8384
break;
8485
}

src/Neo.Cryptography.MPTTrie/Trie.Proof.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
using Neo.Persistence.Providers;
1414
using System;
1515
using System.Collections.Generic;
16+
using System.Diagnostics.CodeAnalysis;
1617

1718
namespace Neo.Cryptography.MPTTrie
1819
{
1920
partial class Trie
2021
{
21-
public bool TryGetProof(byte[] key, out HashSet<byte[]> proof)
22+
public bool TryGetProof(byte[] key, [NotNull] out HashSet<byte[]> proof)
2223
{
2324
var path = ToNibbles(key);
2425
if (path.Length == 0)
@@ -65,7 +66,7 @@ private bool GetProof(ref Node node, ReadOnlySpan<byte> path, HashSet<byte[]> se
6566
if (path.StartsWith(node.Key.Span))
6667
{
6768
set.Add(node.ToArrayWithoutReference());
68-
return GetProof(ref node._next, path[node.Key.Length..], set);
69+
return GetProof(ref node._next!, path[node.Key.Length..], set);
6970
}
7071
break;
7172
}

0 commit comments

Comments
 (0)