Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }