public BlockResult ExecuteNextBlock(CancellationToken cancellationToken)
        {
            this.logger.LogTrace("()");

            BlockResult result = new BlockResult();

            try
            {
                using (new StopwatchDisposable(o => this.Validator.PerformanceCounter.AddBlockFetchingTime(o)))
                {
                    while (true)
                    {
                        result.Block = this.Puller.NextBlock(cancellationToken);
                        if (result.Block != null)
                        {
                            this.logger.LogTrace("Block received from puller.");
                            break;
                        }

                        this.logger.LogTrace("No block received from puller due to reorganization, rewinding.");
                        while (true)
                        {
                            uint256      hash     = this.UTXOSet.Rewind().GetAwaiter().GetResult();
                            ChainedBlock rewinded = this.Chain.GetBlock(hash);
                            if (rewinded == null)
                            {
                                this.logger.LogTrace("Rewound to '{0}', which is still not a part of the current best chain, rewinding further.", hash);
                                continue;
                            }

                            this.logger.LogTrace("Rewound to '{0}'.", hash);
                            this.Tip = rewinded;
                            this.Puller.SetLocation(rewinded);
                            break;
                        }
                    }
                }

                this.AcceptBlock(new ContextInformation(result, this.Validator.ConsensusParams));
            }
            catch (ConsensusErrorException ex)
            {
                result.Error = ex.ConsensusError;
            }

            this.logger.LogTrace("(-):*.{0}='{1}',*.{2}='{3}'", nameof(result.ChainedBlock), result.ChainedBlock, nameof(result.Error), result.Error?.Message);
            return(result);
        }
        public ContextInformation(BlockResult blockResult, NBitcoin.Consensus consensus)
        {
            Guard.NotNull(blockResult, nameof(blockResult));
            Guard.NotNull(consensus, nameof(consensus));

            this.BlockResult = blockResult;
            this.Consensus   = consensus;

            // TODO: adding flags to determine the flow of logic is not ideal
            // a refator is in depbate on moving to a consensus rules engine
            // this will remove hte need for flags as a validation will
            // only use the required rules (i.e if the check pow rule will be ommited form the flow)
            this.CheckPow        = true;
            this.CheckMerkleRoot = true;
            this.OnlyCheck       = false;
        }
        public BlockResult ExecuteNextBlock(CancellationToken cancellationToken)
        {
            BlockResult result = new BlockResult();

            try
            {
                using (this.watch.Start(o => this.Validator.PerformanceCounter.AddBlockFetchingTime(o)))
                {
                    while (true)
                    {
                        result.Block = this.Puller.NextBlock(cancellationToken);
                        if (result.Block != null)
                        {
                            break;
                        }
                        else
                        {
                            while (true)
                            {
                                var hash     = this.UTXOSet.Rewind().GetAwaiter().GetResult();
                                var rewinded = this.Chain.GetBlock(hash);
                                if (rewinded == null)
                                {
                                    continue;
                                }
                                this.Tip = rewinded;
                                this.Puller.SetLocation(rewinded);
                                break;
                            }
                        }
                    }
                }

                this.AcceptBlock(new ContextInformation(result, this.Validator.ConsensusParams));
            }
            catch (ConsensusErrorException ex)
            {
                result.Error = ex.ConsensusError;
            }
            return(result);
        }