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); }
public async Task TokenTransferParallelTest() { var chain = await _blockchainService.GetChainAsync(); var tokenAmount = _transactionCount / _groupCount; var(prepareTransactions, keyPairs) = await _parallelTestHelper.PrepareTokenForParallel(_groupCount, tokenAmount); await _parallelTestHelper.BroadcastTransactions(prepareTransactions); var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, prepareTransactions); block = await _blockExecutingService.ExecuteBlockAsync(block.Header, prepareTransactions); var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); var cancellableTransactions = await _parallelTestHelper.GenerateTransactionsWithoutConflict(keyPairs, tokenAmount); var allTransaction = systemTransactions.Concat(cancellableTransactions).ToList(); await _parallelTestHelper.BroadcastTransactions(allTransaction); var groupedTransactions = await _grouper.GroupAsync( new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, cancellableTransactions); groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); groupedTransactions.NonParallelizables.Count.ShouldBe(0); block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransaction); block = await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, cancellableTransactions, CancellationToken.None); var codeRemarks = await _codeRemarksManager.GetCodeRemarksAsync(Hash.FromRawBytes(_parallelTestHelper.TokenContractCode)); codeRemarks.ShouldBeNull(); groupedTransactions = await _grouper.GroupAsync( new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, cancellableTransactions); groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); groupedTransactions.NonParallelizables.Count.ShouldBe(0); block.TransactionIds.Count().ShouldBe(allTransaction.Count); }
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 mergeResult = await ExecuteParallelizableTransactionsAsync(groupedTransactions.Parallelizables, blockHeader, transactionExecutingDto.PartialBlockStateSet, cancellationToken); returnSets.AddRange(mergeResult.ExecutionReturnSets); var conflictingSets = mergeResult.ConflictingReturnSets; var returnSetCollection = new ExecutionReturnSetCollection(returnSets); var updatedPartialBlockStateSet = GetUpdatedBlockStateSet(returnSetCollection, transactionExecutingDto); var nonParallelizableReturnSets = await ExecuteNonParallelizableTransactionsAsync(groupedTransactions.NonParallelizables, blockHeader, updatedPartialBlockStateSet, cancellationToken); returnSets.AddRange(nonParallelizableReturnSets); var transactionWithoutContractReturnSets = ProcessTransactionsWithoutContract( groupedTransactions.TransactionsWithoutContract); Logger.LogTrace("Merged results from transactions without contract."); returnSets.AddRange(transactionWithoutContractReturnSets); if (conflictingSets.Count > 0 && returnSets.Count + conflictingSets.Count == transactionExecutingDto.Transactions.Count()) { ProcessConflictingSets(conflictingSets); returnSets.AddRange(conflictingSets); } return(returnSets); }
public async Task <List <ExecutionReturnSet> > ExecuteAsync(TransactionExecutingDto transactionExecutingDto, CancellationToken cancellationToken, bool throwException = false) { Logger.LogTrace($"Entered parallel ExecuteAsync."); var transactions = transactionExecutingDto.Transactions.ToList(); var blockHeader = transactionExecutingDto.BlockHeader; // TODO: Is it reasonable to allow throwing exception here // if (throwException) // { // throw new NotSupportedException( // $"Throwing exception is not supported in {nameof(LocalParallelTransactionExecutingService)}."); // } 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 _plainExecutingService.ExecuteAsync( new TransactionExecutingDto { BlockHeader = blockHeader, Transactions = groupedTransactions.NonParallelizables, PartialBlockStateSet = transactionExecutingDto.PartialBlockStateSet }, cancellationToken, throwException); Logger.LogTrace("Merged results from non-parallelizables."); returnSets.AddRange(nonParallelizableReturnSets); var returnSetCollection = new ReturnSetCollection(returnSets); var updatedPartialBlockStateSet = returnSetCollection.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); } } var tasks = groupedTransactions.Parallelizables.Select( txns => ExecuteAndPreprocessResult(new TransactionExecutingDto { BlockHeader = blockHeader, Transactions = txns, PartialBlockStateSet = updatedPartialBlockStateSet, }, cancellationToken, throwException)); var results = await Task.WhenAll(tasks); Logger.LogTrace("Executed parallelizables."); returnSets.AddRange(MergeResults(results, out var conflictingSets).Item1); 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) { await EventBus.PublishAsync(new ConflictingTransactionsFoundInParallelGroupsEvent( blockHeader.Height - 1, blockHeader.PreviousBlockHash, returnSets, conflictingSets )); await ProcessConflictingSetsAsync(conflictingSets, returnSets, blockHeader); } return(returnSets); }
public async Task <List <ExecutionReturnSet> > ExecuteAsync(TransactionExecutingDto transactionExecutingDto, CancellationToken cancellationToken, bool throwException = false) { Logger.LogTrace($"Entered parallel ExecuteAsync."); var transactions = transactionExecutingDto.Transactions.ToList(); var blockHeader = transactionExecutingDto.BlockHeader; // TODO: Is it reasonable to allow throwing exception here // if (throwException) // { // throw new NotSupportedException( // $"Throwing exception is not supported in {nameof(LocalParallelTransactionExecutingService)}."); // } var chainContext = new ChainContext { BlockHash = blockHeader.PreviousBlockHash, BlockHeight = blockHeader.Height - 1 }; var groupedTransactions = await _grouper.GroupAsync(chainContext, transactions); var tasks = groupedTransactions.Parallelizables.AsParallel().Select( txns => ExecuteAndPreprocessResult(new TransactionExecutingDto { BlockHeader = blockHeader, Transactions = txns, PartialBlockStateSet = transactionExecutingDto.PartialBlockStateSet }, cancellationToken, throwException)); var results = await Task.WhenAll(tasks); Logger.LogTrace("Executed parallelizables."); var returnSets = MergeResults(results, out var conflictingSets).Item1; var returnSetCollection = new ReturnSetCollection(returnSets); var updatedPartialBlockStateSet = returnSetCollection.ToBlockStateSet(); updatedPartialBlockStateSet.MergeFrom(transactionExecutingDto.PartialBlockStateSet?.Clone() ?? new BlockStateSet()); Logger.LogTrace("Merged results from parallelizables."); var nonParallelizableReturnSets = await _plainExecutingService.ExecuteAsync( new TransactionExecutingDto { BlockHeader = blockHeader, Transactions = groupedTransactions.NonParallelizables, PartialBlockStateSet = updatedPartialBlockStateSet }, cancellationToken, throwException); Logger.LogTrace("Merged results from non-parallelizables."); returnSets.AddRange(nonParallelizableReturnSets); var transactionWithoutContractReturnSets = await ProcessTransactionsWithoutContract( groupedTransactions.TransactionsWithoutContract, blockHeader); Logger.LogTrace("Merged results from transactions without contract."); returnSets.AddRange(transactionWithoutContractReturnSets); if (conflictingSets.Count > 0) { await EventBus.PublishAsync(new ConflictingTransactionsFoundInParallelGroupsEvent( blockHeader.Height - 1, blockHeader.PreviousBlockHash, returnSets, conflictingSets )); } var transactionOrder = transactions.Select(t => t.GetHash()).ToList(); return(returnSets.AsParallel().OrderBy(d => transactionOrder.IndexOf(d.TransactionId)).ToList()); }
public async Task TokenTransferParallelTest() { var chain = await _blockchainService.GetChainAsync(); var tokenAmount = _transactionCount / _groupCount; var(prepareTransactions, keyPairs) = await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 1000000000); await _parallelTestHelper.BroadcastTransactions(prepareTransactions); var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, prepareTransactions); block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, prepareTransactions)).Block; await _blockchainService.AddBlockAsync(block); await _blockAttachService.AttachBlockAsync(block); var systemTransactions = await _parallelTestHelper.GenerateTransferTransactions(1); var cancellableTransactions = await _parallelTestHelper.GenerateTransactionsWithoutConflictAsync(keyPairs, tokenAmount); var allTransaction = systemTransactions.Concat(cancellableTransactions).ToList(); await _parallelTestHelper.BroadcastTransactions(allTransaction); var groupedTransactions = await _grouper.GroupAsync( new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, cancellableTransactions); groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); groupedTransactions.NonParallelizables.Count.ShouldBe(0); block = _parallelTestHelper.GenerateBlock(block.GetHash(), block.Height, allTransaction); block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, systemTransactions, cancellableTransactions, CancellationToken.None)).Block; await _blockchainService.AddBlockAsync(block); await _blockAttachService.AttachBlockAsync(block); var chainContext = new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }; var tokenContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, TokenSmartContractAddressNameProvider.StringName); var nonparallelContractCode = await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext, tokenContractAddress); nonparallelContractCode.ShouldBeNull(); groupedTransactions = await _grouper.GroupAsync( new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height }, cancellableTransactions); groupedTransactions.Parallelizables.Count.ShouldBe(_groupCount); groupedTransactions.NonParallelizables.Count.ShouldBe(0); block.TransactionIds.Count().ShouldBe(allTransaction.Count); }