private void OnBlockProcessed(object?sender, BlockProcessedEventArgs e)
        {
            if (_logger.IsWarn)
            {
                _logger.Warn($"Tree tracker for {_baselineTree} processing block {e.Block.ToString(Block.Format.Short)}");
            }

            if (_currentBlockHeader != null && _currentBlockHeader.Hash != e.Block.ParentHash && _currentBlockHeader.Number < e.Block.Number)
            {
                // what is this - not covered by any test?
                // why do we build tree here?
                _baselineTreeHelper.BuildTree(_baselineTree, _address, new BlockParameter(_currentBlockHeader.Hash), new BlockParameter(e.Block.Hash));
                _currentBlockHeader = e.Block.Header;

                // TODO: why this is here
                _baselineTree.MemorizeCurrentCount(_baselineTree.LastBlockDbHash, _baselineTree.LastBlockWithLeaves, _baselineTree.Count);
                return;
            }

            uint removedItemsCount = 0;
            bool reorganized       = _currentBlockHeader != null && _currentBlockHeader.Hash != e.Block.ParentHash;

            if (reorganized)
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn(
                        $"Tree tracker for {_baselineTree} reorganizes from branching point at {e.Block.ToString(Block.Format.Short)}");
                }
                removedItemsCount = Revert(e.Block.Number);
            }

            _currentBlockHeader = e.Block.Header;
            uint treeStartingCount = _baselineTree.Count;
            uint newLeavesCount    = AddFromCurrentBlock(e.TxReceipts);

            _baselineTree.CalculateHashes(treeStartingCount - removedItemsCount);
            if (newLeavesCount != 0 || removedItemsCount != 0 || reorganized)
            {
                uint currentTreeCount = treeStartingCount + newLeavesCount - removedItemsCount;
                _baselineTree.MemorizeCurrentCount(e.Block.Hash, e.Block.Number, currentTreeCount);
            }
        }
Пример #2
0
        public BaselineTree BuildTree(BaselineTree baselineTree, Address treeAddress, BlockParameter blockFrom, BlockParameter blockTo)
        {
            if (_logger.IsWarn)
            {
                _logger.Warn($"Build {baselineTree} from {blockFrom} to {blockTo}");
            }

            var       initCount          = baselineTree.Count;
            LogFilter insertLeavesFilter = new LogFilter(
                0,
                blockFrom,
                blockTo,
                new AddressFilter(treeAddress),
                new SequenceTopicsFilter(new SpecificTopic(BaselineModule.LeavesTopic)));

            LogFilter insertLeafFilter = new LogFilter(
                0,
                blockFrom,
                blockTo,
                new AddressFilter(treeAddress),
                new SequenceTopicsFilter(new SpecificTopic(BaselineModule.LeafTopic)));

            var insertLeavesLogs = _logFinder.FindLogs(insertLeavesFilter);
            var insertLeafLogs   = _logFinder.FindLogs(insertLeafFilter);

            long?currentBlockNumber = null;
            uint count = 0;

            using var batch = baselineTree.StartBatch();
            foreach (FilterLog filterLog in insertLeavesLogs
                     .Union(insertLeafLogs)
                     .OrderBy(fl => fl.BlockNumber).ThenBy(fl => fl.LogIndex))
            {
                if (filterLog.BlockHash == baselineTree.LastBlockDbHash)
                {
                    continue;
                }
                if (currentBlockNumber == null)
                {
                    currentBlockNumber = filterLog.BlockNumber;
                }

                if (currentBlockNumber != filterLog.BlockNumber)
                {
                    baselineTree.MemorizePastCount(currentBlockNumber.Value, count);
                    currentBlockNumber = filterLog.BlockNumber;
                }

                if (filterLog.Data.Length == 96)
                {
                    Keccak leafHash = new Keccak(filterLog.Data.Slice(32, 32).ToArray());

                    if (_logger.IsWarn)
                    {
                        _logger.Warn($"Inserting leaf into {baselineTree} in block {currentBlockNumber}");
                    }
                    baselineTree.Insert(leafHash, false);
                    ++count;
                }
                else
                {
                    for (int i = 0; i < (filterLog.Data.Length - 128) / 32; i++)
                    {
                        Keccak leafHash = new Keccak(filterLog.Data.Slice(128 + 32 * i, 32).ToArray());
                        if (_logger.IsWarn)
                        {
                            _logger.Warn($"Inserting leaf {i} into {baselineTree} in block {currentBlockNumber}");
                        }
                        baselineTree.Insert(leafHash, false);
                        ++count;
                    }
                }
            }

            if (currentBlockNumber != null && count != 0)
            {
                baselineTree.MemorizePastCount(currentBlockNumber.Value, baselineTree.Count);
            }

            baselineTree.CalculateHashes(initCount);
            return(baselineTree);
        }