예제 #1
0
        static readonly int MaxBlocks = 70;          // The maximum number of blocks that may be cached.

        public IEnumerable <NBitcoin.Block> GetBlocks(IEnumerable <NBitcoin.uint256> hashes, CancellationToken cancellationToken)
        {
            var asked = hashes.ToList();

            if (asked.Count > MaxBlocks)                            // Asked for more than fit in the cache size, no point in checking cache.
            {
                return(_Repo.GetBlocks(hashes, cancellationToken)); // Fetch from repo instead.
            }
            var lastAsked = _LastAsked;

            if (lastAsked != null && asked.SequenceEqual(lastAsked.Select(a => a.Item1)))
            {
                return(lastAsked.Select(l => l.Item2));
            }

            var blocks = _Repo.GetBlocks(hashes, cancellationToken).ToList();

            if (blocks.Count < 5)  // Shouldn't this number match 'MaxBlocks = 70' ?
            {
                _LastAsked = blocks.Select(b => Tuple.Create(b.GetHash(), b)).ToList();
            }
            else
            {
                _LastAsked = null;
            }

            return(blocks);
        }
예제 #2
0
        public IEnumerable <NBitcoin.Block> GetBlocks(IEnumerable <NBitcoin.uint256> hashes, CancellationToken cancellation)
        {
            var asked = hashes.ToList();

            if (asked.Count > MaxBlocks)
            {
                return(_Repo.GetBlocks(hashes, cancellation));
            }
            var lastAsked = _LastAsked;

            if (lastAsked != null && asked.SequenceEqual(lastAsked.Select(a => a.Item1)))
            {
                return(lastAsked.Select(l => l.Item2));
            }
            var blocks = _Repo.GetBlocks(hashes, cancellation).ToList();

            if (blocks.Count < 5)
            {
                _LastAsked = blocks.Select(b => Tuple.Create(b.GetHash(), b)).ToList();
            }
            else
            {
                _LastAsked = null;
            }
            return(blocks);
        }
예제 #3
0
        public IEnumerator <BlockInfo> GetEnumerator()
        {
            Queue <DateTime> lastLogs    = new Queue <DateTime>();
            Queue <int>      lastHeights = new Queue <int>();

            var fork    = _BlockHeaders.FindFork(_Checkpoint.BlockLocator);
            var headers = _BlockHeaders.EnumerateAfter(fork);

            headers = headers.Where(h => h.Height <= ToHeight);
            var first = headers.FirstOrDefault();

            if (first == null)
            {
                yield break;
            }
            var height = first.Height;

            if (first.Height == 1)
            {
                headers = new[] { fork }.Concat(headers);
                height  = 0;
            }

            foreach (var block in _BlocksRepository.GetBlocks(headers.Select(b => b.HashBlock), CancellationToken))
            {
                var header = _BlockHeaders.GetBlock(height);

                if (block == null)
                {
                    var storeTip = _BlocksRepository.GetStoreTip();
                    if (storeTip != null)
                    {
                        // Store is caught up with Chain but the block is missing from the store.
                        if (header.Header.BlockTime <= storeTip.Header.BlockTime)
                        {
                            throw new InvalidOperationException($"Chained block not found in store (height = { height }). Re-create the block store.");
                        }
                    }
                    // Allow Store to catch up with Chain.
                    break;
                }

                _LastProcessed = header;
                yield return(new BlockInfo()
                {
                    Block = block,
                    BlockId = header.HashBlock,
                    Height = header.Height
                });

                IndexerTrace.Processed(height, Math.Min(ToHeight, _BlockHeaders.Tip.Height), lastLogs, lastHeights);
                height++;
            }
        }
예제 #4
0
        public IEnumerator <BlockInfo> GetEnumerator()
        {
            Queue <DateTime> lastLogs    = new Queue <DateTime>();
            Queue <int>      lastHeights = new Queue <int>();

            var fork = _BlockHeaders.FindFork(_Checkpoint.BlockLocator);

            _LastProcessed = fork;
            var headers = _BlockHeaders.EnumerateAfter(fork);

            headers = headers.Where(h => h.Height >= FromHeight && h.Height <= ToHeight);
            var first = headers.FirstOrDefault();

            if (first == null)
            {
                yield break;
            }
            var height = first.Height;

            if (first.Height == 1)
            {
                headers = new[] { fork }.Concat(headers);
                height  = 0;
            }

            foreach (var block in _BlocksRepository.GetBlocks(headers.Select(b => b.HashBlock), CancellationToken).TakeWhile(b => b != null))
            {
                var header = _BlockHeaders.GetBlock(height);
                _LastProcessed = header;
                yield return(new BlockInfo()
                {
                    Block = block,
                    BlockId = header.HashBlock,
                    Height = header.Height
                });

                IndexerTrace.Processed(height, Math.Min(ToHeight, _BlockHeaders.Tip.Height), lastLogs, lastHeights);
                height++;
            }
        }