Skip to content

Commit d594e53

Browse files
authored
Merge branch 'dev' into feature/whitelist-to-sdk
2 parents d1a71ef + 85e9efd commit d594e53

File tree

23 files changed

+359
-22
lines changed

23 files changed

+359
-22
lines changed

contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,12 @@ private void ProcessNextRound(NextRoundInput input)
127127
{
128128
var minersCount = GetMinersCount(nextRound);
129129
if (minersCount != 0 && State.ElectionContract.Value != null)
130+
{
130131
State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput
131132
{
132133
MinersCount = minersCount
133134
});
135+
}
134136
}
135137
}
136138

contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,16 @@ private Address ExtractTokenContractAddress(ByteString bytes)
215215
private void AssertCrossChainTransaction(Transaction originalTransaction, Address validAddress,
216216
params string[] validMethodNames)
217217
{
218-
var validateResult = validMethodNames.Contains(originalTransaction.MethodName)
218+
var validateResult = validMethodNames.Contains(MaybeRecoverInlineTransactionFunctionName(originalTransaction.MethodName))
219219
&& originalTransaction.To == validAddress;
220220
Assert(validateResult, "Invalid transaction.");
221221
}
222+
223+
private static string MaybeRecoverInlineTransactionFunctionName(string methodName)
224+
{
225+
var parts = methodName.Split('.');
226+
return parts.Length > 1 ? parts[^2] : methodName;
227+
}
222228

223229
private void RegisterTokenInfo(TokenInfo tokenInfo)
224230
{

protobuf/inline_transaction.proto

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
syntax = "proto3";
2+
3+
option csharp_namespace = "AElf.Types";
4+
5+
6+
import "aelf/core.proto";
7+
import "aelf/options.proto";
8+
9+
service InlineTransaction {
10+
}
11+
12+
message InlineTransactionCreated {
13+
option (aelf.is_event) = true;
14+
aelf.Transaction transaction = 1 [(aelf.is_indexed) = true];
15+
}

protobuf/test_virtual_address_contract.proto

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ service VirtualAddressContract {
1414
option (aelf.base) = "acs1.proto";
1515

1616
rpc VirtualAddressVote(VirtualAddressVoteInput) returns (google.protobuf.Empty);
17+
rpc VirtualAddressVoteWithInline(VirtualAddressVoteWithCountInput) returns (google.protobuf.Empty);
1718
rpc VirtualAddressWithdraw(aelf.Hash) returns (google.protobuf.Empty);
1819
rpc VirtualAddressChangeVotingOption(VirtualAddressChangeVotingOptionInput) returns (google.protobuf.Empty);
1920
rpc VirtualAddressClaimProfit(VirtualAddressClaimProfitInput) returns (google.protobuf.Empty);
@@ -32,6 +33,11 @@ message VirtualAddressVoteInput {
3233
aelf.Hash token = 4;
3334
}
3435

36+
message VirtualAddressVoteWithCountInput {
37+
VirtualAddressVoteInput vote_input = 1; // Existing input type
38+
int32 count = 2; // Additional count input
39+
}
40+
3541
message VirtualAddressChangeVotingOptionInput {
3642
bool is_reset = 1;
3743
aelf.Hash vote_id = 2;

protobuf/virtual_transaction.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ message VirtualTransactionCreated {
1717
string method_name = 4 [(aelf.is_indexed) = true];
1818
bytes params = 5;
1919
aelf.Address signatory = 6 [(aelf.is_indexed) = true];
20-
}
20+
}

src/AElf.ContractTestKit.AEDPoSExtension/UnitTestPlainTransactionExecutingService.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Threading;
33
using System.Threading.Tasks;
44
using AElf.Kernel;
5+
using AElf.Kernel.Blockchain.Application;
56
using AElf.Kernel.FeatureDisable.Core;
67
using AElf.Kernel.SmartContract;
78
using AElf.Kernel.SmartContract.Application;
@@ -13,8 +14,8 @@ public class UnitTestPlainTransactionExecutingService : PlainTransactionExecutin
1314
{
1415
public UnitTestPlainTransactionExecutingService(ISmartContractExecutiveService smartContractExecutiveService,
1516
IEnumerable<IPostExecutionPlugin> postPlugins, IEnumerable<IPreExecutionPlugin> prePlugins,
16-
ITransactionContextFactory transactionContextFactory, IFeatureDisableService featureDisableService) : base(
17-
smartContractExecutiveService, postPlugins, prePlugins, transactionContextFactory, featureDisableService)
17+
ITransactionContextFactory transactionContextFactory, IFeatureDisableService featureDisableService,IBlockchainService blockchainService) : base(
18+
smartContractExecutiveService, postPlugins, prePlugins, transactionContextFactory, featureDisableService,blockchainService)
1819
{
1920
}
2021

src/AElf.Kernel.Core/Extensions/TransactionExtensions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ public static int Size(this Transaction transaction)
1616

1717
public static bool VerifySignature(this Transaction transaction)
1818
{
19+
if (transaction.IsInlineWithTransactionId())
20+
{
21+
return true;
22+
}
1923
if (!transaction.VerifyFields())
2024
return false;
2125

@@ -27,7 +31,16 @@ public static bool VerifySignature(this Transaction transaction)
2731

2832
public static bool VerifyExpiration(this Transaction transaction, long chainBranchBlockHeight)
2933
{
34+
if (transaction.IsInlineWithTransactionId())
35+
{
36+
return true;
37+
}
3038
return transaction.RefBlockNumber <= chainBranchBlockHeight &&
3139
transaction.GetExpiryBlockNumber() > chainBranchBlockHeight;
3240
}
41+
42+
public static bool IsInlineWithTransactionId(this Transaction transaction)
43+
{
44+
return transaction.MethodName.Contains(".");
45+
}
3346
}

src/AElf.Kernel.SmartContract/AElf.Kernel.SmartContract.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,8 @@
2222
<ContractMessage Include="..\..\protobuf\virtual_transaction.proto">
2323
<Link>Protobuf\Proto\virtual_transaction.proto</Link>
2424
</ContractMessage>
25+
<ContractMessage Include="..\..\protobuf\inline_transaction.proto">
26+
<Link>Protobuf\Proto\inline_transaction.proto</Link>
27+
</ContractMessage>
2528
</ItemGroup>
2629
</Project>

src/AElf.Kernel.SmartContract/Application/PlainTransactionExecutingService.cs

Lines changed: 97 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.Linq;
44
using System.Threading;
55
using System.Threading.Tasks;
6+
using AElf.CSharp.Core.Extension;
7+
using AElf.Kernel.Blockchain.Application;
68
using AElf.Kernel.FeatureDisable.Core;
79
using AElf.Kernel.SmartContract.Domain;
810
using AElf.Kernel.SmartContract.Infrastructure;
@@ -23,14 +25,17 @@ public class PlainTransactionExecutingService : IPlainTransactionExecutingServic
2325
private readonly ISmartContractExecutiveService _smartContractExecutiveService;
2426
private readonly ITransactionContextFactory _transactionContextFactory;
2527
private readonly IFeatureDisableService _featureDisableService;
28+
private readonly IBlockchainService _blockchainService;
2629

2730
public PlainTransactionExecutingService(ISmartContractExecutiveService smartContractExecutiveService,
2831
IEnumerable<IPostExecutionPlugin> postPlugins, IEnumerable<IPreExecutionPlugin> prePlugins,
29-
ITransactionContextFactory transactionContextFactory, IFeatureDisableService featureDisableService)
32+
ITransactionContextFactory transactionContextFactory, IFeatureDisableService featureDisableService,
33+
IBlockchainService blockchainService)
3034
{
3135
_smartContractExecutiveService = smartContractExecutiveService;
3236
_transactionContextFactory = transactionContextFactory;
3337
_featureDisableService = featureDisableService;
38+
_blockchainService = blockchainService;
3439
_prePlugins = GetUniquePlugins(prePlugins);
3540
_postPlugins = GetUniquePlugins(postPlugins);
3641
Logger = NullLogger<PlainTransactionExecutingService>.Instance;
@@ -61,6 +66,7 @@ public async Task<List<ExecutionReturnSet>> ExecuteAsync(TransactionExecutingDto
6166
var singleTxExecutingDto = new SingleTransactionExecutingDto
6267
{
6368
Depth = 0,
69+
InlineWithTransactionIdCounter = new InlineWithTransactionIdCounter(),
6470
ChainContext = groupChainContext,
6571
Transaction = transaction,
6672
CurrentBlockTime = transactionExecutingDto.BlockHeader.Time,
@@ -71,7 +77,7 @@ public async Task<List<ExecutionReturnSet>> ExecuteAsync(TransactionExecutingDto
7177
var transactionExecutionTask = Task.Run(() => ExecuteOneAsync(singleTxExecutingDto,
7278
cancellationToken), cancellationToken);
7379

74-
trace = await transactionExecutionTask.WithCancellation(cancellationToken);
80+
trace = await transactionExecutionTask;
7581
}
7682
catch (OperationCanceledException)
7783
{
@@ -90,7 +96,7 @@ public async Task<List<ExecutionReturnSet>> ExecuteAsync(TransactionExecutingDto
9096
var result = GetTransactionResult(trace, transactionExecutingDto.BlockHeader.Height);
9197

9298
var returnSet = GetReturnSet(trace, result);
93-
returnSets.Add(returnSet);
99+
returnSets.AddRange(returnSet);
94100
}
95101

96102
return returnSets;
@@ -175,14 +181,22 @@ protected virtual async Task<TransactionTrace> ExecuteOneAsync(
175181

176182
#endregion
177183

184+
var methodName = txContext.Transaction.MethodName;
185+
var originMethodName = MaybeRecoverInlineTransactionFunctionName(methodName);
186+
txContext.Transaction.MethodName = originMethodName;
187+
178188
await executive.ApplyAsync(txContext);
179189

180190
if (txContext.Trace.IsSuccessful())
191+
{
192+
// Maybe layered method name.
193+
txContext.Transaction.MethodName = methodName;
181194
await ExecuteInlineTransactions(singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime,
182195
txContext, internalStateCache,
183196
internalChainContext,
184197
singleTxExecutingDto.OriginTransactionId,
185198
cancellationToken);
199+
}
186200

187201
#region PostTransaction
188202

@@ -221,11 +235,40 @@ private async Task ExecuteInlineTransactions(int depth, Timestamp currentBlockTi
221235
{
222236
var trace = txContext.Trace;
223237
internalStateCache.Update(txContext.Trace.GetStateSets());
238+
239+
var methodNameCount = new Dictionary<string, int>();
224240
foreach (var inlineTx in txContext.Trace.InlineTransactions)
225241
{
242+
var needTxId = NeedTransactionId(inlineTx.MethodName);
243+
if (needTxId)
244+
{
245+
txContext.InlineWithTransactionIdCounter.Increment();
246+
if (!methodNameCount.TryAdd(inlineTx.MethodName, 0))
247+
{
248+
methodNameCount[inlineTx.MethodName]++;
249+
inlineTx.MethodName =
250+
GenerateLayeredMethodNameForInlineTransaction(
251+
txContext.Transaction,
252+
inlineTx.MethodName,
253+
methodNameCount[inlineTx.MethodName]
254+
);
255+
}
256+
else
257+
{
258+
inlineTx.MethodName = GenerateLayeredMethodNameForInlineTransaction(
259+
txContext.Transaction,
260+
inlineTx.MethodName,
261+
0
262+
);
263+
}
264+
265+
await _blockchainService.AddTransactionsAsync([inlineTx]);
266+
}
267+
226268
var singleTxExecutingDto = new SingleTransactionExecutingDto
227269
{
228270
Depth = depth + 1,
271+
InlineWithTransactionIdCounter = txContext.InlineWithTransactionIdCounter,
229272
ChainContext = internalChainContext,
230273
Transaction = inlineTx,
231274
CurrentBlockTime = currentBlockTime,
@@ -246,6 +289,25 @@ private async Task ExecuteInlineTransactions(int depth, Timestamp currentBlockTi
246289
}
247290
}
248291

292+
private static string GenerateLayeredMethodNameForInlineTransaction(Transaction parentTx, string inlineFunctionName,
293+
int index)
294+
{
295+
var parentTxMethodName = parentTx.MethodName;
296+
inlineFunctionName = inlineFunctionName.StartsWith('.') ? inlineFunctionName[1..] : inlineFunctionName;
297+
return $"{parentTx.GetHash().ToHex()}.{parentTxMethodName}.{inlineFunctionName}.{index}";
298+
}
299+
300+
private static string MaybeRecoverInlineTransactionFunctionName(string methodName)
301+
{
302+
var parts = methodName.Split('.');
303+
return parts.Length > 1 ? parts[^2] : methodName;
304+
}
305+
306+
private static bool NeedTransactionId(string methodName)
307+
{
308+
return methodName.Contains('.');
309+
}
310+
249311
private async Task<bool> ExecutePluginOnPreTransactionStageAsync(IExecutive executive,
250312
ITransactionContext txContext,
251313
Timestamp currentBlockTime,
@@ -393,7 +455,7 @@ private TransactionResult GetTransactionResult(TransactionTrace trace, long bloc
393455
return txResult;
394456
}
395457

396-
private ExecutionReturnSet GetReturnSet(TransactionTrace trace, TransactionResult result)
458+
private IEnumerable<ExecutionReturnSet> GetReturnSet(TransactionTrace trace, TransactionResult result)
397459
{
398460
var returnSet = new ExecutionReturnSet
399461
{
@@ -402,12 +464,41 @@ private ExecutionReturnSet GetReturnSet(TransactionTrace trace, TransactionResul
402464
Bloom = result.Bloom,
403465
TransactionResult = result
404466
};
467+
var returnSets = new List<ExecutionReturnSet> { returnSet };
405468

406469
if (trace.IsSuccessful())
407470
{
408471
var transactionExecutingStateSets = trace.GetStateSets();
409472
returnSet = GetReturnSet(returnSet, transactionExecutingStateSets);
410473
returnSet.ReturnValue = trace.ReturnValue;
474+
475+
var inlineTxWithIdList = trace.GetAllInlineTransactions().Where(tx => NeedTransactionId(tx.MethodName));
476+
foreach (var inlineTx in inlineTxWithIdList)
477+
{
478+
var inlineTxId = inlineTx.GetHash();
479+
var inlineReturnSet = new ExecutionReturnSet
480+
{
481+
TransactionId = inlineTxId,
482+
Status = TransactionResultStatus.Mined,
483+
TransactionResult = new TransactionResult
484+
{
485+
TransactionId = inlineTxId,
486+
BlockNumber = result.BlockNumber,
487+
Status = TransactionResultStatus.Mined
488+
}
489+
};
490+
491+
// No need to execute GetReturnSet method, because changes are already set to `returnSet`.
492+
493+
returnSets.Add(inlineReturnSet);
494+
495+
Logger.LogWarning($"Inline tx id: {inlineTx.GetHash().ToHex()}\n{inlineTx}");
496+
var log = new InlineTransactionCreated()
497+
{
498+
Transaction = inlineTx
499+
};
500+
returnSet.TransactionResult.Logs.Add(log.ToLogEvent(inlineTx.To));
501+
}
411502
}
412503
else
413504
{
@@ -426,7 +517,7 @@ private ExecutionReturnSet GetReturnSet(TransactionTrace trace, TransactionResul
426517
var reads = trace.GetFlattenedReads();
427518
foreach (var read in reads) returnSet.StateAccesses[read.Key] = read.Value;
428519

429-
return returnSet;
520+
return returnSets;
430521
}
431522

432523
private ExecutionReturnSet GetReturnSet(ExecutionReturnSet returnSet,
@@ -476,6 +567,7 @@ protected ITransactionContext CreateTransactionContext(SingleTransactionExecutin
476567
singleTxExecutingDto.ChainContext, singleTxExecutingDto.OriginTransactionId, origin,
477568
singleTxExecutingDto.Depth, singleTxExecutingDto.CurrentBlockTime);
478569

570+
txContext.InlineWithTransactionIdCounter = singleTxExecutingDto.InlineWithTransactionIdCounter;
479571
return txContext;
480572
}
481573
}

src/AElf.Kernel.SmartContract/Dto/SingleTransactionExecutingDto.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ public class SingleTransactionExecutingDto
1313
public bool IsCancellable { get; set; } = true;
1414

1515
public Hash OriginTransactionId { get; set; }
16+
public InlineWithTransactionIdCounter InlineWithTransactionIdCounter { get; set; }
1617
}

0 commit comments

Comments
 (0)