public async Task <TransactionTrace> ExecuteAsync(IChainContext chainContext, Transaction transaction,
                                                          Timestamp currentBlockTime)
        {
            var trace = new TransactionTrace()
            {
                TransactionId = transaction.GetHash()
            };

            var transactionContext = new TransactionContext
            {
                PreviousBlockHash = chainContext.BlockHash,
                CurrentBlockTime  = currentBlockTime,
                Transaction       = transaction,
                BlockHeight       = chainContext.BlockHeight + 1,
                Trace             = trace,
                CallDepth         = 0,
                StateCache        = chainContext.StateCache
            };

            var executive = await _smartContractExecutiveService.GetExecutiveAsync(
                chainContext, transaction.To);

            try
            {
                await executive.ApplyAsync(transactionContext);
            }
            finally
            {
                await _smartContractExecutiveService.PutExecutiveAsync(chainContext, transaction.To, executive);
            }

            return(trace);
        }
Esempio n. 2
0
        protected override async Task <TransactionTrace> ExecuteOneAsync(
            SingleTransactionExecutingDto singleTxExecutingDto,
            CancellationToken cancellationToken)
        {
            if (singleTxExecutingDto.IsCancellable)
            {
                cancellationToken.ThrowIfCancellationRequested();
            }

            singleTxExecutingDto.OriginTransactionId = _pluginOriginId;
            var txContext = CreateTransactionContext(singleTxExecutingDto);
            var trace     = txContext.Trace;

            var internalStateCache   = new TieredStateCache(singleTxExecutingDto.ChainContext.StateCache);
            var internalChainContext =
                new ChainContextWithTieredStateCache(singleTxExecutingDto.ChainContext, internalStateCache);

            IExecutive executive;

            try
            {
                executive = await _smartContractExecutiveService.GetExecutiveAsync(
                    internalChainContext,
                    singleTxExecutingDto.Transaction.To);
            }
            catch (SmartContractFindRegistrationException)
            {
                txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                txContext.Trace.Error          += "Invalid contract address.\n";
                return(trace);
            }

            try
            {
                await executive.ApplyAsync(txContext);

                if (txContext.Trace.IsSuccessful())
                {
                    await ExecuteInlineTransactions(singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime,
                                                    txContext, internalStateCache,
                                                    internalChainContext,
                                                    singleTxExecutingDto.OriginTransactionId,
                                                    cancellationToken);
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Transaction execution failed.");
                txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                txContext.Trace.Error          += ex + "\n";
                throw;
            }
            finally
            {
                await _smartContractExecutiveService.PutExecutiveAsync(singleTxExecutingDto.ChainContext,
                                                                       singleTxExecutingDto.Transaction.To, executive);
            }

            return(trace);
        }
Esempio n. 3
0
        public async Task <TransactionTrace> ExecuteAsync(IChainContext chainContext, Transaction transaction,
                                                          Timestamp currentBlockTime)
        {
            var transactionContext = _transactionContextFactory.Create(transaction, chainContext, currentBlockTime);
            var executive          = await _smartContractExecutiveService.GetExecutiveAsync(
                chainContext, transaction.To);

            try
            {
                await executive.ApplyAsync(transactionContext);
            }
            finally
            {
                await _smartContractExecutiveService.PutExecutiveAsync(chainContext, transaction.To, executive);
            }

            return(transactionContext.Trace);
        }
        private async Task <TransactionResourceInfo> GetResourcesForOneAsync(IChainContext chainContext,
                                                                             Transaction transaction, CancellationToken ct)
        {
            IExecutive executive = null;
            var        address   = transaction.To;

            try
            {
                executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, address);

                var codeRemarks = await _codeRemarksManager.GetCodeRemarksAsync(executive.ContractHash);

                if (codeRemarks != null && codeRemarks.NonParallelizable)
                {
                    return(new TransactionResourceInfo
                    {
                        TransactionId = transaction.GetHash(),
                        ParallelType = ParallelType.NonParallelizable
                    });
                }

                var resourceInfo = await executive.GetTransactionResourceInfoAsync(chainContext, transaction);

                // Try storing in cache here
                return(resourceInfo);
            }
            catch (SmartContractFindRegistrationException e)
            {
                return(new TransactionResourceInfo
                {
                    TransactionId = transaction.GetHash(),
                    ParallelType = ParallelType.InvalidContractAddress
                });
            }
            finally
            {
                if (executive != null)
                {
                    await _smartContractExecutiveService.PutExecutiveAsync(address, executive);
                }
            }
        }
Esempio n. 5
0
        private async Task <TransactionTrace> ExecuteOneAsync(int depth, IChainContext chainContext,
                                                              Transaction transaction, Timestamp currentBlockTime, CancellationToken cancellationToken,
                                                              Address origin = null, bool isCancellable = true)
        {
            if (isCancellable && cancellationToken.IsCancellationRequested)
            {
                return(new TransactionTrace
                {
                    TransactionId = transaction.GetHash(),
                    ExecutionStatus = ExecutionStatus.Canceled,
                    Error = "Execution cancelled"
                });
            }

            if (transaction.To == null || transaction.From == null)
            {
                throw new Exception($"error tx: {transaction}");
            }

            var trace = new TransactionTrace
            {
                TransactionId = transaction.GetHash()
            };

            var txContext = new TransactionContext
            {
                PreviousBlockHash = chainContext.BlockHash,
                CurrentBlockTime  = currentBlockTime,
                Transaction       = transaction,
                BlockHeight       = chainContext.BlockHeight + 1,
                Trace             = trace,
                CallDepth         = depth,
                StateCache        = chainContext.StateCache,
                Origin            = origin != null ? origin : transaction.From
            };

            var internalStateCache   = new TieredStateCache(chainContext.StateCache);
            var internalChainContext = new ChainContextWithTieredStateCache(chainContext, internalStateCache);

            IExecutive executive;

            try
            {
                executive = await _smartContractExecutiveService.GetExecutiveAsync(
                    internalChainContext,
                    transaction.To);
            }
            catch (SmartContractFindRegistrationException e)
            {
                txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                txContext.Trace.Error          += "Invalid contract address.\n";
                return(trace);
            }

            try
            {
                #region PreTransaction

                if (depth == 0)
                {
                    if (!await ExecutePluginOnPreTransactionStageAsync(executive, txContext, currentBlockTime,
                                                                       internalChainContext, internalStateCache, cancellationToken))
                    {
                        return(trace);
                    }
                }

                #endregion

                await executive.ApplyAsync(txContext);

                await ExecuteInlineTransactions(depth, currentBlockTime, txContext, internalStateCache,
                                                internalChainContext, cancellationToken);

                #region PostTransaction

                if (depth == 0)
                {
                    if (!await ExecutePluginOnPostTransactionStageAsync(executive, txContext, currentBlockTime,
                                                                        internalChainContext, internalStateCache, cancellationToken))
                    {
                        return(trace);
                    }
                }

                #endregion
            }
            catch (Exception ex)
            {
                Logger.LogError($"Tx execution failed: {txContext}");
                txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                txContext.Trace.Error          += ex + "\n";
                throw;
            }
            finally
            {
                await _smartContractExecutiveService.PutExecutiveAsync(transaction.To, executive);

                await LocalEventBus.PublishAsync(new TransactionExecutedEventData
                {
                    TransactionTrace = trace
                });
            }

            return(trace);
        }
Esempio n. 6
0
        private async Task <TransactionTrace> ExecuteOneAsync(SingleTransactionExecutingDto singleTxExecutingDto,
                                                              CancellationToken cancellationToken)
        {
            if (singleTxExecutingDto.IsCancellable)
            {
                cancellationToken.ThrowIfCancellationRequested();
            }

            var txContext = CreateTransactionContext(singleTxExecutingDto, out var trace);

            var internalStateCache   = new TieredStateCache(singleTxExecutingDto.ChainContext.StateCache);
            var internalChainContext = new ChainContextWithTieredStateCache(singleTxExecutingDto.ChainContext, internalStateCache);

            IExecutive executive;

            try
            {
                executive = await _smartContractExecutiveService.GetExecutiveAsync(
                    internalChainContext,
                    singleTxExecutingDto.Transaction.To);
            }
            catch (SmartContractFindRegistrationException)
            {
                txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                txContext.Trace.Error          += "Invalid contract address.\n";
                return(trace);
            }

            try
            {
                #region PreTransaction

                if (singleTxExecutingDto.Depth == 0)
                {
                    if (!await ExecutePluginOnPreTransactionStageAsync(executive, txContext, singleTxExecutingDto.CurrentBlockTime,
                                                                       internalChainContext, internalStateCache, cancellationToken))
                    {
                        trace.ExecutionStatus = ExecutionStatus.Prefailed;
                        return(trace);
                    }
                }

                #endregion

                await executive.ApplyAsync(txContext);

                if (txContext.Trace.IsSuccessful())
                {
                    await ExecuteInlineTransactions(singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime,
                                                    txContext, internalStateCache,
                                                    internalChainContext, cancellationToken);
                }

                #region PostTransaction

                if (singleTxExecutingDto.Depth == 0)
                {
                    if (!await ExecutePluginOnPostTransactionStageAsync(executive, txContext, singleTxExecutingDto.CurrentBlockTime,
                                                                        internalChainContext, internalStateCache, cancellationToken))
                    {
                        trace.ExecutionStatus = ExecutionStatus.Postfailed;
                        return(trace);
                    }
                }

                #endregion
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Transaction execution failed.");
                txContext.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                txContext.Trace.Error          += ex + "\n";
                throw;
            }
            finally
            {
                await _smartContractExecutiveService.PutExecutiveAsync(singleTxExecutingDto.ChainContext,
                                                                       singleTxExecutingDto.Transaction.To, executive);

#if DEBUG
                await LocalEventBus.PublishAsync(new TransactionExecutedEventData
                {
                    TransactionTrace = trace
                });
#endif
            }

            return(trace);
        }
        private async Task <TransactionTrace> ExecuteOneAsync(int depth, IChainContext chainContext,
                                                              Transaction transaction, DateTime currentBlockTime, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(new TransactionTrace()
                {
                    TransactionId = transaction.GetHash(),
                    ExecutionStatus = ExecutionStatus.Canceled
                });
            }

            if (transaction.To == null || transaction.From == null)
            {
                throw new Exception($"error tx: {transaction}");
            }

            var trace = new TransactionTrace
            {
                TransactionId = transaction.GetHash()
            };

            var txCtxt = new TransactionContext
            {
                PreviousBlockHash = chainContext.BlockHash,
                CurrentBlockTime  = currentBlockTime,
                Transaction       = transaction,
                BlockHeight       = chainContext.BlockHeight + 1,
                Trace             = trace,
                CallDepth         = depth,
                StateCache        = chainContext.StateCache
            };

            var internalStateCache   = new TieredStateCache(chainContext.StateCache);
            var internalChainContext = new ChainContextWithTieredStateCache(chainContext, internalStateCache);
            var executive            = await _smartContractExecutiveService.GetExecutiveAsync(
                internalChainContext,
                transaction.To);

            try
            {
                #region PreTransaction

                if (depth == 0)
                {
                    foreach (var plugin in _plugins)
                    {
                        var transactions = await plugin.GetPreTransactionsAsync(executive.Descriptors, txCtxt);

                        foreach (var preTx in transactions)
                        {
                            var preTrace = await ExecuteOneAsync(0, internalChainContext, preTx, currentBlockTime,
                                                                 cancellationToken);

                            trace.PreTransactions.Add(preTx);
                            trace.PreTraces.Add(preTrace);
                            if (!preTrace.IsSuccessful())
                            {
                                trace.ExecutionStatus = ExecutionStatus.Prefailed;
                                return(trace);
                            }

                            internalStateCache.Update(preTrace.GetFlattenedWrite()
                                                      .Select(x => new KeyValuePair <string, byte[]>(x.Key, x.Value.ToByteArray())));
                        }
                    }
                }

                #endregion

                await executive.ApplyAsync(txCtxt);

                if (txCtxt.Trace.IsSuccessful() && txCtxt.Trace.InlineTransactions.Count > 0)
                {
                    internalStateCache.Update(txCtxt.Trace.GetFlattenedWrite()
                                              .Select(x => new KeyValuePair <string, byte[]>(x.Key, x.Value.ToByteArray())));
                    foreach (var inlineTx in txCtxt.Trace.InlineTransactions)
                    {
                        var inlineTrace = await ExecuteOneAsync(depth + 1, internalChainContext, inlineTx,
                                                                currentBlockTime, cancellationToken);

                        trace.InlineTraces.Add(inlineTrace);
                        if (!inlineTrace.IsSuccessful())
                        {
                            // Fail already, no need to execute remaining inline transactions
                            break;
                        }

                        internalStateCache.Update(inlineTrace.GetFlattenedWrite()
                                                  .Select(x => new KeyValuePair <string, byte[]>(x.Key, x.Value.ToByteArray())));
                    }
                }
            }
            catch (Exception ex)
            {
                txCtxt.Trace.ExecutionStatus = ExecutionStatus.ContractError;
                txCtxt.Trace.StdErr         += ex + "\n";
                throw;
            }
            finally
            {
                await _smartContractExecutiveService.PutExecutiveAsync(transaction.To, executive);
            }

            return(trace);
        }