Skip to content

Commit

Permalink
Merge pull request #3625 from AElfProject/feature/transaction-result-…
Browse files Browse the repository at this point in the history
…optimize

Transaction status result optimization
  • Loading branch information
JimAelf authored Dec 3, 2024
2 parents 85e9efd + 39398fa commit f21fc2d
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 0 deletions.
2 changes: 2 additions & 0 deletions protobuf/aelf/core.proto
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ enum TransactionResultStatus {
PENDING_VALIDATION = 5;
// Transaction validation failed.
NODE_VALIDATION_FAILED = 6;
// Transaction is expired
EXPIRED = 7;
}

message TransactionResult {
Expand Down
5 changes: 5 additions & 0 deletions src/AElf.WebApp.Application.Chain/Dto/TransactionResultDto.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
using System;

namespace AElf.WebApp.Application.Chain.Dto;

public class TransactionResultDto
{
public string TransactionId { get; set; }

[Obsolete("The Status is obsolete. Use StatusV2 instead.")]
public string Status { get; set; }

public string StatusV2 { get; set; }

public LogEventDto[] Logs { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ namespace AElf.WebApp.Application.Chain;
public interface ITransactionResultAppService
{
Task<TransactionResultDto> GetTransactionResultAsync(string transactionId);

Task<TransactionResultDto> GetTransactionResultV2Async(string transactionId);

Task<List<TransactionResultDto>> GetTransactionResultsAsync(string blockHash, int offset = 0,
int limit = 10);
Expand Down Expand Up @@ -130,6 +132,72 @@ await _transactionResultProxyService.InvalidTransactionResultService.GetInvalidT
}
return output;
}
/// <summary>
/// Get the current status of a transaction, available since V1.12.0
/// </summary>
/// <param name="transactionId">transaction id</param>
/// <returns></returns>
public async Task<TransactionResultDto> GetTransactionResultV2Async(string transactionId)
{
Hash transactionIdHash;
try
{
transactionIdHash = Hash.LoadFromHex(transactionId);
}
catch
{
throw new UserFriendlyException(Error.Message[Error.InvalidTransactionId],
Error.InvalidTransactionId.ToString());
}

var transactionResult = await GetTransactionResultAsync(transactionIdHash);
var output = _objectMapper.GetMapper()
.Map<TransactionResult, TransactionResultDto>(transactionResult,
opt => opt.Items[TransactionProfile.ErrorTrace] = _webAppOptions.IsDebugMode);
output.StatusV2 = output.Status;

var transaction = await _transactionManager.GetTransactionAsync(transactionResult.TransactionId);
output.Transaction = _objectMapper.Map<Transaction, TransactionDto>(transaction);
output.TransactionSize = transaction?.CalculateSize() ?? 0;

var chain = await _blockchainService.GetChainAsync();
if (transactionResult.Status == TransactionResultStatus.Pending &&
chain.BestChainHeight - output.Transaction?.RefBlockNumber > KernelConstants.ReferenceBlockValidPeriod)
{
output.StatusV2 = TransactionResultStatus.Expired.ToString().ToUpper();
return output;
}

if (transactionResult.Status != TransactionResultStatus.NotExisted)
{
await FormatTransactionParamsAsync(output.Transaction, transaction.Params);
return output;
}

var validationStatus = _transactionResultStatusCacheProvider.GetTransactionResultStatus(transactionIdHash);
if (validationStatus != null)
{
output.StatusV2 = validationStatus.TransactionResultStatus.ToString().ToUpper();
output.Error =
TransactionErrorResolver.TakeErrorMessage(validationStatus.Error, _webAppOptions.IsDebugMode);
return output;
}

if (_transactionOptions.StoreInvalidTransactionResultEnabled)
{
var failedTransactionResult =
await _transactionResultProxyService.InvalidTransactionResultService.GetInvalidTransactionResultAsync(
transactionIdHash);
if (failedTransactionResult != null)
{
output.StatusV2 = failedTransactionResult.Status.ToString().ToUpper();
output.Error = failedTransactionResult.Error;
return output;
}
}

return output;
}

/// <summary>
/// Get multiple transaction results.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,37 @@ public async Task Get_TransactionResult_Success_Test()
response.BlockNumber.ShouldBe(block.Height);
response.BlockHash.ShouldBe(block.GetHash().ToHex());
}

[Fact]
public async Task Get_TransactionResultV2_Expired_Test()
{
// Generate a transaction
var transaction = await _osTestHelper.GenerateTransferTransaction();

// Push chain height to be ref_block_number + at least 512
await MineSomeBlocks(520);
var transactionHex = transaction.GetHash().ToHex();

// Broadcast expired transaction
await _osTestHelper.BroadcastTransactions(new List<Transaction> { transaction });

// Check transaction status
var response = await GetResponseAsObjectAsync<TransactionResultDto>(
$"/api/blockChain/transactionResultV2?transactionId={transactionHex}");
response.StatusV2.ShouldBe(TransactionResultStatus.Expired.ToString().ToUpper());
}

private async Task MineSomeBlocks(int blockNumber)
{
var heightBefore = (await _osTestHelper.GetChainContextAsync()).BlockHeight;
for (var i = 0; i < blockNumber; i++)
{
await _osTestHelper.MinedOneBlock();
}

var heightAfter = (await _osTestHelper.GetChainContextAsync()).BlockHeight;
heightAfter.ShouldBe(heightBefore + blockNumber);
}

[Fact]
public async Task Get_Failed_TransactionResult_Success_Test()
Expand Down

0 comments on commit f21fc2d

Please sign in to comment.