protected virtual async Task <Block> FillBlockAfterExecutionAsync(BlockHeader blockHeader, List <Transaction> transactions, ReturnSetCollection returnSetCollection) { Logger.LogTrace("Start block field filling after execution."); var bloom = new Bloom(); var blockStateSet = new BlockStateSet { BlockHeight = blockHeader.Height, PreviousHash = blockHeader.PreviousBlockHash }; foreach (var returnSet in returnSetCollection.Executed) { foreach (var change in returnSet.StateChanges) { blockStateSet.Changes[change.Key] = change.Value; blockStateSet.Deletes.Remove(change.Key); } foreach (var delete in returnSet.StateDeletes) { blockStateSet.Deletes.AddIfNotContains(delete.Key); blockStateSet.Changes.Remove(delete.Key); } bloom.Combine(new[] { new Bloom(returnSet.Bloom.ToByteArray()) }); } blockHeader.Bloom = ByteString.CopyFrom(bloom.Data); blockHeader.MerkleTreeRootOfWorldState = CalculateWorldStateMerkleTreeRoot(blockStateSet); var allExecutedTransactionIds = transactions.Select(x => x.GetHash()).ToList(); var orderedReturnSets = returnSetCollection.ToList().AsParallel() .OrderBy(d => allExecutedTransactionIds.IndexOf(d.TransactionId)).ToList(); blockHeader.MerkleTreeRootOfTransactionStatus = CalculateTransactionStatusMerkleTreeRoot(orderedReturnSets); blockHeader.MerkleTreeRootOfTransactions = CalculateTransactionMerkleTreeRoot(allExecutedTransactionIds); var blockHash = blockHeader.GetHashWithoutCache(); var blockBody = new BlockBody(); blockBody.TransactionIds.AddRange(allExecutedTransactionIds); var block = new Block { Header = blockHeader, Body = blockBody }; blockStateSet.BlockHash = blockHash; Logger.LogTrace("Set block state set."); await _blockchainStateService.SetBlockStateSetAsync(blockStateSet); Logger.LogTrace("Finish block field filling after execution."); return(block); }
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) }); }
private async Task <Block> FillBlockAfterExecutionAsync(BlockHeader blockHeader, List <Transaction> transactions, List <ExecutionReturnSet> blockExecutionReturnSet) { var bloom = new Bloom(); var blockStateSet = new BlockStateSet { BlockHeight = blockHeader.Height, PreviousHash = blockHeader.PreviousBlockHash }; foreach (var returnSet in blockExecutionReturnSet) { foreach (var change in returnSet.StateChanges) { blockStateSet.Changes[change.Key] = change.Value; } if (returnSet.Status == TransactionResultStatus.Mined) { bloom.Combine(new[] { new Bloom(returnSet.Bloom.ToByteArray()) }); } } blockHeader.Bloom = ByteString.CopyFrom(bloom.Data); blockHeader.MerkleTreeRootOfWorldState = CalculateWorldStateMerkleTreeRoot(blockStateSet); var allExecutedTransactionIds = transactions.Select(x => x.GetHash()).ToList(); blockExecutionReturnSet = blockExecutionReturnSet.AsParallel() .OrderBy(d => allExecutedTransactionIds.IndexOf(d.TransactionId)).ToList(); blockHeader.MerkleTreeRootOfTransactionStatus = CalculateTransactionStatusMerkleTreeRoot(blockExecutionReturnSet); blockHeader.MerkleTreeRootOfTransactions = CalculateTransactionMerkleTreeRoot(allExecutedTransactionIds); var blockHash = blockHeader.GetHashWithoutCache(); var blockBody = new BlockBody(); blockBody.TransactionIds.AddRange(allExecutedTransactionIds); var block = new Block { Header = blockHeader, Body = blockBody }; blockStateSet.BlockHash = blockHash; await _blockchainStateService.SetBlockStateSetAsync(blockStateSet); return(block); }