Пример #1
0
        public void SetUp()
        {
            _stepDelay = TimeSpan.FromMilliseconds(20);

            _pendingTxSelector   = Substitute.For <IPendingTxSelector>();
            _blockchainProcessor = Substitute.For <IBlockchainProcessor>();
            _sealer               = Substitute.For <ISealer>();
            _blockTree            = Substitute.For <IBlockTree>();
            _blockProcessingQueue = Substitute.For <IBlockProcessingQueue>();
            _stateProvider        = Substitute.For <IStateProvider>();
            _timestamper          = Substitute.For <ITimestamper>();
            _auRaStepCalculator   = Substitute.For <IAuRaStepCalculator>();
            _auraConfig           = Substitute.For <IAuraConfig>();
            _nodeAddress          = TestItem.AddressA;
            _auRaBlockProducer    = new AuRaBlockProducer(
                _pendingTxSelector,
                _blockchainProcessor,
                _stateProvider,
                _sealer,
                _blockTree,
                _blockProcessingQueue,
                _timestamper,
                LimboLogs.Instance, _auRaStepCalculator, _auraConfig, _nodeAddress);

            _auraConfig.ForceSealing.Returns(true);
            _pendingTxSelector.SelectTransactions(Arg.Any <long>()).Returns(Array.Empty <Transaction>());
            _sealer.CanSeal(Arg.Any <long>(), Arg.Any <Keccak>()).Returns(true);
            _sealer.SealBlock(Arg.Any <Block>(), Arg.Any <CancellationToken>()).Returns(c => Task.FromResult(c.Arg <Block>()));
            _blockProcessingQueue.IsEmpty.Returns(true);
            _auRaStepCalculator.TimeToNextStep.Returns(_stepDelay);
            _blockTree.BestKnownNumber.Returns(1);
            _blockTree.Head.Returns(Build.A.BlockHeader.WithAura(10, Bytes.Empty).TestObject);
            _blockchainProcessor.Process(Arg.Any <Block>(), ProcessingOptions.ProducingBlock, Arg.Any <IBlockTracer>()).Returns(c => c.Arg <Block>());
        }
Пример #2
0
        private Task <bool> ProduceNewBlock(BlockHeader parent, CancellationToken token)
        {
            _stateProvider.StateRoot = parent.StateRoot;
            Block block = PrepareBlock(parent);

            if (PreparedBlockCanBeMined(block))
            {
                var processedBlock = ProcessPreparedBlock(block);
                if (processedBlock == null)
                {
                    if (Logger.IsError)
                    {
                        Logger.Error("Block prepared by block producer was rejected by processor.");
                    }
                }
                else
                {
                    return(_sealer.SealBlock(processedBlock, token).ContinueWith((Func <Task <Block>, bool>)(t =>
                    {
                        if (t.IsCompletedSuccessfully)
                        {
                            if (t.Result != null)
                            {
                                if (Logger.IsInfo)
                                {
                                    Logger.Info($"Sealed block {t.Result.ToString(Block.Format.HashNumberDiffAndTx)}");
                                }
                                BlockTree.SuggestBlock(t.Result);
                                return true;
                            }
                            else
                            {
                                if (Logger.IsInfo)
                                {
                                    Logger.Info($"Failed to seal block {processedBlock.ToString(Block.Format.HashNumberDiffAndTx)} (null seal)");
                                }
                            }
                        }
                        else if (t.IsFaulted)
                        {
                            if (Logger.IsError)
                            {
                                Logger.Error("Mining failed", t.Exception);
                            }
                        }
                        else if (t.IsCanceled)
                        {
                            if (Logger.IsInfo)
                            {
                                Logger.Info($"Sealing block {processedBlock.Number} cancelled");
                            }
                        }

                        return false;
                    }), token));
                }
            }

            return(Task.FromResult(false));
        }
Пример #3
0
        protected ValueTask ProduceNewBlock(BlockHeader parent, CancellationToken token)
        {
            _stateProvider.StateRoot = parent.StateRoot;

            Block block = PrepareBlock(parent);

            if (PreparedBlockCanBeMined(block))
            {
                Block processedBlock = Processor.Process(block, ProcessingOptions.ProducingBlock, NullBlockTracer.Instance);
                if (processedBlock == null)
                {
                    if (Logger.IsError)
                    {
                        Logger.Error("Block prepared by block producer was rejected by processor.");
                    }
                }
                else
                {
                    _sealer.SealBlock(processedBlock, token).ContinueWith(t =>
                    {
                        if (t.IsCompletedSuccessfully)
                        {
                            if (t.Result != null)
                            {
                                if (Logger.IsInfo)
                                {
                                    Logger.Info($"Sealed block {t.Result.ToString(Block.Format.HashNumberDiffAndTx)}");
                                }
                                BlockTree.SuggestBlock(t.Result);
                            }
                            else
                            {
                                if (Logger.IsInfo)
                                {
                                    Logger.Info($"Failed to seal block {processedBlock.ToString(Block.Format.HashNumberDiffAndTx)} (null seal)");
                                }
                            }
                        }
                        else if (t.IsFaulted)
                        {
                            if (Logger.IsError)
                            {
                                Logger.Error("Mining failed", t.Exception);
                            }
                        }
                        else if (t.IsCanceled)
                        {
                            if (Logger.IsInfo)
                            {
                                Logger.Info($"Sealing block {processedBlock.Number} cancelled");
                            }
                        }
                    }, token);
                }
            }

            return(default);
Пример #4
0
        private void OnBlockProcessorQueueEmpty(object sender, EventArgs e)
        {
            CancellationToken token;

            lock (_syncToken)
            {
                _cancellationTokenSource = new CancellationTokenSource();
                token = _cancellationTokenSource.Token;
            }

            Block block = PrepareBlock();

            if (block == null)
            {
                if (_logger.IsError)
                {
                    _logger.Error("Failed to prepare block for mining.");
                }
                return;
            }

            Block processedBlock = _processor.Process(block, ProcessingOptions.NoValidation | ProcessingOptions.ReadOnlyChain | ProcessingOptions.WithRollback, NullBlockTracer.Instance);

            _sealer.SealBlock(processedBlock, token).ContinueWith(t =>
            {
                if (t.IsCompletedSuccessfully)
                {
                    _blockTree.SuggestBlock(t.Result);
                }
                else if (t.IsFaulted)
                {
                    _logger.Error("Mining failer", t.Exception);
                }
                else if (t.IsCanceled)
                {
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Mining block {processedBlock.ToString(Block.Format.FullHashAndNumber)} cancelled");
                    }
                }
            }, token);
        }
Пример #5
0
        private void ConsumeSignal()
        {
            foreach (Block signal in _signalsQueue.GetConsumingEnumerable(_cancellationTokenSource.Token))
            {
                Block parentBlock = signal;
                while (_signalsQueue.TryTake(out Block nextSignal))
                {
                    if (parentBlock.Number <= nextSignal.Number)
                    {
                        parentBlock = nextSignal;
                    }
                }

                try
                {
                    Block block = PrepareBlock(parentBlock);
                    if (block == null)
                    {
                        if (_logger.IsTrace)
                        {
                            _logger.Trace("Skipping block production or block production failed");
                        }
                        continue;
                    }

                    if (_logger.IsInfo)
                    {
                        _logger.Info($"Processing prepared block {block.Number}");
                    }
                    Block processedBlock = _processor.Process(block, ProcessingOptions.NoValidation | ProcessingOptions.ReadOnlyChain | ProcessingOptions.WithRollback, NullBlockTracer.Instance);
                    if (processedBlock == null)
                    {
                        if (_logger.IsInfo)
                        {
                            _logger.Info($"Prepared block has lost the race");
                        }
                        continue;
                    }

                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Sealing prepared block {processedBlock.Number}");
                    }

                    _sealer.SealBlock(processedBlock, _cancellationTokenSource.Token).ContinueWith(t =>
                    {
                        if (t.IsCompletedSuccessfully)
                        {
                            if (t.Result != null)
                            {
                                if (_logger.IsInfo)
                                {
                                    _logger.Info($"Sealed block {t.Result.ToString(Block.Format.HashNumberDiffAndTx)}");
                                }
                                _scheduledBlock = t.Result;
                            }
                            else
                            {
                                if (_logger.IsInfo)
                                {
                                    _logger.Info($"Failed to seal block {processedBlock.ToString(Block.Format.HashNumberDiffAndTx)} (null seal)");
                                }
                            }
                        }
                        else if (t.IsFaulted)
                        {
                            if (_logger.IsError)
                            {
                                _logger.Error("Mining failed", t.Exception);
                            }
                        }
                        else if (t.IsCanceled)
                        {
                            if (_logger.IsInfo)
                            {
                                _logger.Info($"Sealing block {processedBlock.Number} cancelled");
                            }
                        }
                    }, _cancellationTokenSource.Token);
                }
                catch (Exception e)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error($"Block producer could not produce block on top of {parentBlock.ToString(Block.Format.Short)}", e);
                    }
                }
            }
        }
Пример #6
0
        private void ProduceNewBlock(BlockHeader parentHeader)
        {
            _stateProvider.StateRoot = parentHeader.StateRoot;

            Block block = PrepareBlock(parentHeader);

            if (block == null)
            {
                if (_logger.IsError)
                {
                    _logger.Error("Failed to prepare block for mining.");
                }
                return;
            }

            if (block.Transactions.Length == 0)
            {
                if (_config.ForceSealing)
                {
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Force sealing block {block.Number} without transactions.");
                    }
                }
                else
                {
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Skip seal block {block.Number}, no transactions pending.");
                    }
                    return;
                }
            }

            Block processedBlock = _processor.Process(block, ProcessingOptions.NoValidation | ProcessingOptions.ReadOnlyChain | ProcessingOptions.WithRollback, NullBlockTracer.Instance);

            if (_logger.IsInfo)
            {
                _logger.Info($"Mined a DEV block {processedBlock.ToString(Block.Format.FullHashAndNumber)} State Root: {processedBlock.StateRoot}");
            }

            if (processedBlock == null)
            {
                if (_logger.IsError)
                {
                    _logger.Error("Block prepared by block producer was rejected by processor");
                }
                return;
            }

            _sealer.SealBlock(processedBlock, _cancellationTokenSource.Token).ContinueWith(t =>
            {
                if (t.IsCompletedSuccessfully)
                {
                    if (t.Result != null)
                    {
                        if (_logger.IsInfo)
                        {
                            _logger.Info($"Sealed block {t.Result.ToString(Block.Format.HashNumberDiffAndTx)}");
                        }
                        _blockTree.SuggestBlock(t.Result);
                    }
                    else
                    {
                        if (_logger.IsInfo)
                        {
                            _logger.Info($"Failed to seal block {processedBlock.ToString(Block.Format.HashNumberDiffAndTx)} (null seal)");
                        }
                    }
                }
                else if (t.IsFaulted)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error("Mining failed", t.Exception);
                    }
                }
                else if (t.IsCanceled)
                {
                    if (_logger.IsInfo)
                    {
                        _logger.Info($"Sealing block {processedBlock.Number} cancelled");
                    }
                }
            }, _cancellationTokenSource.Token);
        }
Пример #7
0
 protected virtual Task <Block> SealBlock(Block block, BlockHeader parent, CancellationToken token) => _sealer.SealBlock(block, token);
Пример #8
0
 public Task <Block> SealBlock(Block block, CancellationToken cancellationToken) =>
 _sealer.SealBlock(block, cancellationToken);