public async Task <BlockExecutedSet> ExecuteBlockAsync(BlockHeader blockHeader,
                                                               IEnumerable <Transaction> nonCancellableTransactions, IEnumerable <Transaction> cancellableTransactions,
                                                               CancellationToken cancellationToken)
        {
            Logger.LogTrace("Entered ExecuteBlockAsync");
            var nonCancellable           = nonCancellableTransactions.ToList();
            var cancellable              = cancellableTransactions.ToList();
            var nonCancellableReturnSets =
                await _transactionExecutingService.ExecuteAsync(
                    new TransactionExecutingDto { BlockHeader = blockHeader, Transactions = nonCancellable },
                    CancellationToken.None);

            Logger.LogTrace("Executed non-cancellable txs");

            var returnSetCollection = new ExecutionReturnSetCollection(nonCancellableReturnSets);
            List <ExecutionReturnSet> cancellableReturnSets = new List <ExecutionReturnSet>();

            if (!cancellationToken.IsCancellationRequested && cancellable.Count > 0)
            {
                cancellableReturnSets = await _transactionExecutingService.ExecuteAsync(
                    new TransactionExecutingDto
                {
                    BlockHeader          = blockHeader,
                    Transactions         = cancellable,
                    PartialBlockStateSet = returnSetCollection.ToBlockStateSet()
                },
                    cancellationToken);

                returnSetCollection.AddRange(cancellableReturnSets);
                Logger.LogTrace("Executed cancellable txs");
            }

            var executedCancellableTransactions = new HashSet <Hash>(cancellableReturnSets.Select(x => x.TransactionId));
            var allExecutedTransactions         =
                nonCancellable.Concat(cancellable.Where(x => executedCancellableTransactions.Contains(x.GetHash())))
                .ToList();
            var blockStateSet =
                CreateBlockStateSet(blockHeader.PreviousBlockHash, blockHeader.Height, returnSetCollection);
            var block = await FillBlockAfterExecutionAsync(blockHeader, allExecutedTransactions, returnSetCollection,
                                                           blockStateSet);

            // set txn results
            var transactionResults = await SetTransactionResultsAsync(returnSetCollection, block.Header);

            // set blocks state
            blockStateSet.BlockHash = block.GetHash();
            Logger.LogTrace("Set block state set.");
            await _blockchainStateService.SetBlockStateSetAsync(blockStateSet);

            // handle execution cases
            await CleanUpReturnSetCollectionAsync(block.Header, returnSetCollection);

            return(new BlockExecutedSet
            {
                Block = block,
                TransactionMap = allExecutedTransactions.ToDictionary(p => p.GetHash(), p => p),
                TransactionResultMap = transactionResults.ToDictionary(p => p.TransactionId, p => p)
            });
        }
Exemple #2
0
        private BlockStateSet GetUpdatedBlockStateSet(ExecutionReturnSetCollection executionReturnSetCollection,
                                                      TransactionExecutingDto transactionExecutingDto)
        {
            var updatedPartialBlockStateSet = executionReturnSetCollection.ToBlockStateSet();

            if (transactionExecutingDto.PartialBlockStateSet != null)
            {
                var partialBlockStateSet = transactionExecutingDto.PartialBlockStateSet.Clone();
                foreach (var change in partialBlockStateSet.Changes)
                {
                    if (updatedPartialBlockStateSet.Changes.TryGetValue(change.Key, out _))
                    {
                        continue;
                    }
                    if (updatedPartialBlockStateSet.Deletes.Contains(change.Key))
                    {
                        continue;
                    }
                    updatedPartialBlockStateSet.Changes[change.Key] = change.Value;
                }

                foreach (var delete in partialBlockStateSet.Deletes)
                {
                    if (updatedPartialBlockStateSet.Deletes.Contains(delete))
                    {
                        continue;
                    }
                    if (updatedPartialBlockStateSet.Changes.TryGetValue(delete, out _))
                    {
                        continue;
                    }
                    updatedPartialBlockStateSet.Deletes.Add(delete);
                }
            }

            return(updatedPartialBlockStateSet);
        }