public async Task <List <ExecutionReturnSet> > ExecuteAsync(TransactionExecutingDto transactionExecutingDto, CancellationToken cancellationToken) { Logger.LogTrace("Entered parallel ExecuteAsync."); var transactions = transactionExecutingDto.Transactions.ToList(); var blockHeader = transactionExecutingDto.BlockHeader; var chainContext = new ChainContext { BlockHash = blockHeader.PreviousBlockHash, BlockHeight = blockHeader.Height - 1 }; var groupedTransactions = await _grouper.GroupAsync(chainContext, transactions); var returnSets = new List <ExecutionReturnSet>(); var nonParallelizableReturnSets = await _planTransactionExecutingService.ExecuteAsync( new TransactionExecutingDto { BlockHeader = blockHeader, Transactions = groupedTransactions.NonParallelizables, PartialBlockStateSet = transactionExecutingDto.PartialBlockStateSet }, cancellationToken); Logger.LogTrace("Merged results from non-parallelizables."); returnSets.AddRange(nonParallelizableReturnSets); var returnSetCollection = new ReturnSetCollection(returnSets); var updatedPartialBlockStateSet = GetUpdatedBlockStateSet(returnSetCollection, transactionExecutingDto); var tasks = groupedTransactions.Parallelizables.Select( txns => ExecuteAndPreprocessResult(new TransactionExecutingDto { BlockHeader = blockHeader, Transactions = txns, PartialBlockStateSet = updatedPartialBlockStateSet, }, cancellationToken)); var results = await Task.WhenAll(tasks); Logger.LogTrace("Executed parallelizables."); returnSets.AddRange(MergeResults(results, out var conflictingSets)); Logger.LogTrace("Merged results from parallelizables."); var transactionWithoutContractReturnSets = await ProcessTransactionsWithoutContract( groupedTransactions.TransactionsWithoutContract, blockHeader); Logger.LogTrace("Merged results from transactions without contract."); returnSets.AddRange(transactionWithoutContractReturnSets); if (conflictingSets.Count > 0 && returnSets.Count + conflictingSets.Count == transactionExecutingDto.Transactions.Count()) { await ProcessConflictingSetsAsync(conflictingSets, blockHeader); returnSets.AddRange(conflictingSets); } return(returnSets); }
private async Task <List <ExecutionReturnSet> > ExecuteNonParallelizableTransactionsAsync(List <Transaction> transactions, BlockHeader blockHeader, BlockStateSet blockStateSet, CancellationToken cancellationToken) { var nonParallelizableReturnSets = await _planTransactionExecutingService.ExecuteAsync( new TransactionExecutingDto { Transactions = transactions, BlockHeader = blockHeader, PartialBlockStateSet = blockStateSet }, cancellationToken); Logger.LogTrace("Merged results from non-parallelizables."); return(nonParallelizableReturnSets); }
public async Task <bool> ValidateTransactionAsync(Transaction transaction, IChainContext chainContext) { if (!_transactionOptions.EnableTransactionExecutionValidation) { return(true); } var executionReturnSets = await _plainTransactionExecutingService.ExecuteAsync(new TransactionExecutingDto() { Transactions = new[] { transaction }, BlockHeader = new BlockHeader { PreviousBlockHash = chainContext.BlockHash, Height = chainContext.BlockHeight + 1, Time = TimestampHelper.GetUtcNow(), } }, CancellationToken.None); var executionValidationResult = executionReturnSets.FirstOrDefault()?.Status == TransactionResultStatus.Mined; if (!executionValidationResult) { var transactionId = transaction.GetHash(); // TODO: Consider to remove TransactionExecutionValidationFailedEvent. await LocalEventBus.PublishAsync(new TransactionExecutionValidationFailedEvent { TransactionId = transactionId }); await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent { TransactionId = transactionId, TransactionResultStatus = TransactionResultStatus.NodeValidationFailed, Error = executionReturnSets.FirstOrDefault()?.TransactionResult?.Error ?? string.Empty }); } return(executionValidationResult); }