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); }
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); }
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++; } }
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++; } }