public async Task <List <TransactionTrace> > ExecuteAsync(List <Transaction> transactions, Hash chainId, CancellationToken cancellationToken, Hash disambiguationHash = null) { var chainContext = await _chainContextService.GetChainContextAsync(chainId); var stateCache = new Dictionary <DataPath, StateCache>(); var traces = new List <TransactionTrace>(); foreach (var transaction in transactions) { var trace = await ExecuteOneAsync(0, transaction, chainId, chainContext, stateCache, cancellationToken); //Console.WriteLine($"{transaction.GetHash().ToHex()} : {trace.ExecutionStatus.ToString()}"); if (trace.IsSuccessful() && trace.ExecutionStatus == ExecutionStatus.ExecutedButNotCommitted) { //Console.WriteLine($"tx executed successfully: {transaction.GetHash().ToHex()}"); await trace.CommitChangesAsync(_stateStore); // await _stateDictator.ApplyCachedDataAction(bufferedStateUpdates); // foreach (var kv in bufferedStateUpdates) // { // stateCache[kv.Key] = kv.Value; // } } if (_transactionTraceManager != null) { // Will be null only in tests await _transactionTraceManager.AddTransactionTraceAsync(trace, disambiguationHash); } traces.Add(trace); if (cancellationToken.IsCancellationRequested) { break; } } // await _stateDictator.ApplyCachedDataAction(stateCache); return(traces); }
/// <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); } }