private async Task <List <TransactionWithResourceInfo> > FindContractOfWrongResourcesAsync(IChainContext chainContext,
                                                                                                   List <ExecutionReturnSet> returnSets)
        {
            var transactionIds = returnSets.Select(rs => rs.TransactionId);
            var transactions   = await _blockchainService.GetTransactionsAsync(transactionIds);

            var txnWithResources =
                await _resourceExtractionService.GetResourcesAsync(chainContext, transactions, CancellationToken.None);

            txnWithResources =
                txnWithResources.Where(t => t.TransactionResourceInfo.ParallelType == ParallelType.Parallelizable);

            var txnWithResourceList   = txnWithResources.ToList();
            var readOnlyKeys          = txnWithResourceList.GetReadOnlyPaths().Select(p => p.ToStateKey()).ToList();
            var returnSetLookup       = returnSets.ToDictionary(rs => rs.TransactionId, rs => rs);
            var wrongTxnWithResources = new List <TransactionWithResourceInfo>();

            foreach (var txnWithResource in txnWithResourceList)
            {
                var extracted = new HashSet <string>(txnWithResource.TransactionResourceInfo.WritePaths
                                                     .Concat(txnWithResource.TransactionResourceInfo.ReadPaths).Select(p => p.ToStateKey()));
                extracted.ExceptWith(readOnlyKeys);
                var actual = GetKeys(returnSetLookup[txnWithResource.Transaction.GetHash()]);
                actual.ExceptWith(extracted);
                if (actual.Count == 0)
                {
                    continue;
                }
                Logger.LogDebug($"Conflict keys:{string.Join(";", actual)}");
                wrongTxnWithResources.Add(txnWithResource);
            }

            return(wrongTxnWithResources);
        }
        private async Task <List <Transaction> > FindContractOfWrongResourcesAsync(IChainContext chainContext,
                                                                                   List <ExecutionReturnSet> returnSets)
        {
            var transactionIds = returnSets.Select(rs => rs.TransactionId);
            var transactions   = await _blockchainService.GetTransactionsAsync(transactionIds);

            var txnWithResources =
                await _resourceExtractionService.GetResourcesAsync(chainContext, transactions, CancellationToken.None);

            var returnSetLookup = returnSets.ToDictionary(rs => rs.TransactionId, rs => rs);
            var wrongTxns       = new List <Transaction>();

            foreach (var txnWithResource in txnWithResources)
            {
                var extracted = new HashSet <string>(txnWithResource.Item2.Paths.Select(p => p.ToStateKey()));
                var actual    = GetKeys(returnSetLookup[txnWithResource.Item1.GetHash()]);
                actual.ExceptWith(extracted);
                if (actual.Count > 0)
                {
                    Logger.LogWarning($"Conflict keys:{string.Join(";", actual)}");
                    wrongTxns.Add(txnWithResource.Item1);
                }
            }

            return(wrongTxns);
        }
Exemple #3
0
        public async Task <GroupedTransactions> GroupAsync(IChainContext chainContext, List <Transaction> transactions)
        {
            Logger.LogTrace("Entered GroupAsync");

            var toBeGrouped = GetTransactionsToBeGrouped(transactions, out var groupedTransactions);

            using (var cts = new CancellationTokenSource(_options.GroupingTimeOut))
            {
                var parallelizables = new List <TransactionWithResourceInfo>();

                Logger.LogTrace("Extracting resources for transactions.");
                var txsWithResources =
                    await _resourceExtractionService.GetResourcesAsync(chainContext, toBeGrouped, cts.Token);

                Logger.LogTrace("Completed resource extraction.");

                foreach (var twr in txsWithResources)
                {
                    if (twr.TransactionResourceInfo.ParallelType == ParallelType.InvalidContractAddress)
                    {
                        groupedTransactions.TransactionsWithoutContract.Add(twr.Transaction);
                        continue;
                    }

                    // If timed out at this point, return all transactions as non-parallelizable
                    if (cts.IsCancellationRequested)
                    {
                        groupedTransactions.NonParallelizables.Add(twr.Transaction);
                        continue;
                    }

                    if (twr.TransactionResourceInfo.ParallelType == ParallelType.NonParallelizable)
                    {
                        groupedTransactions.NonParallelizables.Add(twr.Transaction);
                        continue;
                    }

                    if (twr.TransactionResourceInfo.Paths.Count == 0)
                    {
                        // groups.Add(new List<Transaction>() {twr.Item1}); // Run in their dedicated group
                        groupedTransactions.NonParallelizables.Add(twr.Transaction);
                        continue;
                    }

                    parallelizables.Add(twr);
                }

                groupedTransactions.Parallelizables.AddRange(GroupParallelizables(parallelizables));

                Logger.LogTrace("Completed transaction grouping.");
            }

            Logger.LogDebug($"From {transactions.Count} transactions, grouped {groupedTransactions.Parallelizables.Sum(p=>p.Count)} txs into " +
                            $"{groupedTransactions.Parallelizables.Count} groups, left " +
                            $"{groupedTransactions.NonParallelizables.Count} as non-parallelizable transactions.");

            return(groupedTransactions);
        }