private async Task <Block?> TryProduceBlock(BlockHeader?parentHeader, CancellationToken cancellationToken = default) { Task <Block?>[] produceTasks = new Task <Block?> [_blockProducers.Length]; for (int i = 0; i < _blockProducers.Length; i++) { T blockProducerInfo = _blockProducers[i]; produceTasks[i] = blockProducerInfo.BlockProductionTrigger.BuildBlock(parentHeader, cancellationToken, blockProducerInfo.BlockTracer); } IEnumerable <(Block?Block, T BlockProducer)> blocksWithProducers; try { Block?[] blocks = await Task.WhenAll(produceTasks); blocksWithProducers = blocks.Zip(_blockProducers); } catch (OperationCanceledException) { blocksWithProducers = produceTasks .Zip(_blockProducers) .Where(t => t.First.IsCompletedSuccessfully) .Select(t => (t.First.Result, t.Second)); } Block?bestBlock = _bestBlockPicker.GetBestBlock(blocksWithProducers); if (bestBlock is not null) { if (produceTasks.Count(t => t.IsCompletedSuccessfully && t.Result is not null) > 1) { if (_logger.IsInfo) { _logger.Info($"Picked block {bestBlock} to be included to the chain."); } } BlockProduced?.Invoke(this, new BlockEventArgs(bestBlock)); } return(bestBlock); }
private void OnBlockProduced(object?sender, BlockEventArgs e) { BlockProduced?.Invoke(this, e); }