public async Task <List <ExecutionReturnSet> > ExecuteAsync(TransactionExecutingDto transactionExecutingDto, CancellationToken cancellationToken, bool throwException) { var groupStateCache = transactionExecutingDto.PartialBlockStateSet == null ? new TieredStateCache() : new TieredStateCache( new StateCacheFromPartialBlockStateSet(transactionExecutingDto.PartialBlockStateSet)); var groupChainContext = new ChainContextWithTieredStateCache( transactionExecutingDto.BlockHeader.PreviousBlockHash, transactionExecutingDto.BlockHeader.Height - 1, groupStateCache); var returnSets = new List <ExecutionReturnSet>(); foreach (var transaction in transactionExecutingDto.Transactions) { if (cancellationToken.IsCancellationRequested) { break; } var trace = await ExecuteOneAsync(0, groupChainContext, transaction, transactionExecutingDto.BlockHeader.Time, cancellationToken); // Will be useful when debugging MerkleTreeRootOfWorldState is different from each miner. Logger.LogTrace(transaction.MethodName); Logger.LogTrace(trace.StateSet.Writes.Values.Select(v => v.ToBase64().ComputeHash().ToHex()) .JoinAsString("\n")); if (!trace.IsSuccessful()) { if (throwException) { Logger.LogError(trace.Error); } // Do not package this transaction if any of his inline transactions canceled. if (IsTransactionCanceled(trace)) { break; } trace.SurfaceUpError(); } else { groupStateCache.Update(trace.GetFlattenedWrites() .Select(x => new KeyValuePair <string, byte[]>(x.Key, x.Value.ToByteArray()))); } if (trace.Error != string.Empty) { Logger.LogError(trace.Error); } var result = GetTransactionResult(trace, transactionExecutingDto.BlockHeader.Height); if (result != null) { await _transactionResultService.AddTransactionResultAsync(result, transactionExecutingDto.BlockHeader); } var returnSet = GetReturnSet(trace, result); returnSets.Add(returnSet); } return(returnSets); }
public async Task <List <ExecutionReturnSet> > ExecuteAsync(TransactionExecutingDto transactionExecutingDto, CancellationToken cancellationToken) { try { var groupStateCache = transactionExecutingDto.PartialBlockStateSet.ToTieredStateCache(); var groupChainContext = new ChainContextWithTieredStateCache( transactionExecutingDto.BlockHeader.PreviousBlockHash, transactionExecutingDto.BlockHeader.Height - 1, groupStateCache); var returnSets = new List <ExecutionReturnSet>(); foreach (var transaction in transactionExecutingDto.Transactions) { TransactionTrace trace; if (cancellationToken.IsCancellationRequested) { break; } var singleTxExecutingDto = new SingleTransactionExecutingDto { Depth = 0, ChainContext = groupChainContext, Transaction = transaction, CurrentBlockTime = transactionExecutingDto.BlockHeader.Time, OriginTransactionId = transaction.GetHash() }; try { var transactionExecutionTask = Task.Run(() => ExecuteOneAsync(singleTxExecutingDto, cancellationToken), cancellationToken); trace = await transactionExecutionTask.WithCancellation(cancellationToken); } catch (OperationCanceledException) { Logger.LogTrace("Transaction canceled."); if (cancellationToken.IsCancellationRequested) { break; } continue; } if (!TryUpdateStateCache(trace, groupStateCache)) { break; } #if DEBUG if (!string.IsNullOrEmpty(trace.Error)) { Logger.LogInformation(trace.Error); } #endif var result = GetTransactionResult(trace, transactionExecutingDto.BlockHeader.Height); var returnSet = GetReturnSet(trace, result); returnSets.Add(returnSet); } return(returnSets); } catch (Exception e) { Logger.LogError(e, "Failed while executing txs in block."); throw; } }
public async Task <List <ExecutionReturnSet> > ExecuteAsync(TransactionExecutingDto transactionExecutingDto, CancellationToken cancellationToken) { try { var groupStateCache = transactionExecutingDto.PartialBlockStateSet == null ? new TieredStateCache() : new TieredStateCache( new StateCacheFromPartialBlockStateSet(transactionExecutingDto.PartialBlockStateSet)); var groupChainContext = new ChainContextWithTieredStateCache( transactionExecutingDto.BlockHeader.PreviousBlockHash, transactionExecutingDto.BlockHeader.Height - 1, groupStateCache); var transactionResults = new List <TransactionResult>(); var returnSets = new List <ExecutionReturnSet>(); foreach (var transaction in transactionExecutingDto.Transactions) { TransactionTrace trace; if (cancellationToken.IsCancellationRequested) { break; } var singleTxExecutingDto = new SingleTransactionExecutingDto { Depth = 0, ChainContext = groupChainContext, Transaction = transaction, CurrentBlockTime = transactionExecutingDto.BlockHeader.Time, }; try { var transactionExecutionTask = Task.Run(() => ExecuteOneAsync(singleTxExecutingDto, cancellationToken), cancellationToken); trace = await transactionExecutionTask.WithCancellation(cancellationToken); } catch (OperationCanceledException) { Logger.LogTrace("Transaction canceled."); if (cancellationToken.IsCancellationRequested) { break; } continue; } if (trace == null) { break; } if (!trace.IsSuccessful()) { // Do not package this transaction if any of his inline transactions canceled. if (IsTransactionCanceled(trace)) { break; } var transactionExecutingStateSets = new List <TransactionExecutingStateSet>(); foreach (var preTrace in trace.PreTraces) { if (preTrace.IsSuccessful()) { transactionExecutingStateSets.AddRange(preTrace.GetStateSets()); } } foreach (var postTrace in trace.PostTraces) { if (postTrace.IsSuccessful()) { transactionExecutingStateSets.AddRange(postTrace.GetStateSets()); } } groupStateCache.Update(transactionExecutingStateSets); trace.SurfaceUpError(); } else { groupStateCache.Update(trace.GetStateSets()); } #if DEBUG if (trace.Error != string.Empty) { Logger.LogError(trace.Error); } #endif var result = GetTransactionResult(trace, transactionExecutingDto.BlockHeader.Height); transactionResults.Add(result); var returnSet = GetReturnSet(trace, result); returnSets.Add(returnSet); } await _transactionResultService.AddTransactionResultsAsync(transactionResults, transactionExecutingDto.BlockHeader); return(returnSets); } catch (Exception e) { Logger.LogError(e, "Failed while executing txs in block."); throw; } }
public async Task <List <ExecutionReturnSet> > ExecuteAsync(TransactionExecutingDto transactionExecutingDto, CancellationToken cancellationToken, bool throwException) { try { var groupStateCache = transactionExecutingDto.PartialBlockStateSet == null ? new TieredStateCache() : new TieredStateCache( new StateCacheFromPartialBlockStateSet(transactionExecutingDto.PartialBlockStateSet)); var groupChainContext = new ChainContextWithTieredStateCache( transactionExecutingDto.BlockHeader.PreviousBlockHash, transactionExecutingDto.BlockHeader.Height - 1, groupStateCache); var transactionResults = new List <TransactionResult>(); var returnSets = new List <ExecutionReturnSet>(); foreach (var transaction in transactionExecutingDto.Transactions) { TransactionTrace trace; if (cancellationToken.IsCancellationRequested) { break; } var singleTxExecutingDto = new SingleTransactionExecutingDto { Depth = 0, ChainContext = groupChainContext, Transaction = transaction, CurrentBlockTime = transactionExecutingDto.BlockHeader.Time, }; try { var task = Task.Run(() => ExecuteOneAsync(singleTxExecutingDto, cancellationToken), cancellationToken); trace = await task.WithCancellation(cancellationToken); } catch (OperationCanceledException) { Logger.LogTrace($"transaction canceled"); break; } if (trace == null) { break; } // Will be useful when debugging MerkleTreeRootOfWorldState is different from each miner. /* * Logger.LogTrace(transaction.MethodName); * Logger.LogTrace(trace.StateSet.Writes.Values.Select(v => v.ToBase64().ComputeHash().ToHex()) * .JoinAsString("\n")); */ if (!trace.IsSuccessful()) { if (throwException) { Logger.LogError(trace.Error); } // Do not package this transaction if any of his inline transactions canceled. if (IsTransactionCanceled(trace)) { break; } var transactionExecutingStateSets = new List <TransactionExecutingStateSet>(); foreach (var preTrace in trace.PreTraces) { if (preTrace.IsSuccessful()) { transactionExecutingStateSets.AddRange(preTrace.GetStateSets()); } } foreach (var postTrace in trace.PostTraces) { if (postTrace.IsSuccessful()) { transactionExecutingStateSets.AddRange(postTrace.GetStateSets()); } } groupStateCache.Update(transactionExecutingStateSets); trace.SurfaceUpError(); } else { groupStateCache.Update(trace.GetStateSets()); } if (trace.Error != string.Empty) { Logger.LogError(trace.Error); } var result = GetTransactionResult(trace, transactionExecutingDto.BlockHeader.Height); if (result != null) { result.TransactionFee = trace.TransactionFee; transactionResults.Add(result); } var returnSet = GetReturnSet(trace, result); returnSets.Add(returnSet); } await _transactionResultService.AddTransactionResultsAsync(transactionResults, transactionExecutingDto.BlockHeader); return(returnSets); } catch (Exception e) { Logger.LogTrace("Failed while executing txs in block.", e); throw; } }