Exemplo n.º 1
0
 public ExtendedBlockPuller(BlockPuller.OnBlockDownloadedCallback callback, IChainState chainState, ProtocolVersion protocolVersion, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory)
 {
     this.puller = new BlockPuller(callback, chainState, protocolVersion, dateTimeProvider, loggerFactory);
 }
 public ExtendedBlockPuller(IChainState chainState, NodeSettings nodeSettings, IDateTimeProvider dateTimeProvider, INodeStats nodeStats, ILoggerFactory loggerFactory)
 {
     this.puller = new BlockPuller(chainState, nodeSettings, dateTimeProvider, nodeStats, loggerFactory);
 }
        /// <summary>
        /// Pull blocks, validate them and update the UTXO Set
        /// </summary>
        /// <param name="utxo">UTXO Set</param>
        /// <param name="puller">Block source</param>
        /// <returns>Stream of validated blocks</returns>
        public IEnumerable <Block> Run(CoinViewStack utxoStack, BlockPuller puller)
        {
            var utxo            = utxoStack.Top;
            var cache           = utxoStack.Find <CacheCoinView>();
            var lookaheadPuller = puller as ILookaheadBlockPuller;

            puller.SetLocation(utxo.Tip);
            ThresholdConditionCache bip9 = new ThresholdConditionCache(_ConsensusParams);
            StopWatch watch    = new StopWatch();
            bool      rejected = false;

            while (true)
            {
                Block block = null;
                while (true)
                {
                    rejected = false;
                    try
                    {
                        using (watch.Start(o => PerformanceCounter.AddBlockFetchingTime(o)))
                        {
                            block = puller.NextBlock();
                        }
                        ChainedBlock       next;
                        ContextInformation context;
                        ConsensusFlags     flags;
                        using (watch.Start(o => PerformanceCounter.AddBlockProcessingTime(o)))
                        {
                            CheckBlockHeader(block.Header);
                            next    = new ChainedBlock(block.Header, block.Header.GetHash(), utxo.Tip);
                            context = new ContextInformation(next, this._ConsensusParams);
                            ContextualCheckBlockHeader(block.Header, context);
                            var states = bip9.GetStates(utxo.Tip);
                            flags = new ConsensusFlags(next, states, _ConsensusParams);
                            ContextualCheckBlock(block, flags, context);
                            CheckBlock(block);
                        }

                        var commitable = new CommitableCoinView(next, utxo);
                        using (watch.Start(o => PerformanceCounter.AddUTXOFetchingTime(o)))
                        {
                            commitable.FetchCoins(GetIdsToFetch(block, flags.EnforceBIP30));
                        }
                        commitable.SetInner(NullCoinView.Instance);

                        Task prefetching = GetPrefetchingTask(cache, lookaheadPuller, flags);
                        using (watch.Start(o => PerformanceCounter.AddBlockProcessingTime(o)))
                        {
                            ExecuteBlock(block, next, flags, commitable, null);
                        }
                        using (watch.Start(o => PerformanceCounter.AddUTXOFetchingTime(o)))
                        {
                            prefetching.Wait();
                            commitable.Commit(utxo);
                        }
                    }
                    catch (ConsensusErrorException ex)
                    {
                        rejected = true;
                        if (ex.ConsensusError == ConsensusErrors.TimeTooNew)
                        {
                            puller.Reject(block, RejectionMode.Temporary);
                        }
                        else
                        {
                            puller.Reject(block, RejectionMode.Permanent);
                        }
                    }
                    if (!rejected)
                    {
                        yield return(block);
                    }
                }
            }
        }