diff --git a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs index 8840c15b01..cb375da9b4 100644 --- a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs @@ -61,6 +61,7 @@ T Call(Address fromAddress, Address toAddress, string methodName, ByteString where T : IMessage, new(); void SendInline(Address toAddress, string methodName, ByteString args); + void SendInlineWithTransactionId(Address toAddress, string methodName, ByteString args); void SendVirtualInline(Hash fromVirtualAddress, Address toAddress, string methodName, ByteString args); diff --git a/src/AElf.Kernel.SmartContract/Application/PlainTransactionExecutingService.cs b/src/AElf.Kernel.SmartContract/Application/PlainTransactionExecutingService.cs index c3cfa917fa..1da6ed019d 100644 --- a/src/AElf.Kernel.SmartContract/Application/PlainTransactionExecutingService.cs +++ b/src/AElf.Kernel.SmartContract/Application/PlainTransactionExecutingService.cs @@ -24,12 +24,10 @@ public class PlainTransactionExecutingService : IPlainTransactionExecutingServic private readonly ISmartContractExecutiveService _smartContractExecutiveService; private readonly ITransactionContextFactory _transactionContextFactory; private readonly IFeatureDisableService _featureDisableService; - private readonly ITransactionManager _transactionManager; public PlainTransactionExecutingService(ISmartContractExecutiveService smartContractExecutiveService, IEnumerable postPlugins, IEnumerable prePlugins, - ITransactionContextFactory transactionContextFactory, IFeatureDisableService featureDisableService, - ITransactionManager transactionManager) + ITransactionContextFactory transactionContextFactory, IFeatureDisableService featureDisableService) { _smartContractExecutiveService = smartContractExecutiveService; _transactionContextFactory = transactionContextFactory; @@ -38,7 +36,6 @@ public PlainTransactionExecutingService(ISmartContractExecutiveService smartCont _postPlugins = GetUniquePlugins(postPlugins); Logger = NullLogger.Instance; LocalEventBus = NullLocalEventBus.Instance; - _transactionManager = transactionManager; } public ILogger Logger { get; set; } @@ -88,7 +85,7 @@ public async Task> ExecuteAsync(TransactionExecutingDto } List traceList = new List(); - List inlineTxList = new List(); + // List inlineTxList = new List(); WrapTraceList(traceList, trace); // WrapinlineTxList(inlineTxList, trace); // foreach (var inlinetransaction in inlineTxList) @@ -109,7 +106,9 @@ public async Task> ExecuteAsync(TransactionExecutingDto int index = 1; foreach (var transactionTrace in traceList) { - Console.WriteLine("index="+ index+++" "+transactionTrace.TransactionId); + // Console.WriteLine("index="+ index+++" "+transactionTrace.TransactionId); + + Console.WriteLine("transactionTraceId="+index+++"="+transactionTrace.TransactionId); if (!TryUpdateStateCache(transactionTrace, groupStateCache)) break; @@ -166,12 +165,16 @@ private void WrapinlineTxList(List inlineTxList, TransactionTrace t } } + private readonly Dictionary traceDictionary = new Dictionary(); + private List WrapTraceList(List traceList, TransactionTrace trace) { + HashSet txIdSet = new HashSet(); // Create a stack to hold the traces for processing Stack stack = new Stack(); stack.Push(trace); + int index = 1; // Process all traces in the stack while (stack.Count > 0) { @@ -179,10 +182,21 @@ private List WrapTraceList(List traceList, T var currentTrace = stack.Pop(); // Add the current trace to the list - if (currentTrace.IsInlineTransaction) + // if (currentTrace.IsInlineTransaction) + // { + + // if (currentTrace.IsInlineTransaction && !txIdSet.Contains(currentTrace.TransactionId) || index == 1) + if (currentTrace.IsInlineTxWithId || index == 1) { - traceList.Add(currentTrace); + // Console.WriteLine("currentTrace="+currentTrace.TransactionId); + traceList.AddIfNotContains(currentTrace); + txIdSet.Add(currentTrace.TransactionId); + index++; + break; } + + + // } // If the current trace contains inline traces, add them to the stack if (currentTrace.InlineTraces != null) @@ -197,6 +211,13 @@ private List WrapTraceList(List traceList, T return traceList; } + public static void AddIfNotContainsByTransactionId( List traceList, TransactionTrace currentTrace) + { + if (traceList.All(trace => trace.TransactionId != currentTrace.TransactionId)) + { + traceList.Add(currentTrace); + } + } private void GetAllTrace(List transactionTraces, TransactionTrace transactionTrace) { @@ -335,7 +356,8 @@ private async Task ExecuteInlineTransactions(int depth, Timestamp currentBlockTi int index = 0; foreach (var inlineTx in txContext.Trace.InlineTransactions) { - if (txContext.IsInlineTransaction) + inlineTx.IsInlineTxWithId = true; + if (txContext.IsInlineTxWithId || inlineTx.IsInlineTxWithId) { AutoGenerateInlineTxId(inlineTx,originTransactionId,index); } @@ -358,6 +380,11 @@ private async Task ExecuteInlineTransactions(int depth, Timestamp currentBlockTi // { // inlineTrace.IsInlineTransaction = true; // } + if (txContext.IsInlineTxWithId || inlineTx.IsInlineTxWithId) + { + inlineTrace.IsInlineTxWithId = true; + } + trace.InlineTraces.Add(inlineTrace); if (!inlineTrace.IsSuccessful()) // Already failed, no need to execute remaining inline transactions @@ -369,7 +396,10 @@ private async Task ExecuteInlineTransactions(int depth, Timestamp currentBlockTi private void AutoGenerateInlineTxId(Transaction inlineTx, Hash originTransactionId, int index) { - inlineTx.SetHash(HashHelper.XorAndCompute(originTransactionId, HashHelper.ComputeFrom(index))); + inlineTx.SetHash(HashHelper.XorAndCompute(originTransactionId, HashHelper.ComputeFrom(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() ))); + // inlineTx.SetHash(HashHelper.XorAndCompute(originTransactionId, HashHelper.ComputeFrom(index ))); + Console.WriteLine("SetHash="+inlineTx.GetHash()); + inlineTx.IsInlineTxWithId = true; } private async Task ExecutePluginOnPreTransactionStageAsync(IExecutive executive, diff --git a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs index e35307beca..6c516669bc 100644 --- a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs @@ -238,7 +238,7 @@ public void SendInline(Address toAddress, string methodName, ByteString args) public void SendInlineWithTransactionId(Address toAddress, string methodName, ByteString args) { - // TransactionContext.IsInlineTransaction = true; + TransactionContext.IsInlineTxWithId = true; TransactionContext.Trace.InlineTransactions.Add(new Transaction { IsInlineTxWithId = true, @@ -291,10 +291,12 @@ public void SendVirtualInline(Hash fromVirtualAddress, Address toAddress, string public void SendVirtualInlineBySystemContract(Hash fromVirtualAddress, Address toAddress, string methodName, ByteString args) { + TransactionContext.IsInlineTxWithId = true; TransactionContext.Trace.InlineTransactions.Add(new Transaction { From = ConvertVirtualAddressToContractAddressWithContractHashName(fromVirtualAddress, Self), To = toAddress, + IsInlineTxWithId = true, MethodName = methodName, Params = args }); diff --git a/src/AElf.Kernel.SmartContract/ITransactionContext.cs b/src/AElf.Kernel.SmartContract/ITransactionContext.cs index 54a7bdf49c..610fd544ff 100644 --- a/src/AElf.Kernel.SmartContract/ITransactionContext.cs +++ b/src/AElf.Kernel.SmartContract/ITransactionContext.cs @@ -17,5 +17,5 @@ public interface ITransactionContext Transaction Transaction { get; set; } TransactionTrace Trace { get; set; } IStateCache StateCache { get; set; } - bool IsInlineTransaction { get; set; } + bool IsInlineTxWithId { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract/TransactionContext.cs b/src/AElf.Kernel.SmartContract/TransactionContext.cs index 856123d57f..d59e6b4254 100644 --- a/src/AElf.Kernel.SmartContract/TransactionContext.cs +++ b/src/AElf.Kernel.SmartContract/TransactionContext.cs @@ -16,5 +16,5 @@ public class TransactionContext : ITransactionContext public Transaction Transaction { get; set; } public TransactionTrace Trace { get; set; } public IStateCache StateCache { get; set; } - public bool IsInlineTransaction { get; set; } + public bool IsInlineTxWithId { get; set; } } \ No newline at end of file diff --git a/src/AElf.Kernel.Types/Transaction/TransactionTrace.cs b/src/AElf.Kernel.Types/Transaction/TransactionTrace.cs index e8fef9ebb3..46c8c098c9 100644 --- a/src/AElf.Kernel.Types/Transaction/TransactionTrace.cs +++ b/src/AElf.Kernel.Types/Transaction/TransactionTrace.cs @@ -12,7 +12,7 @@ public partial class TransactionTrace public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } - public bool IsInlineTransaction { get; set; } + public bool IsInlineTxWithId { get; set; } public IEnumerable FlattenedLogs { diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs index de3fd1464a..dad965347a 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs @@ -205,6 +205,10 @@ public void SendInline(Address toAddress, string methodName, ByteString args) { SmartContractBridgeContextImplementation.SendInline(toAddress, methodName, args); } + public void SendInlineWithTransactionId(Address toAddress, string methodName, ByteString args) + { + SmartContractBridgeContextImplementation.SendInlineWithTransactionId(toAddress, methodName, args); + } /// /// Sends a virtual inline transaction to another contract. diff --git a/src/AElf.Sdk.CSharp/SmartContractBridgeContextExtensions.cs b/src/AElf.Sdk.CSharp/SmartContractBridgeContextExtensions.cs index 6b278213d6..6b3a693b00 100644 --- a/src/AElf.Sdk.CSharp/SmartContractBridgeContextExtensions.cs +++ b/src/AElf.Sdk.CSharp/SmartContractBridgeContextExtensions.cs @@ -49,7 +49,7 @@ public static T Call(this ISmartContractBridgeContext context, Address addres public static void SendInline(this ISmartContractBridgeContext context, Address toAddress, string methodName, IMessage message) { - context.SendInline(toAddress, methodName, ConvertToByteString(message)); + context.SendInlineWithTransactionId(toAddress, methodName, ConvertToByteString(message)); } /// @@ -125,12 +125,6 @@ public static void SendInline(this CSharpSmartContractContext context, Address t { context.SendInline(toAddress, methodName, ConvertToByteString(message)); } - - public static void SendInlineWithTransactionId(this CSharpSmartContractContext context, Address toAddress, string methodName, - IMessage message) - { - context.SendInline(toAddress, methodName, ConvertToByteString(message)); - } /// /// Sends a virtual inline transaction to another contract. diff --git a/test/AElf.Contracts.TestContract.TransactionFees/Contract_Action.cs b/test/AElf.Contracts.TestContract.TransactionFees/Contract_Action.cs index 5e572de329..3ae552d34e 100644 --- a/test/AElf.Contracts.TestContract.TransactionFees/Contract_Action.cs +++ b/test/AElf.Contracts.TestContract.TransactionFees/Contract_Action.cs @@ -64,6 +64,7 @@ public override Empty FailInlineTransfer(TransferInput input) Memo = input.Memo }); + // Context.SendInlineWithTransactionId(State.TokenContract.Value, "Burn", new BurnInput Context.SendInline(State.TokenContract.Value, "Burn", new BurnInput { Symbol = "ELF",