/// <summary>
        /// Pre-fetch UTXOs for a block and some blocks with higher height.
        /// <para>
        /// This task runs in the background.
        /// </para>
        /// </summary>
        /// <param name="header">Header of a block that is about to be partially validated and that requires pre-fetching.</param>
        private Task OnHeaderEnqueued(ChainedHeader header, CancellationToken cancellation)
        {
            ChainedHeader currentHeader = header;

            // Go Lookahead blocks ahead of current header and get block for pre-fetching.
            // There might be several blocks at height of header.Height + Lookahead but
            // only first one will be pre-fetched since pre-fetching is in place mostly to
            // speed up IBD.
            for (int i = 0; i < Lookahead; i++)
            {
                if (currentHeader.Next.Count == 0)
                {
                    this.logger.LogTrace("(-)[NO_HEADERS]");
                    return(Task.CompletedTask);
                }

                currentHeader = currentHeader.Next.FirstOrDefault();

                if (currentHeader == null)
                {
                    this.logger.LogTrace("(-)[NO_NEXT_HEADER]");
                    return(Task.CompletedTask);
                }
            }

            Block block = currentHeader.Block;

            if (block == null)
            {
                this.logger.LogTrace("(-)[NO_BLOCK_DATA]");
                return(Task.CompletedTask);
            }

            bool farFromTip = currentHeader.Height > this.chainIndexer.Tip.Height + (Lookahead / 2);

            if (!farFromTip)
            {
                this.logger.LogDebug("Skipping pre-fetch, the block selected is too close to the tip.");
                this.logger.LogTrace("(-)[TOO_CLOSE_TO_PREFETCH_HEIGHT]");
                return(Task.CompletedTask);
            }

            bool enforceBIP30 = false;

            if (currentHeader.Height > this.checkpoints.GetLastCheckpointHeight())
            {
                enforceBIP30 = DeploymentFlags.EnforceBIP30ForBlock(currentHeader);
            }

            OutPoint[] idsToCache = this.coinviewHelper.GetIdsToFetch(block, enforceBIP30);

            if (idsToCache.Length != 0)
            {
                this.coinview.CacheCoins(idsToCache);

                this.logger.LogDebug("Block '{0}' had {1} ids pre-fetched.", currentHeader.Height, idsToCache.Length);
            }

            return(Task.CompletedTask);
        }
        /// <summary>
        /// Pre-fetches UTXOs for a block and some blocks with higher height.
        /// pre-fetching is done on the background.
        /// </summary>
        /// <param name="header">Header of a block that is about to be partially validated and requires pre-fetching.</param>
        private async Task OnHeaderEnqueuedAsync(ChainedHeader header, CancellationToken cancellation)
        {
            ChainedHeader currentHeader = header;

            // Go Lookahead blocks ahead of current header and get block for pre-fetching.
            // There might be several blocks at height of header.Height + Lookahead but
            // only first one will be pre-fetched since pre-fetching is in place mostly to
            // speed up IBD.
            for (int i = 0; i < Lookahead; i++)
            {
                if (currentHeader.Next.Count == 0)
                {
                    this.logger.LogTrace("(-)[NO_HEADERS]");
                    return;
                }

                currentHeader = currentHeader.Next.FirstOrDefault();

                if (currentHeader == null)
                {
                    this.logger.LogTrace("(-)[NO_NEXT_HEADER]");
                    return;
                }
            }

            Block block = currentHeader.Block;

            if (block == null)
            {
                this.logger.LogTrace("(-)[NO_BLOCK_DATA]");
                return;
            }

            bool farFromTip = currentHeader.Height > this.chainIndexer.Tip.Height + (Lookahead / 2);

            if (!farFromTip)
            {
                this.logger.LogDebug("Block selected for pre-fetching is too close to the tip! Skipping pre-fetching.");
                this.logger.LogTrace("(-)[TOO_CLOSE_TO_PREFETCH]");
                return;
            }

            bool enforceBIP30 = DeploymentFlags.EnforceBIP30ForBlock(currentHeader);

            uint256[] idsToFetch = this.coinviewHelper.GetIdsToFetch(block, enforceBIP30);

            if (idsToFetch.Length != 0)
            {
                this.coinview.FetchCoins(idsToFetch, cancellation);

                this.logger.LogTrace("{0} ids were pre-fetched.", idsToFetch.Length);
            }
        }