Skip to content

Commit

Permalink
Merge branch 'release/1.12.0' into feature/mq
Browse files Browse the repository at this point in the history
extend seed NFT expiration time
  • Loading branch information
JimAelf committed Dec 3, 2024
2 parents 6880c6b + 9d567e4 commit 599be60
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 0 deletions.
29 changes: 29 additions & 0 deletions contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,35 @@ public override Int32Value GetMaxBatchApproveCount(Empty input)
};
}

public override Empty ExtendSeedExpirationTime(ExtendSeedExpirationTimeInput input)
{
var tokenInfo = GetTokenInfo(input.Symbol);
if (tokenInfo == null)
{
throw new AssertionException("Seed NFT does not exist.");
}

Assert(tokenInfo.Owner == Context.Sender, "Sender is not Seed NFT owner.");
var oldExpireTimeLong = 0L;
if (tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey,
out var oldExpireTime))
{
long.TryParse(oldExpireTime, out oldExpireTimeLong);
}

tokenInfo.ExternalInfo.Value[TokenContractConstants.SeedExpireTimeExternalInfoKey] =
input.ExpirationTime.ToString();
State.TokenInfos[input.Symbol] = tokenInfo;
Context.Fire(new SeedExpirationTimeUpdated
{
ChainId = tokenInfo.IssueChainId,
Symbol = input.Symbol,
OldExpirationTime = oldExpireTimeLong,
NewExpirationTime = input.ExpirationTime
});
return new Empty();
}

private int GetMaxBatchApproveCount()
{
return State.MaxBatchApproveCount.Value == 0
Expand Down
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
16 changes: 16 additions & 0 deletions protobuf/token_contract_impl.proto
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ service TokenContractImpl {
rpc GetMaxBatchApproveCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) {

}

rpc ExtendSeedExpirationTime (ExtendSeedExpirationTimeInput) returns (google.protobuf.Empty) {
}
}

message AdvanceResourceTokenInput {
Expand Down Expand Up @@ -444,4 +447,17 @@ message ModifyTokenIssuerAndOwnerInput {

message SetTokenIssuerAndOwnerModificationEnabledInput{
bool enabled = 1;
}

message ExtendSeedExpirationTimeInput {
string symbol = 1;
int64 expiration_time = 2;
}

message SeedExpirationTimeUpdated {
option (aelf.is_event) = true;
int32 chain_id = 1;
string symbol = 2;
int64 old_expiration_time = 3;
int64 new_expiration_time = 4;
}
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
11 changes: 11 additions & 0 deletions test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1893,4 +1893,15 @@ public async Task TokenIssuerAndOwnerModification_Test()
result.TransactionResult.Error.ShouldContain("Set token issuer and owner disabled.");

}

[Theory]
[InlineData("SEED-0", 1731927992000)]
public async Task ExtendSeedExpirationTime_Test(string symbol, long expirationTime)
{
ExtendSeedExpirationTimeInput input = new ExtendSeedExpirationTimeInput();
input.Symbol = symbol;
input.ExpirationTime = expirationTime;

await TokenContractStub.ExtendSeedExpirationTime.CallAsync(input);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,7 @@ internal async Task<IExecutionResult<Empty>> CreateMutiTokenWithExceptionAsync(
await CreateSeedNftAsync(stub, createInput);
return await stub.Create.SendWithExceptionAsync(createInput);
}



}
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 599be60

Please sign in to comment.