Beispiel #1
0
        private async Task <JobExecutionStatus> RunJob(JobExecutionRequest request)
        {
/*
 * Temporarily disabled.
 * TODO: https://github.com/AElfProject/AElf/issues/338
 *          _state = State.Running;
 */
            var result = await _proxyExecutingService.ExecuteAsync(request.Transactions, request.ChainId, _cancellationTokenSource.Token);

            request.ResultCollector?.Tell(new TransactionTraceMessage(request.RequestId, result));

            // TODO: What if actor died in the middle

            var retMsg = new JobExecutionStatus(request.RequestId, JobExecutionStatus.RequestStatus.Completed);

            // TODO: tell requestor and router about the worker complete job,and set to idle state.

/*
 * Temporarily disabled.
 * TODO: https://github.com/AElfProject/AElf/issues/338
 *          request.ResultCollector?.Tell(retMsg);
 *          request.Router?.Tell(retMsg);
 */
            _servingRequestId = -1;

/*
 * Temporarily disabled.
 * TODO: https://github.com/AElfProject/AElf/issues/338
 *          _state = State.Idle;
 */
            return(retMsg);
        }
Beispiel #2
0
        private async Task <List <TransactionTrace> > ExecuteTransactions(List <Transaction> txs, bool noTimeout = false)
        {
            using (var cts = new CancellationTokenSource())
            {
                if (!noTimeout)
                {
                    var distance = await _dpoSInfoProvider.GetDistanceToTimeSlotEnd();

                    var distanceRation = distance * (NodeConfig.Instance.RatioSynchronize + NodeConfig.Instance.RatioMine);
                    var timeout        = Math.Min(distanceRation, _maxMineTime);
                    cts.CancelAfter(TimeSpan.FromMilliseconds(timeout));
                    _logger?.Trace($"Execution limit time: {timeout}ms");
                }

                if (cts.IsCancellationRequested)
                {
                    return(null);
                }
                var disambiguationHash =
                    HashHelpers.GetDisambiguationHash(await GetNewBlockIndexAsync(), _producerAddress);

                var traces = txs.Count == 0
                    ? new List <TransactionTrace>()
                    : await _executingService.ExecuteAsync(txs, Config.ChainId, cts.Token, disambiguationHash);

                return(traces);
            }
        }
        public async Task <List <TransactionTrace> > ExecuteAsync(List <Transaction> transactions, Hash chainId,
                                                                  CancellationToken token, Hash disambiguationHash = null)
        {
            token.Register(() => _actorEnvironment.Requestor.Tell(JobExecutionCancelMessage.Instance));

            List <List <Transaction> >          groups;
            Dictionary <Transaction, Exception> failedTxs;

            var dposTxs   = transactions.Where(tx => tx.Type == TransactionType.DposTransaction).ToList();
            var normalTxs = transactions.Where(tx => tx.Type != TransactionType.DposTransaction).ToList();

            //disable parallel module by default because it doesn't finish yet (don't support contract call)
            if (ParallelConfig.Instance.IsParallelEnable)
            {
                var groupRes = await _grouper.ProcessWithCoreCount(GroupStrategy.Limited_MaxAddMins,
                                                                   ActorConfig.Instance.ConcurrencyLevel, chainId, normalTxs);

                groups    = groupRes.Item1;
                failedTxs = groupRes.Item2;
            }
            else
            {
                groups = new List <List <Transaction> > {
                    normalTxs
                };
                failedTxs = new Dictionary <Transaction, Exception>();
            }

            var dposResult = _singlExecutingService.ExecuteAsync(dposTxs, chainId, token);
            var tasks      = groups.Select(
                txs => Task.Run(() => AttemptToSendExecutionRequest(chainId, txs, token, disambiguationHash), token)
                ).ToArray();

            var results = dposResult.Result;

            results.AddRange((await Task.WhenAll(tasks)).SelectMany(x => x).ToList());

            foreach (var failed in failedTxs)
            {
                var failedTrace = new TransactionTrace
                {
                    StdErr = "Transaction with ID/hash " + failed.Key.GetHash().DumpHex() +
                             " failed, detail message: \n" + failed.Value.Dump(),
                    TransactionId = failed.Key.GetHash()
                };
                results.Add(failedTrace);
                Console.WriteLine(failedTrace.StdErr);
            }

            return(results);
        }
Beispiel #4
0
        /// <summary>
        /// Execute transactions.
        /// </summary>
        /// <param name="readyTxs"></param>
        /// <param name="chainId"></param>
        /// <param name="disambiguationHash"></param>
        /// <returns></returns>
        private async Task <List <TransactionResult> > ExecuteTransactions(List <Transaction> readyTxs, Hash chainId,
                                                                           Hash disambiguationHash, CancellationTokenSource cancellationTokenSource)
        {
            var traces = readyTxs.Count == 0
                ? new List <TransactionTrace>()
                : await _executingService.ExecuteAsync(readyTxs, chainId, cancellationTokenSource.Token, disambiguationHash);

            var results = new List <TransactionResult>();

            foreach (var trace in traces)
            {
                var res = new TransactionResult
                {
                    TransactionId = trace.TransactionId
                };
                if (string.IsNullOrEmpty(trace.StdErr))
                {
                    res.Logs.AddRange(trace.FlattenedLogs);
                    res.Status    = Status.Mined;
                    res.RetVal    = ByteString.CopyFrom(trace.RetVal.ToFriendlyBytes());
                    res.StateHash = trace.GetSummarizedStateHash();
                }
                else
                {
                    res.Status    = Status.Failed;
                    res.RetVal    = ByteString.CopyFromUtf8(trace.StdErr);
                    res.StateHash = trace.GetSummarizedStateHash();
                    if (!cancellationTokenSource.IsCancellationRequested)
                    {
                        _logger?.Error($"Transaction execute failed. TransactionId: {res.TransactionId.DumpHex()}, " +
                                       $"StateHash: {res.StateHash} Transaction deatils: {readyTxs.Find(x => x.GetHash() == trace.TransactionId)}" +
                                       $"\n {trace.StdErr}");
                    }
                }

                results.Add(res);
            }

            return(results);
        }
Beispiel #5
0
        private async Task <List <TransactionResult> > ExecuteTransactions(List <Transaction> txs, Hash chainId)
        {
            try
            {
                var traces = txs.Count == 0
                    ? new List <TransactionTrace>()
                    : await _executingService.ExecuteAsync(txs, chainId, Cts.Token);

                var results = new List <TransactionResult>();
                foreach (var trace in traces)
                {
                    var res = new TransactionResult
                    {
                        TransactionId = trace.TransactionId,
                    };
                    if (string.IsNullOrEmpty(trace.StdErr))
                    {
                        res.Logs.AddRange(trace.FlattenedLogs);
                        res.Status = Status.Mined;
                        res.RetVal = ByteString.CopyFrom(trace.RetVal.ToFriendlyBytes());
                    }
                    else
                    {
                        res.Status = Status.Failed;
                        res.RetVal = ByteString.CopyFromUtf8(trace.StdErr);
                    }

                    results.Add(res);
                }

                return(results);
            }
            catch (Exception e)
            {
                await Interrupt(e.ToString(), txs, e);

                return(null);
            }
        }
Beispiel #6
0
        public void StateRollbackTest()
        {
            var key       = new KeyPairGenerator().Generate();
            var addresses = Enumerable.Range(0, 10).Select(x => Address.FromString(x.ToString())).ToList();
            var txs       = addresses.Select(x => _mock.GetInitializeTxn(x, 1)).ToList();

            var b1 = new Block()
            {
                Header = new BlockHeader()
                {
                    ChainId           = _mock.ChainId1,
                    Index             = _mock.BlockChain.GetCurrentBlockHeightAsync().Result + 1,
                    PreviousBlockHash = _mock.BlockChain.GetCurrentBlockHashAsync().Result,
                    P = ByteString.CopyFrom(key.GetEncodedPublicKey())
                },
                Body = new BlockBody()
            };

            b1.Body.Transactions.AddRange(txs.Select(x => x.GetHash()));
            b1.Body.TransactionList.AddRange(txs);

            var disHash1 = b1.Header.GetDisambiguationHash();

            _executingService.ExecuteAsync(txs, _mock.ChainId1, CancellationToken.None, disHash1);

            _mock.BlockChain.AddBlocksAsync(new List <IBlock>()
            {
                b1
            });

            foreach (var addr in addresses)
            {
                Assert.Equal((ulong)1, _mock.GetBalance(addr));
            }

            var tfrs = Enumerable.Range(0, 5)
                       .Select(i => _mock.GetTransferTxn1(addresses[2 * i], addresses[2 * i + 1], 1)).ToList();

            var b2 = new Block()
            {
                Header = new BlockHeader()
                {
                    ChainId           = _mock.ChainId1,
                    Index             = _mock.BlockChain.GetCurrentBlockHeightAsync().Result + 1,
                    PreviousBlockHash = _mock.BlockChain.GetCurrentBlockHashAsync().Result,
                    P = ByteString.CopyFrom(key.GetEncodedPublicKey())
                },
                Body = new BlockBody()
            };

            b2.Body.Transactions.AddRange(tfrs.Select(x => x.GetHash()));
            b2.Body.TransactionList.AddRange(tfrs);

            var disHash2 = b2.Header.GetDisambiguationHash();

            _executingService.ExecuteAsync(tfrs, _mock.ChainId1, CancellationToken.None, disHash2);

            _mock.BlockChain.AddBlocksAsync(new List <IBlock>()
            {
                b2
            });
            foreach (var i in Enumerable.Range(0, 5))
            {
                Assert.Equal((ulong)0, _mock.GetBalance(addresses[2 * i]));
                Assert.Equal((ulong)2, _mock.GetBalance(addresses[2 * i + 1]));
            }

            _mock.BlockChain.RollbackToHeight(2);

            foreach (var addr in addresses)
            {
                Assert.Equal((ulong)1, _mock.GetBalance(addr));
            }
        }
Beispiel #7
0
        public async Task <KeyValuePair <string, double> > MultipleGroupBenchmark(int txNumber, int groupCount)
        {
            int repeatTime = _options.RepeatTime;

            var txList = _dataGenerater.GetMultipleGroupTx(txNumber, groupCount, _contractHash);

            var targets       = GetTargetHashesForTransfer(txList);
            var originBalance = await ReadBalancesForAddrs(targets, _contractHash);

            var expectedTransferBalance = originBalance.Select(balance => balance + (ulong)(((txNumber / groupCount) * 20) * repeatTime)).ToList();

            long timeused = 0;

            for (int i = 0; i < repeatTime; i++)
            {
                _logger.Info($"round {i+1} / {repeatTime} start");
                foreach (var tx in txList)
                {
                    tx.IncrementId += 1;
                }
                Stopwatch swExec = new Stopwatch();
                swExec.Start();

                var cts      = new CancellationTokenSource();
                var txResult = await _executingService.ExecuteAsync(txList, ChainId, cts.Token);

                swExec.Stop();
                timeused += swExec.ElapsedMilliseconds;
                txResult.ForEach(trace =>
                {
                    if (!trace.StdErr.IsNullOrEmpty())
                    {
                        _logger.Error("Execution error: " + trace.StdErr);
                    }
                });
                Thread.Sleep(50); //sleep 50 ms to let async logger finish printing contents of previous round
                _logger.Info($"round {i+1} / {repeatTime} ended, used time {swExec.ElapsedMilliseconds} ms");
            }

            var acturalBalance = await ReadBalancesForAddrs(GetTargetHashesForTransfer(txList), _contractHash);

            //A double zip, first combine expectedTransferBalance with acturalBalance to get the compare string " {tx count per group} * transferBal * repeatTime = {expected} || {actural}"
            //              then combine originBalance with the compare string above.
            _logger.Info(
                $"Validation for balance transfer for {groupCount} group with {txNumber / groupCount} transactions: \n\t" +
                string.Join("\n\t",
                            originBalance.Zip(
                                expectedTransferBalance.Zip(
                                    acturalBalance,
                                    (expected, actural) => $"{txNumber / groupCount} * 20 * {repeatTime} = {expected} || actural: {actural}"),
                                (origin, compareStr) => $"expected: {origin} + {compareStr}")));


            for (int j = 0; j < acturalBalance.Count; j++)
            {
                if (expectedTransferBalance[j] != acturalBalance[j])
                {
                    throw new Exception($"Result inconsist in transaction with {groupCount} groups, see log for more details");
                }
            }

            var time = txNumber / (timeused / 1000.0 / repeatTime);
            var str  = groupCount + " groups with " + txList.Count + " tx in total";

            return(new KeyValuePair <string, double>(str, time));
        }