Exemplo n.º 1
0
        /// <summary>
        /// A puller method that will continuously loop and ask for the next block  in the chain from peers.
        /// The block will then be passed to the consensus validation.
        /// </summary>
        /// <remarks>
        /// If the <see cref="Block"/> returned from the puller is <c>null</c> that means the puller is signaling a reorg was detected.
        /// In this case a rewind of the <see cref="CoinView"/> db will be triggered to roll back consensus until a block is found that is in the best chain.
        /// </remarks>
        private async Task PullerLoopAsync()
        {
            this.logger.LogTrace("()");

            while (!this.nodeLifetime.ApplicationStopping.IsCancellationRequested)
            {
                BlockValidationContext blockValidationContext = new BlockValidationContext();

                using (new StopwatchDisposable(o => this.Validator.PerformanceCounter.AddBlockFetchingTime(o)))
                {
                    // Save the current consensus tip to later check if it changed.
                    ChainedBlock consensusTip = this.Tip;

                    this.logger.LogTrace("Asking block puller to deliver next block.");

                    // This method will block until the next block is downloaded.
                    LookaheadResult lookaheadResult = this.Puller.NextBlock(this.nodeLifetime.ApplicationStopping);

                    if (lookaheadResult.Block == null)
                    {
                        using (await this.consensusLock.LockAsync(this.nodeLifetime.ApplicationStopping).ConfigureAwait(false))
                        {
                            this.logger.LogTrace("No block received from puller due to reorganization.");

                            if (!consensusTip.Equals(this.Tip))
                            {
                                this.logger.LogTrace("Consensus tip changed from '{0}' to '{1}', no rewinding.", consensusTip, this.Tip);
                                continue;
                            }

                            this.logger.LogTrace("Rewinding.");
                            await this.RewindCoinViewLockedAsync().ConfigureAwait(false);

                            continue;
                        }
                    }

                    blockValidationContext.Block = lookaheadResult.Block;
                    blockValidationContext.Peer  = lookaheadResult.Peer;
                }

                this.logger.LogTrace("Block received from puller.");
                await this.AcceptBlockAsync(blockValidationContext).ConfigureAwait(false);
            }

            this.logger.LogTrace("(-)");
        }
        /// <summary>
        /// A puller method that will continuously loop and ask for the next block  in the chain from peers.
        /// The block will then be passed to the consensus validation.
        /// </summary>
        /// <remarks>
        /// If the <see cref="Block"/> returned from the puller is null that means the puller is signalling a reorg was detected.
        /// In this case a rewind of the <see cref="CoinView"/> db will be triggered to roll back consensus until a block is found that is in the best chain.
        /// </remarks>
        /// <param name="cancellationToken">A cancellation token that will stop the loop.</param>
        private async Task PullerLoopAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                BlockValidationContext blockValidationContext = new BlockValidationContext();

                using (new StopwatchDisposable(o => this.Validator.PerformanceCounter.AddBlockFetchingTime(o)))
                {
                    // Save the current consensus tip to later check if it changed.
                    ChainedBlock consensusTip = this.Tip;

                    // This method will block until the next block is downloaded.
                    blockValidationContext.Block = this.Puller.NextBlock(cancellationToken);

                    if (blockValidationContext.Block == null)
                    {
                        using (await this.consensusLock.LockAsync().ConfigureAwait(false))
                        {
                            this.logger.LogTrace("No block received from puller due to reorganization.");

                            if (!consensusTip.Equals(this.Tip))
                            {
                                this.logger.LogTrace("Consensus tip changed from '{0}' to '{1}', no rewinding.", consensusTip, this.Tip);
                                continue;
                            }

                            this.logger.LogTrace("Rewinding.");
                            await this.RewindCoinViewLockedAsync().ConfigureAwait(false);

                            continue;
                        }
                    }
                }

                this.logger.LogTrace("Block received from puller.");
                await this.AcceptBlockAsync(blockValidationContext).ConfigureAwait(false);
            }
        }