Exemplo n.º 1
0
        public static MPTNode NewHash(UInt256 hash)
        {
            if (hash is null)
            {
                throw new ArgumentNullException(nameof(NewHash));
            }
            var n = new MPTNode
            {
                type = NodeType.HashNode,
                hash = hash,
            };

            return(n);
        }
Exemplo n.º 2
0
        public static MPTNode NewLeaf(byte[] value)
        {
            if (value is null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            var n = new MPTNode
            {
                type      = NodeType.LeafNode,
                Value     = value,
                Reference = 1,
            };

            return(n);
        }
Exemplo n.º 3
0
        public static MPTNode NewBranch()
        {
            var n = new MPTNode
            {
                type      = NodeType.BranchNode,
                Reference = 1,
                Children  = new MPTNode[BranchChildCount],
            };

            for (int i = 0; i < BranchChildCount; i++)
            {
                n.Children[i] = new MPTNode();
            }
            return(n);
        }
Exemplo n.º 4
0
        public void PutNode(MPTNode np)
        {
            var n = Resolve(np.Hash);

            if (n is null)
            {
                np.Reference   = 1;
                cache[np.Hash] = new Trackable
                {
                    Node  = np.Clone(),
                    State = TrackState.Added,
                };
                return;
            }
            var entry = cache[np.Hash];

            entry.Node.Reference++;
            entry.State = TrackState.Changed;
        }
Exemplo n.º 5
0
        public MPTNode Clone()
        {
            switch (type)
            {
            case NodeType.BranchNode:
                var n = new MPTNode
                {
                    type      = type,
                    Reference = Reference,
                    Children  = new MPTNode[BranchChildCount],
                };
                for (int i = 0; i < BranchChildCount; i++)
                {
                    n.Children[i] = Children[i].CloneAsChild();
                }
                return(n);

            case NodeType.ExtensionNode:
                return(new MPTNode
                {
                    type = type,
                    Key = (byte[])Key.Clone(),
                    Next = Next.CloneAsChild(),
                    Reference = Reference,
                });

            case NodeType.LeafNode:
                return(new MPTNode
                {
                    type = type,
                    Value = (byte[])Value.Clone(),
                    Reference = Reference,
                });

            case NodeType.HashNode:
            case NodeType.Empty:
                return(this);

            default:
                throw new InvalidOperationException(nameof(Clone));
            }
        }
Exemplo n.º 6
0
        public static MPTNode NewExtension(byte[] key, MPTNode next)
        {
            if (key is null || next is null)
            {
                throw new ArgumentNullException(nameof(NewExtension));
            }
            if (key.Length == 0)
            {
                throw new InvalidOperationException(nameof(NewExtension));
            }
            var n = new MPTNode
            {
                type      = NodeType.ExtensionNode,
                Key       = key,
                Next      = next,
                Reference = 1,
            };

            return(n);
        }
Exemplo n.º 7
0
        private bool GetProof(ref MPTNode node, ReadOnlySpan <byte> path, HashSet <byte[]> set)
        {
            switch (node.Type)
            {
            case NodeType.LeafNode:
            {
                if (path.IsEmpty)
                {
                    set.Add(node.ToArrayWithoutReference());
                    return(true);
                }
                break;
            }

            case NodeType.Empty:
                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");
                }
                node = newNode;
                return(GetProof(ref node, path, set));
            }

            case NodeType.BranchNode:
            {
                set.Add(node.ToArrayWithoutReference());
                if (path.IsEmpty)
                {
                    return(GetProof(ref node.Children[MPTNode.BranchChildCount - 1], path, set));
                }
                return(GetProof(ref node.Children[path[0]], path[1..], set));
Exemplo n.º 8
0
        private bool TryDelete(ref MPTNode node, ReadOnlySpan <byte> path)
        {
            switch (node.Type)
            {
            case NodeType.LeafNode:
            {
                if (path.IsEmpty)
                {
                    if (!full)
                    {
                        cache.DeleteNode(node.Hash);
                    }
                    node = new MPTNode();
                    return(true);
                }
                return(false);
            }

            case NodeType.ExtensionNode:
            {
                if (path.StartsWith(node.Key))
                {
                    var oldHash = node.Hash;
                    var result  = TryDelete(ref node.Next, path[node.Key.Length..]);
Exemplo n.º 9
0
        private ReadOnlySpan <byte> Seek(ref MPTNode node, ReadOnlySpan <byte> path, out MPTNode start)
        {
            switch (node.Type)
            {
            case NodeType.LeafNode:
            {
                if (path.IsEmpty)
                {
                    start = node;
                    return(ReadOnlySpan <byte> .Empty);
                }
                break;
            }

            case NodeType.Empty:
                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");
                }
                node = newNode;
                return(Seek(ref node, path, out start));
            }

            case NodeType.BranchNode:
            {
                if (path.IsEmpty)
                {
                    start = node;
                    return(ReadOnlySpan <byte> .Empty);
                }
                return(Concat(path[..1], Seek(ref node.Children[path[0]], path[1..], out start)));