예제 #1
0
        public ConsensusFeature(
            DBreezeCoinView dBreezeCoinView,
            Network network,
            LookaheadBlockPuller blockPuller,
            CoinView coinView,
            ChainState chainState,
            IConnectionManager connectionManager,
            Signals.Signals signals,
            ConsensusLoop consensusLoop,
            NodeDeployments nodeDeployments,
            ILoggerFactory loggerFactory,
            ConsensusStats consensusStats,
            ConsensusSettings consensusSettings,
            IRuleRegistration ruleRegistration,
            IConsensusRules consensusRules,
            StakeChainStore stakeChain = null)
        {
            this.dBreezeCoinView   = dBreezeCoinView;
            this.blockPuller       = blockPuller;
            this.coinView          = coinView;
            this.chainState        = chainState;
            this.connectionManager = connectionManager;
            this.signals           = signals;
            this.network           = network;
            this.consensusLoop     = consensusLoop;
            this.nodeDeployments   = nodeDeployments;
            this.stakeChain        = stakeChain;
            this.logger            = loggerFactory.CreateLogger(this.GetType().FullName);
            this.loggerFactory     = loggerFactory;
            this.consensusStats    = consensusStats;
            this.ruleRegistration  = ruleRegistration;
            this.consensusRules    = consensusRules;

            this.chainState.MaxReorgLength = this.network.Consensus.Option <PowConsensusOptions>().MaxReorgLength;
        }
        public ConsensusFeature(
            IAsyncLoopFactory asyncLoopFactory,
            DBreezeCoinView dBreezeCoinView,
            Network network,
            PowConsensusValidator consensusValidator,
            ConcurrentChain chain,
            LookaheadBlockPuller blockPuller,
            CoinView coinView,
            ChainState chainState,
            IConnectionManager connectionManager,
            INodeLifetime nodeLifetime,
            Signals.Signals signals,
            ConsensusLoop consensusLoop,
            NodeSettings nodeSettings,
            NodeDeployments nodeDeployments,
            ILoggerFactory loggerFactory,
            IDateTimeProvider dateTimeProvider,
            ConsensusManager consensusManager,
            ConsensusStats consensusStats,
            ConsensusSettings consensusSettings,
            StakeChainStore stakeChain = null)
        {
            this.dBreezeCoinView    = dBreezeCoinView;
            this.consensusValidator = consensusValidator;
            this.chain             = chain;
            this.blockPuller       = blockPuller;
            this.coinView          = coinView;
            this.chainState        = chainState;
            this.connectionManager = connectionManager;
            this.nodeLifetime      = nodeLifetime;
            this.signals           = signals;
            this.network           = network;
            this.consensusLoop     = consensusLoop;
            this.nodeSettings      = nodeSettings;
            this.nodeDeployments   = nodeDeployments;
            this.stakeChain        = stakeChain;
            this.logger            = loggerFactory.CreateLogger(this.GetType().FullName);
            this.loggerFactory     = loggerFactory;
            this.dateTimeProvider  = dateTimeProvider;
            this.consensusManager  = consensusManager;
            this.consensusStats    = consensusStats;
            this.consensusSettings = consensusSettings;

            this.chainState.MaxReorgLength = this.network.Consensus.Option <PowConsensusOptions>().MaxReorgLength;
        }
예제 #3
0
        public ConsensusFeature(
            Network network,
            IChainState chainState,
            IConnectionManager connectionManager,
            Signals.Signals signals,
            IConsensusManager consensusManager,
            NodeDeployments nodeDeployments,
            ConsensusStats consensusStats)
        {
            this.chainState        = chainState;
            this.connectionManager = connectionManager;
            this.signals           = signals;
            this.consensusManager  = consensusManager;
            this.nodeDeployments   = nodeDeployments;
            this.consensusStats    = consensusStats;

            this.chainState.MaxReorgLength = network.Consensus.MaxReorgLength;
        }
        private Task RunLoop(CancellationToken cancellationToken)
        {
            try
            {
                var            stack = new CoinViewStack(this.coinView);
                CachedCoinView cache = stack.Find <CachedCoinView>();
                var            stats = new ConsensusStats(stack, this.coinView, this.consensusLoop, this.chainState, this.chain, this.connectionManager, this.loggerFactory);

                ChainedBlock lastTip = this.consensusLoop.Tip;
                foreach (BlockResult block in this.consensusLoop.Execute(cancellationToken))
                {
                    if (this.consensusLoop.Tip.FindFork(lastTip) != lastTip)
                    {
                        this.logger.LogInformation("Reorg detected, rewinding from '{0}' to '{1}'.", lastTip.HashBlock, this.consensusLoop.Tip);
                    }

                    lastTip = this.consensusLoop.Tip;

                    cancellationToken.ThrowIfCancellationRequested();

                    if (block.Error != null)
                    {
                        this.logger.LogError("Block rejected: {0}", block.Error.Message);

                        // Pull again.
                        this.consensusLoop.Puller.SetLocation(this.consensusLoop.Tip);

                        if (block.Error == ConsensusErrors.BadWitnessNonceSize)
                        {
                            this.logger.LogInformation("You probably need witness information, activating witness requirement for peers.");
                            this.connectionManager.AddDiscoveredNodesRequirement(NodeServices.NODE_WITNESS);
                            this.consensusLoop.Puller.RequestOptions(TransactionOptions.Witness);
                            continue;
                        }

                        // Set the PoW chain back to ConsensusLoop.Tip.
                        this.chain.SetTip(this.consensusLoop.Tip);

                        // Since ChainHeadersBehavior check PoW, MarkBlockInvalid can't be spammed.
                        this.logger.LogError("Marking block as invalid.");
                        this.chainState.MarkBlockInvalid(block.Block.GetHash());
                    }

                    if (block.Error == null)
                    {
                        this.chainState.HighestValidatedPoW = this.consensusLoop.Tip;

                        // We really want to flush if we are at the top of the chain.
                        // Otherwise, we just allow the flush to happen if it is needed.
                        bool forceFlush = this.chain.Tip.HashBlock == block.ChainedBlock?.HashBlock;
                        this.consensusLoop.FlushAsync(forceFlush).GetAwaiter().GetResult();

                        this.signals.SignalBlock(block.Block);
                    }

                    // TODO: Replace this with a signalling object.
                    if (stats.CanLog)
                    {
                        stats.Log();
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException)
                {
                    if (this.nodeLifetime.ApplicationStopping.IsCancellationRequested)
                    {
                        return(Task.FromException(ex));
                    }
                }

                // TODO Need to revisit unhandled exceptions in a way that any process can signal an exception has been
                // thrown so that the node and all the disposables can stop gracefully.
                this.logger.LogDebug("Exception occurred in consensus loop: {0}", ex.ToString());
                this.logger.LogCritical(new EventId(0), ex, "Consensus loop at Tip:{0} unhandled exception {1}", this.consensusLoop.Tip?.Height, ex.ToString());
                NLog.LogManager.Flush();
                throw;
            }

            return(Task.CompletedTask);
        }
        private void RunLoop()
        {
            try
            {
                var stack             = new CoinViewStack(this.coinView);
                var cache             = stack.Find <CachedCoinView>();
                var stats             = new ConsensusStats(stack, this.coinView, this.consensusLoop, this.chainState, this.chain, this.connectionManager, this.loggerFactory);
                var cancellationToken = this.nodeLifetime.ApplicationStopping;

                ChainedBlock lastTip = this.consensusLoop.Tip;
                foreach (var block in this.consensusLoop.Execute(cancellationToken))
                {
                    if (this.consensusLoop.Tip.FindFork(lastTip) != lastTip)
                    {
                        this.logger.LogInformation("Reorg detected, rewinding from " + lastTip.Height + " (" + lastTip.HashBlock + ") to " + this.consensusLoop.Tip.Height + " (" + this.consensusLoop.Tip.HashBlock + ")");
                    }
                    lastTip = this.consensusLoop.Tip;
                    cancellationToken.ThrowIfCancellationRequested();
                    if (block.Error != null)
                    {
                        this.logger.LogError("Block rejected: " + block.Error.Message);

                        //Pull again
                        this.consensusLoop.Puller.SetLocation(this.consensusLoop.Tip);

                        if (block.Error == ConsensusErrors.BadWitnessNonceSize)
                        {
                            this.logger.LogInformation("You probably need witness information, activating witness requirement for peers.");
                            this.connectionManager.AddDiscoveredNodesRequirement(NodeServices.NODE_WITNESS);
                            this.consensusLoop.Puller.RequestOptions(TransactionOptions.Witness);
                            continue;
                        }

                        //Set the PoW chain back to ConsensusLoop.Tip
                        this.chain.SetTip(this.consensusLoop.Tip);
                        //Since ChainHeadersBehavior check PoW, MarkBlockInvalid can't be spammed
                        this.logger.LogError("Marking block as invalid");
                        this.chainState.MarkBlockInvalid(block.Block.GetHash());
                    }

                    if (block.Error == null)
                    {
                        this.chainState.HighestValidatedPoW = this.consensusLoop.Tip;
                        if (this.chain.Tip.HashBlock == block.ChainedBlock?.HashBlock)
                        {
                            this.consensusLoop.FlushAsync();
                        }

                        this.signals.SignalBlock(block.Block);
                    }

                    // TODO: replace this with a signalling object
                    if (stats.CanLog)
                    {
                        stats.Log();
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException)
                {
                    if (this.nodeLifetime.ApplicationStopping.IsCancellationRequested)
                    {
                        return;
                    }
                }

                // TODO Need to revisit unhandled exceptions in a way that any process can signal an exception has been
                // thrown so that the node and all the disposables can stop gracefully.
                this.logger.LogCritical(new EventId(0), ex, "Consensus loop unhandled exception (Tip:" + this.consensusLoop.Tip?.Height + ")");
                throw;
            }
        }