Пример #1
0
        private bool TryDelete(ref MPTNode node, ReadOnlySpan <byte> path)
        {
            switch (node)
            {
            case LeafNode _:
            {
                if (path.IsEmpty)
                {
                    node = HashNode.EmptyNode;
                    return(true);
                }
                return(false);
            }

            case ExtensionNode extensionNode:
            {
                if (path.StartsWith(extensionNode.Key))
                {
                    var result = TryDelete(ref extensionNode.Next, path[extensionNode.Key.Length..]);
Пример #2
0
        public static unsafe MPTNode Decode(ReadOnlySpan <byte> data)
        {
            if (data.IsEmpty)
            {
                return(null);

                fixed(byte *pointer = data)
                {
                    using UnmanagedMemoryStream stream = new UnmanagedMemoryStream(pointer, data.Length);
                    using BinaryReader reader          = new BinaryReader(stream);

                    MPTNode n = (MPTNode)ReflectionCache <NodeType> .CreateInstance((NodeType)reader.ReadByte());

                    if (n is null)
                    {
                        throw new InvalidOperationException();
                    }

                    n.DecodeSpecific(reader);
                    return(n);
                }
        }
Пример #3
0
        private ReadOnlySpan <byte> Seek(ref MPTNode node, ReadOnlySpan <byte> path, out MPTNode start)
        {
            switch (node)
            {
            case LeafNode leafNode:
            {
                if (path.IsEmpty)
                {
                    start = leafNode;
                    return(ReadOnlySpan <byte> .Empty);
                }
                break;
            }

            case HashNode hashNode:
            {
                if (hashNode.IsEmpty)
                {
                    break;
                }
                var newNode = Resolve(hashNode);
                if (newNode is null)
                {
                    break;
                }
                node = newNode;
                return(Seek(ref node, path, out start));
            }

            case BranchNode branchNode:
            {
                if (path.IsEmpty)
                {
                    start = branchNode;
                    return(ReadOnlySpan <byte> .Empty);
                }
                return(Concat(path[..1], Seek(ref branchNode.Children[path[0]], path[1..], out start)));
Пример #4
0
        private bool GetProof(ref MPTNode node, ReadOnlySpan <byte> path, HashSet <byte[]> set)
        {
            switch (node)
            {
            case LeafNode leafNode:
            {
                if (path.IsEmpty)
                {
                    set.Add(leafNode.Encode());
                    return(true);
                }
                break;
            }

            case HashNode hashNode:
            {
                if (hashNode.IsEmpty)
                {
                    break;
                }
                var newNode = Resolve(hashNode);
                if (newNode is null)
                {
                    break;
                }
                node = newNode;
                return(GetProof(ref node, path, set));
            }

            case BranchNode branchNode:
            {
                set.Add(branchNode.Encode());
                if (path.IsEmpty)
                {
                    return(GetProof(ref branchNode.Children[BranchNode.ChildCount - 1], path, set));
                }
                return(GetProof(ref branchNode.Children[path[0]], path[1..], set));
Пример #5
0
        private bool TryGet(ref MPTNode node, ReadOnlySpan <byte> path, out ReadOnlySpan <byte> value)
        {
            switch (node)
            {
            case LeafNode leafNode:
            {
                if (path.IsEmpty)
                {
                    value = leafNode.Value;
                    return(true);
                }
                break;
            }

            case HashNode hashNode:
            {
                if (hashNode.IsEmpty)
                {
                    break;
                }
                var newNode = Resolve(hashNode);
                if (newNode is null)
                {
                    break;
                }
                node = newNode;
                return(TryGet(ref node, path, out value));
            }

            case BranchNode branchNode:
            {
                if (path.IsEmpty)
                {
                    return(TryGet(ref branchNode.Children[BranchNode.ChildCount - 1], path, out value));
                }
                return(TryGet(ref branchNode.Children[path[0]], path[1..], out value));
Пример #6
0
 private void PutToStore(MPTNode node)
 {
     store.Put(Prefix, node.Hash.ToArray(), node.Encode());
 }
Пример #7
0
        private MPTNode Resolve(HashNode n)
        {
            var data = store.TryGet(Prefix, n.Hash.ToArray());

            return(MPTNode.Decode(data));
        }
Пример #8
0
 public MPTTrie(ISnapshot store, UInt256 root)
 {
     this.store = store ?? throw new ArgumentNullException();
     this.root  = root is null ? HashNode.EmptyNode : new HashNode(root);
 }
Пример #9
0
 internal override void DecodeSpecific(BinaryReader reader)
 {
     Key  = reader.ReadVarBytes(MaxKeyLength);
     Next = new HashNode();
     Next.DecodeSpecific(reader);
 }