Example #1
0
        internal void Accept(ITreeVisitor visitor, ITrieNodeResolver nodeResolver, TrieVisitContext trieVisitContext)
        {
            try
            {
                ResolveNode(nodeResolver);
            }
            catch (TrieException)
            {
                visitor.VisitMissingNode(Keccak, trieVisitContext);
                return;
            }

            ResolveKey(nodeResolver, trieVisitContext.Level == 0);

            switch (NodeType)
            {
            case NodeType.Branch:
            {
                visitor.VisitBranch(this, trieVisitContext);
                trieVisitContext.Level++;
                for (int i = 0; i < 16; i++)
                {
                    TrieNode child = GetChild(nodeResolver, i);
                    if (child != null)
                    {
                        child.ResolveKey(nodeResolver, false);
                        if (visitor.ShouldVisit(child.Keccak !))
                        {
                            trieVisitContext.BranchChildIndex = i;
                            child.Accept(visitor, nodeResolver, trieVisitContext);
                        }

                        if (child.IsPersisted)
                        {
                            UnresolveChild(i);
                        }
                    }
                }

                trieVisitContext.Level--;
                trieVisitContext.BranchChildIndex = null;
                break;
            }

            case NodeType.Extension:
            {
                visitor.VisitExtension(this, trieVisitContext);
                TrieNode child = GetChild(nodeResolver, 0);
                if (child == null)
                {
                    throw new InvalidDataException($"Child of an extension {Key} should not be null.");
                }

                child.ResolveKey(nodeResolver, false);
                if (visitor.ShouldVisit(child.Keccak !))
                {
                    trieVisitContext.Level++;
                    trieVisitContext.BranchChildIndex = null;
                    child.Accept(visitor, nodeResolver, trieVisitContext);
                    trieVisitContext.Level--;
                }

                break;
            }

            case NodeType.Leaf:
            {
                visitor.VisitLeaf(this, trieVisitContext, Value);
                if (!trieVisitContext.IsStorage && trieVisitContext.ExpectAccounts)     // can combine these conditions
                {
                    Account account = _accountDecoder.Decode(Value.AsRlpStream());
                    if (account.HasCode && visitor.ShouldVisit(account.CodeHash))
                    {
                        trieVisitContext.Level++;
                        trieVisitContext.BranchChildIndex = null;
                        visitor.VisitCode(account.CodeHash, trieVisitContext);
                        trieVisitContext.Level--;
                    }

                    if (account.HasStorage && visitor.ShouldVisit(account.StorageRoot))
                    {
                        trieVisitContext.IsStorage = true;
                        TrieNode storageRoot = new(NodeType.Unknown, account.StorageRoot);
                        trieVisitContext.Level++;
                        trieVisitContext.BranchChildIndex = null;
                        storageRoot.Accept(visitor, nodeResolver, trieVisitContext);
                        trieVisitContext.Level--;
                        trieVisitContext.IsStorage = false;
                    }
                }

                break;
            }

            default:
                throw new TrieException($"An attempt was made to visit a node {Keccak} of type {NodeType}");
            }
        }