/// <inheritdoc /> /// <summary> /// Mine process. /// </summary> /// <returns></returns> public async Task <IBlock> Mine() { try { var stopwatch = new Stopwatch(); stopwatch.Start(); await GenerateTransactionWithParentChainBlockInfo(); var txs = await _txHub.GetReceiptsOfExecutablesAsync(); var txGrp = txs.GroupBy(tr => tr.IsSystemTxn).ToDictionary(x => x.Key, x => x.ToList()); var traces = new List <TransactionTrace>(); //ParentChainBlockInfo pcb = null; if (txGrp.TryGetValue(true, out var sysRcpts)) { var sysTxs = sysRcpts.Select(x => x.Transaction).ToList(); _txFilter.Execute(sysTxs); _logger?.Trace($"Start executing {sysTxs.Count} system transactions."); traces = await ExecuteTransactions(sysTxs, true); _logger?.Trace($"Finish executing {sysTxs.Count} system transactions."); // need check result of cross chain transaction //FindCrossChainInfo(sysTxs, traces, out pcb); } if (txGrp.TryGetValue(false, out var regRcpts)) { var regTxs = regRcpts.Select(x => x.Transaction).ToList(); _logger?.Trace($"Start executing {regTxs.Count} regular transactions."); traces.AddRange(await ExecuteTransactions(regTxs)); _logger?.Trace($"Finish executing {regTxs.Count} regular transactions."); } ExtractTransactionResults(traces, out var results); // generate block var block = await GenerateBlockAsync(results); _logger?.Info($"Generated block {block.BlockHashToHex} at height {block.Header.Index} with {block.Body.TransactionsCount} txs."); // validate block before appending var chainContext = await _chainContextService.GetChainContextAsync(Hash.LoadHex(ChainConfig.Instance.ChainId)); var blockValidationResult = await _blockValidationService.ValidateBlockAsync(block, chainContext); if (blockValidationResult != BlockValidationResult.Success) { _logger?.Warn($"Found the block generated before invalid: {blockValidationResult}."); return(null); } // append block await _blockChain.AddBlocksAsync(new List <IBlock> { block }); MessageHub.Instance.Publish(new BlockMined(block)); // insert to db Update(results, block); /*if (pcb != null) * { * await _chainManagerBasic.UpdateCurrentBlockHeightAsync(pcb.ChainId, pcb.Height); * }*/ await _txHub.OnNewBlock((Block)block); MessageHub.Instance.Publish(new BlockMinedAndStored(block)); stopwatch.Stop(); _logger?.Info($"Generate block {block.BlockHashToHex} at height {block.Header.Index} " + $"with {block.Body.TransactionsCount} txs, duration {stopwatch.ElapsedMilliseconds} ms."); return(block); } catch (Exception e) { _logger?.Error(e, "Mining failed with exception."); return(null); } }