コード例 #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);
        }
コード例 #2
0
        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);
        }
コード例 #3
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 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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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());
        }
コード例 #6
0
        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);
        }