diff --git a/.github/workflows/sonarqube.yaml b/.github/workflows/sonarqube.yaml index dbfca652b6..b87ff0cf93 100644 --- a/.github/workflows/sonarqube.yaml +++ b/.github/workflows/sonarqube.yaml @@ -15,7 +15,7 @@ jobs: with: dotnet-version: '8.0' - name: Create temporary global.json - run: echo '{"sdk":{"version":"8.0.303"}}' > ./global.json + run: echo '{"sdk":{"version":"8.0.*"}}' > ./global.json - name: Set up JDK 17 uses: actions/setup-java@v1 with: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9cae4c73c7..638b5c27f1 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,20 +1,20 @@ # Azure Pipelines configuration file jobs: -# - template: templates/build-template-window.yml -# parameters: -# parts: 3 -# n: 1 -# codecoverage: true -# - template: templates/build-template-window.yml -# parameters: -# parts: 3 -# n: 2 -# codecoverage: false -# - template: templates/build-template-window.yml -# parameters: -# parts: 3 -# n: 3 -# codecoverage: false + # - template: templates/build-template-window.yml + # parameters: + # parts: 3 + # n: 1 + # codecoverage: true + # - template: templates/build-template-window.yml + # parameters: + # parts: 3 + # n: 2 + # codecoverage: false + # - template: templates/build-template-window.yml + # parameters: + # parts: 3 + # n: 3 + # codecoverage: false - template: templates/build-template-linux.yml parameters: parts: 3 @@ -40,9 +40,9 @@ jobs: parts: 3 n: 2 codecoverage: true - - template: templates/build-template-macos.yml - parameters: - parts: 3 - n: 3 - codecoverage: true + # - template: templates/build-template-macos.yml + # parameters: + # parts: 3 + # n: 3 + # codecoverage: true \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs index 88632c10ff..b708306d99 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs @@ -127,10 +127,12 @@ private void ProcessNextRound(NextRoundInput input) { var minersCount = GetMinersCount(nextRound); if (minersCount != 0 && State.ElectionContract.Value != null) + { State.ElectionContract.UpdateMinersCount.Send(new UpdateMinersCountInput { MinersCount = minersCount }); + } } } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 6adcf01a2a..7c24cb4151 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -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 diff --git a/global.json b/global.json index b76a0b882f..70976d298f 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "8.0.x" + "version": "8.0.*" } } \ No newline at end of file diff --git a/nuget.config b/nuget.config index 8b19203c51..e75cd52656 100644 --- a/nuget.config +++ b/nuget.config @@ -1,6 +1,9 @@ + + + \ No newline at end of file diff --git a/protobuf/aelf/core.proto b/protobuf/aelf/core.proto index 4fe3a5bcf4..d2812d46f7 100644 --- a/protobuf/aelf/core.proto +++ b/protobuf/aelf/core.proto @@ -59,6 +59,8 @@ enum TransactionResultStatus { PENDING_VALIDATION = 5; // Transaction validation failed. NODE_VALIDATION_FAILED = 6; + // Transaction is expired + EXPIRED = 7; } message TransactionResult { diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index 5885914e80..3ae6ffa2c5 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -182,6 +182,9 @@ service TokenContractImpl { rpc GetMaxBatchApproveCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) { } + + rpc ExtendSeedExpirationTime (ExtendSeedExpirationTimeInput) returns (google.protobuf.Empty) { + } } message AdvanceResourceTokenInput { @@ -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; } \ No newline at end of file diff --git a/protobuf/virtual_transaction.proto b/protobuf/virtual_transaction.proto index 8abb9db10c..914ef1e76f 100644 --- a/protobuf/virtual_transaction.proto +++ b/protobuf/virtual_transaction.proto @@ -17,4 +17,4 @@ message VirtualTransactionCreated { string method_name = 4 [(aelf.is_indexed) = true]; bytes params = 5; aelf.Address signatory = 6 [(aelf.is_indexed) = true]; -} \ No newline at end of file +} diff --git a/src/AElf.CSharp.CodeOps/AElf.CSharp.CodeOps.csproj b/src/AElf.CSharp.CodeOps/AElf.CSharp.CodeOps.csproj index dc5501294c..74a45d8ccf 100644 --- a/src/AElf.CSharp.CodeOps/AElf.CSharp.CodeOps.csproj +++ b/src/AElf.CSharp.CodeOps/AElf.CSharp.CodeOps.csproj @@ -10,8 +10,7 @@ - - + diff --git a/src/AElf.CSharp.CodeOps/Validators/Method/ArrayValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Method/ArrayValidator.cs index 5a58387f14..08fced5f36 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Method/ArrayValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Method/ArrayValidator.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading; using AElf.CSharp.Core; +using AElf.Types; using Mono.Cecil; using Mono.Cecil.Cil; using Volo.Abp.DependencyInjection; @@ -24,7 +25,7 @@ public class ArrayValidator : IValidator, ITransientDependency .LimitByTotalSize(typeof(decimal), sizeof(decimal)) .LimitByTotalSize(typeof(char), sizeof(char)) .LimitByTotalSize(typeof(String), 128) // Need to limit the size of strings by disallowing String.Concat - + .LimitByTotalSize(typeof(BigIntValue), 128) // It isn't possible to estimate runtime sizes for below, so limit by count .LimitByCount(typeof(Type), 5) .LimitByCount(typeof(Object), 5) // Support object in Linq queries diff --git a/src/AElf.CSharp.CodeOps/Validators/Module/ContractStructureValidator.cs b/src/AElf.CSharp.CodeOps/Validators/Module/ContractStructureValidator.cs index 59f4209d5a..5fb83cd951 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Module/ContractStructureValidator.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Module/ContractStructureValidator.cs @@ -231,6 +231,8 @@ private bool IsBadStateField(FieldDefinition field) if (_allowedStateTypes.Contains(field.FieldType.FullName)) return false; + if(field.FieldType.Resolve().BaseType.FullName == typeof(StructuredState).FullName) + return false; // If not ContractReferenceState then it is not allowed return field.FieldType.Resolve().BaseType.FullName != typeof(ContractReferenceState).FullName; } diff --git a/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistProvider.cs b/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistProvider.cs index d488b1057e..41e3ba704d 100644 --- a/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistProvider.cs +++ b/src/AElf.CSharp.CodeOps/Validators/Whitelist/IWhitelistProvider.cs @@ -5,6 +5,9 @@ using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; +using AElf.Cryptography.Bn254; +using AElf.Cryptography.EdDSA; +using AElf.Cryptography.Keccak; using AElf.Cryptography.SecretSharing; using AElf.CSharp.Core; using AElf.Kernel.SmartContract; @@ -50,7 +53,6 @@ private void WhitelistAssemblies(Whitelist whitelist) .Assembly(typeof(SecretSharingHelper).Assembly, Trust.Partial) // AElf.Cryptography .Assembly(typeof(ISmartContractBridgeContext).Assembly, Trust.Full) // AElf.Kernel.SmartContract.Shared .Assembly(typeof(Groth16.Net.Verifier).Assembly, Trust.Full) // AElf.Cryptography.ECDSA - .Assembly(typeof(Poseidon.Net.Poseidon).Assembly, Trust.Full) ; } @@ -64,6 +66,15 @@ private void WhitelistSystemTypes(Whitelist whitelist) .Type("Func`1", Permission.Allowed) // Required for protobuf generated code .Type("Func`2", Permission.Allowed) // Required for protobuf generated code .Type("Func`3", Permission.Allowed) // Required for protobuf generated code + .Type("Func`4", Permission.Allowed) + .Type("ValueTuple`1", Permission.Allowed) + .Type("ValueTuple`2", Permission.Allowed) + .Type("ValueTuple`3", Permission.Allowed) + .Type("ValueTuple`4", Permission.Allowed) + .Type("ValueTuple`5", Permission.Allowed) + .Type("ValueTuple`6", Permission.Allowed) + .Type("ValueTuple`7", Permission.Allowed) + .Type("ValueTuple`8", Permission.Allowed) .Type("Nullable`1", Permission.Allowed) // Required for protobuf generated code .Type(typeof(BitConverter), Permission.Denied, member => member .Member(nameof(BitConverter.GetBytes), Permission.Allowed)) @@ -160,6 +171,27 @@ private void WhitelistOthers(Whitelist whitelist) ) ; } + + private void WhitelistCryptographyHelpers(Whitelist whitelist) + { + whitelist + // Selectively allowed types and members + .Namespace("AElf.Cryptography.Bn254", Permission.Denied, type => type + .Type(typeof(Bn254Helper), Permission.Denied, member => member + .Member(nameof(Bn254Helper.Bn254Pairing), Permission.Allowed) + .Member(nameof(Bn254Helper.Bn254G1Add), Permission.Allowed) + .Member(nameof(Bn254Helper.Bn254G1Mul), Permission.Allowed) + )) + .Namespace("AElf.Cryptography.EdDSA", Permission.Denied, type => type + .Type(typeof(EdDsaHelper), Permission.Denied, member => member + .Member(nameof(EdDsaHelper.Ed25519Verify), Permission.Allowed) + )) + .Namespace("AElf.Cryptography.Keccak", Permission.Denied, type => type + .Type(typeof(KeccakHelper), Permission.Denied, member => member + .Member(nameof(KeccakHelper.Keccak256), Permission.Allowed) + )) + ; + } private Whitelist CreateWhitelist() { @@ -169,6 +201,7 @@ private Whitelist CreateWhitelist() WhitelistReflectionTypes(whitelist); WhitelistLinqAndCollections(whitelist); WhitelistOthers(whitelist); + WhitelistCryptographyHelpers(whitelist); return whitelist; } } diff --git a/src/AElf.Cryptography/AElf.Cryptography.csproj b/src/AElf.Cryptography/AElf.Cryptography.csproj index 1f5c07064d..641e967bdd 100644 --- a/src/AElf.Cryptography/AElf.Cryptography.csproj +++ b/src/AElf.Cryptography/AElf.Cryptography.csproj @@ -10,6 +10,9 @@ + + + diff --git a/src/AElf.Cryptography/Bn254/Bn254Helper.cs b/src/AElf.Cryptography/Bn254/Bn254Helper.cs new file mode 100644 index 0000000000..0cf74fc3bc --- /dev/null +++ b/src/AElf.Cryptography/Bn254/Bn254Helper.cs @@ -0,0 +1,38 @@ +using Bn254.Net; +using NetBn254 = Bn254.Net; + +namespace AElf.Cryptography.Bn254 +{ + public static class Bn254Helper + { + public static (byte[] x, byte[] y) Bn254G1Mul(byte[] x1, byte[] y1, byte[] s) + { + var (xUInt256, yUInt256) = NetBn254.Bn254.Mul(UInt256.FromBigEndianBytes(x1), + UInt256.FromBigEndianBytes(y1), + UInt256.FromBigEndianBytes(s)); + return (xUInt256.ToBigEndianBytes(), yUInt256.ToBigEndianBytes()); + } + + public static (byte[] x3, byte[] y3) Bn254G1Add(byte[] x1, byte[] y1, byte[] x2, byte[] y2) + { + var (x3UInt256, y3UInt256) = NetBn254.Bn254.Add(UInt256.FromBigEndianBytes(x1), + UInt256.FromBigEndianBytes(y1), + UInt256.FromBigEndianBytes(x2), UInt256.FromBigEndianBytes(y2)); + return (x3UInt256.ToBigEndianBytes(), y3UInt256.ToBigEndianBytes()); + } + + public static bool Bn254Pairing((byte[], byte[], byte[], byte[], byte[], byte[])[] input) + { + var elements = new (UInt256, UInt256, UInt256, UInt256, UInt256, UInt256)[input.Length]; + for (var i = 0; i < input.Length; i++) + { + var (x1, y1, x2, y2, x3, y3) = input[i]; + elements[i] = (UInt256.FromBigEndianBytes(x1), UInt256.FromBigEndianBytes(y1), + UInt256.FromBigEndianBytes(x2), UInt256.FromBigEndianBytes(y2), + UInt256.FromBigEndianBytes(x3), UInt256.FromBigEndianBytes(y3)); + } + + return NetBn254.Bn254.Pairing(elements); + } + } +} \ No newline at end of file diff --git a/src/AElf.Cryptography/EdDSA/EdDsaHelper.cs b/src/AElf.Cryptography/EdDSA/EdDsaHelper.cs new file mode 100644 index 0000000000..02046e8a02 --- /dev/null +++ b/src/AElf.Cryptography/EdDSA/EdDsaHelper.cs @@ -0,0 +1,22 @@ +using System; +using Rebex.Security.Cryptography; + +namespace AElf.Cryptography.EdDSA +{ + public static class EdDsaHelper + { + public static bool Ed25519Verify(byte[] signature, byte[] message, byte[] publicKey) + { + try + { + var instance = new Ed25519(); + instance.FromPublicKey(publicKey); + return instance.VerifyMessage(message, signature); + } + catch (Exception e) + { + return false; + } + } + } +} \ No newline at end of file diff --git a/src/AElf.Cryptography/Keccak/KeccakHelper.cs b/src/AElf.Cryptography/Keccak/KeccakHelper.cs new file mode 100644 index 0000000000..dbb182f29c --- /dev/null +++ b/src/AElf.Cryptography/Keccak/KeccakHelper.cs @@ -0,0 +1,12 @@ +using Nethereum.Util; + +namespace AElf.Cryptography.Keccak +{ + public static class KeccakHelper + { + public static byte[] Keccak256(byte[] message) + { + return Sha3Keccack.Current.CalculateHash(message); + } + } +} \ No newline at end of file diff --git a/src/AElf.Kernel.FeatureDisable.Core/AElf.Kernel.FeatureDisable.Core.csproj b/src/AElf.Kernel.FeatureDisable.Core/AElf.Kernel.FeatureDisable.Core.csproj index 7b39f518d5..991781b591 100644 --- a/src/AElf.Kernel.FeatureDisable.Core/AElf.Kernel.FeatureDisable.Core.csproj +++ b/src/AElf.Kernel.FeatureDisable.Core/AElf.Kernel.FeatureDisable.Core.csproj @@ -4,6 +4,8 @@ net8.0 enable enable + Release + true diff --git a/src/AElf.Kernel.FeatureDisable/AElf.Kernel.FeatureDisable.csproj b/src/AElf.Kernel.FeatureDisable/AElf.Kernel.FeatureDisable.csproj index fae7fc0cdf..04323c5ffe 100644 --- a/src/AElf.Kernel.FeatureDisable/AElf.Kernel.FeatureDisable.csproj +++ b/src/AElf.Kernel.FeatureDisable/AElf.Kernel.FeatureDisable.csproj @@ -4,6 +4,8 @@ net8.0 enable enable + Release + true diff --git a/src/AElf.Kernel.SmartContract/Application/IExecutionObserverThresholdProvider.cs b/src/AElf.Kernel.SmartContract/Application/IExecutionObserverThresholdProvider.cs index 22df31d5a3..1515ab0c20 100644 --- a/src/AElf.Kernel.SmartContract/Application/IExecutionObserverThresholdProvider.cs +++ b/src/AElf.Kernel.SmartContract/Application/IExecutionObserverThresholdProvider.cs @@ -33,7 +33,7 @@ public IExecutionObserverThreshold GetExecutionObserverThreshold(IBlockIndex blo var branchCountObserverThreshold = GetBlockExecutedData(blockIndex, BranchCountThresholdKey)?.Value ?? SmartContractConstants.ExecutionBranchThreshold; var callCountObserverThreshold = GetBlockExecutedData(blockIndex, CallCountThresholdKey)?.Value ?? - SmartContractConstants.ExecutionBranchThreshold; + SmartContractConstants.ExecutionCallThreshold; return new ExecutionObserverThreshold { ExecutionBranchThreshold = branchCountObserverThreshold, diff --git a/src/AElf.Types/Types/BigIntValue.cs b/src/AElf.Types/Types/BigIntValue.cs index 38ddc94df6..bd8c446065 100644 --- a/src/AElf.Types/Types/BigIntValue.cs +++ b/src/AElf.Types/Types/BigIntValue.cs @@ -5,9 +5,30 @@ namespace AElf.Types { - public partial class BigIntValue : IComparable, IComparable { + #region Frequent Values + + public static BigIntValue Zero => new BigIntValue { Value = "0" }; + public static BigIntValue One => new BigIntValue { Value = "1" }; + + #endregion + + public static BigIntValue FromBigEndianBytes(byte[] bigEndianBytes) + { + var bigInteger = new BigInteger(bigEndianBytes, true, true); + return new BigIntValue + { + Value = bigInteger.ToString() + }; + } + + public byte[] ToBigEndianBytes() + { + var bigInteger = ConvertStringToBigInteger(Value); + return bigInteger.ToByteArray(true, true); + } + public int CompareTo(object obj) { if (!(obj is BigIntValue bigInt)) throw new InvalidOperationException(); @@ -126,6 +147,43 @@ private static bool LessThan(in BigIntValue a, in BigIntValue b) return aBigInt < bBigInt; } + #region Operators + + public static BigIntValue operator %(BigIntValue a, BigIntValue b) + { + return BigInteger.Remainder(ConvertStringToBigInteger(a.Value), ConvertStringToBigInteger(b.Value)) + .ToString(); + } + + public static BigIntValue operator +(BigIntValue a, BigIntValue b) + { + return BigInteger.Add(ConvertStringToBigInteger(a.Value), ConvertStringToBigInteger(b.Value)).ToString(); + } + + public static BigIntValue operator -(BigIntValue a, BigIntValue b) + { + return BigInteger.Subtract(ConvertStringToBigInteger(a.Value), ConvertStringToBigInteger(b.Value)) + .ToString(); + } + + public static BigIntValue operator *(BigIntValue a, BigIntValue b) + { + return BigInteger.Multiply(ConvertStringToBigInteger(a.Value), ConvertStringToBigInteger(b.Value)) + .ToString(); + } + + public static bool operator ==(BigIntValue a, BigIntValue b) + { + return ConvertStringToBigInteger(a?.Value ?? "0") == ConvertStringToBigInteger(b?.Value ?? "0"); + } + + public static bool operator !=(BigIntValue a, BigIntValue b) + { + return !(a == b); + } + + #endregion + #region < <= > >= public static bool operator <(in BigIntValue a, in BigIntValue b) diff --git a/src/AElf.WebApp.Application.Chain/Dto/TransactionResultDto.cs b/src/AElf.WebApp.Application.Chain/Dto/TransactionResultDto.cs index e76f92a941..49459d3dc5 100644 --- a/src/AElf.WebApp.Application.Chain/Dto/TransactionResultDto.cs +++ b/src/AElf.WebApp.Application.Chain/Dto/TransactionResultDto.cs @@ -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 StatusWithBVP instead.")] public string Status { get; set; } + + public string StatusWithBVP { get; set; } public LogEventDto[] Logs { get; set; } diff --git a/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs b/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs index 483dbb4366..c382c0a8de 100644 --- a/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs @@ -25,6 +25,8 @@ public interface ITransactionResultAppService { Task GetTransactionResultAsync(string transactionId); + Task GetTransactionResultWithBVPAsync(string transactionId); + Task> GetTransactionResultsAsync(string blockHash, int offset = 0, int limit = 10); @@ -118,9 +120,73 @@ await _transactionResultProxyService.InvalidTransactionResultService.GetInvalidT return output; } } + return output; + } + /// + /// Get the current status of a transaction, available since V1.12.0 + /// + /// transaction id + /// + public async Task GetTransactionResultWithBVPAsync(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, + opt => opt.Items[TransactionProfile.ErrorTrace] = _webAppOptions.IsDebugMode); + output.StatusWithBVP = output.Status; + + var transaction = await _transactionManager.GetTransactionAsync(transactionResult.TransactionId); + output.Transaction = _objectMapper.Map(transaction); + output.TransactionSize = transaction?.CalculateSize() ?? 0; + + var chain = await _blockchainService.GetChainAsync(); + if (transactionResult.Status == TransactionResultStatus.Pending && + chain.BestChainHeight - output.Transaction?.RefBlockNumber > KernelConstants.ReferenceBlockValidPeriod) + { + output.StatusWithBVP = 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.StatusWithBVP = 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.StatusWithBVP = failedTransactionResult.Status.ToString().ToUpper(); + output.Error = failedTransactionResult.Error; + return output; + } + } return output; - } /// diff --git a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs index cde20e76c9..5aeca9457c 100644 --- a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs +++ b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs @@ -18,7 +18,6 @@ using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel; -using AElf.Sdk.CSharp; using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index 201e56d6e6..24d06e3eec 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -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); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.VirtualTransactionEvent/Action.cs b/test/AElf.Contracts.TestContract.VirtualTransactionEvent/Action.cs index 99fa3348e2..9703205edf 100644 --- a/test/AElf.Contracts.TestContract.VirtualTransactionEvent/Action.cs +++ b/test/AElf.Contracts.TestContract.VirtualTransactionEvent/Action.cs @@ -1,5 +1,4 @@ -using AElf.Sdk.CSharp; -using AElf.Types; +using AElf.Types; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.TestContract.VirtualTransactionEvent; diff --git a/test/AElf.Cryptography.Tests/Bn254HelperTest.cs b/test/AElf.Cryptography.Tests/Bn254HelperTest.cs new file mode 100644 index 0000000000..5a46f165bc --- /dev/null +++ b/test/AElf.Cryptography.Tests/Bn254HelperTest.cs @@ -0,0 +1,111 @@ +using AElf.Cryptography.Bn254; +using AElf.Types; +using Bn254.Net; +using Shouldly; +using Xunit; +using NetBn254 = Bn254.Net; + +namespace AElf.Cryptography.Tests; + +public class EdDsaHelperTest +{ + public static byte[] ToBytes32(BigIntValue value) + { + var bytes = value.ToBigEndianBytes(); + var newArray = new byte[32]; + for (int i = 0; i < bytes.Length; i++) + { + newArray[31 - i] = bytes[bytes.Length - 1 - i]; + } + + return newArray; + } + + [Fact] + public void Bn254G1Mul_Test() + { + // Arrange + byte[] x1 = ToBytes32(new BigIntValue(0)); + byte[] y1 = ToBytes32(new BigIntValue(0)); + byte[] scalar = ToBytes32(new BigIntValue(0)); + + // use raw api to compute result + var (expectedXuInt256, expectedYuInt256) = NetBn254.Bn254.Mul( + UInt256.FromBigEndianBytes(x1), + UInt256.FromBigEndianBytes(y1), + UInt256.FromBigEndianBytes(scalar) + ); + var expectedX = expectedXuInt256.ToBigEndianBytes(); + var expectedY = expectedYuInt256.ToBigEndianBytes(); + + // Act + var (xResult, yResult) = Bn254Helper.Bn254G1Mul(x1, y1, scalar); + + // Assert + xResult.ShouldBe(expectedX); + yResult.ShouldBe(expectedY); + } + + [Fact] + public void Bn254G1Add_Test() + { + // Arrange + byte[] x1 = ToBytes32(new BigIntValue(0)); + byte[] y1 = ToBytes32(new BigIntValue(0)); + byte[] x2 = ToBytes32(new BigIntValue(0)); + byte[] y2 = ToBytes32(new BigIntValue(0)); + + // Use raw API to compute expected results + var (expectedX3UInt256, expectedY3UInt256) = NetBn254.Bn254.Add( + UInt256.FromBigEndianBytes(x1), + UInt256.FromBigEndianBytes(y1), + UInt256.FromBigEndianBytes(x2), + UInt256.FromBigEndianBytes(y2) + ); + var expectedX3 = expectedX3UInt256.ToBigEndianBytes(); + var expectedY3 = expectedY3UInt256.ToBigEndianBytes(); + + // Act + var (x3Result, y3Result) = Bn254Helper.Bn254G1Add(x1, y1, x2, y2); + + // Assert + x3Result.ShouldBe(expectedX3); + y3Result.ShouldBe(expectedY3); + } + + [Fact] + public void Bn254Pairing_Test() + { + // Arrange + var input = new (byte[], byte[], byte[], byte[], byte[], byte[])[] + { + ( + ToBytes32(new BigIntValue(0)), + ToBytes32(new BigIntValue(0)), + ToBytes32(new BigIntValue(0)), + ToBytes32(new BigIntValue(0)), + ToBytes32(new BigIntValue(0)), + ToBytes32(new BigIntValue(0)) + ) + }; + + // Use raw API to compute expected results + bool expected = NetBn254.Bn254.Pairing(new (UInt256, UInt256, UInt256, UInt256, UInt256, UInt256)[] + { + ( + UInt256.FromBigEndianBytes(input[0].Item1), + UInt256.FromBigEndianBytes(input[0].Item2), + UInt256.FromBigEndianBytes(input[0].Item3), + UInt256.FromBigEndianBytes(input[0].Item4), + UInt256.FromBigEndianBytes(input[0].Item5), + UInt256.FromBigEndianBytes(input[0].Item6) + ) + }); + + // Act + bool result = Bn254Helper.Bn254Pairing(input); + + // Assert + result.ShouldBe(expected); + } +} \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/EdDsaHelperTest.cs b/test/AElf.Cryptography.Tests/EdDsaHelperTest.cs new file mode 100644 index 0000000000..443415463c --- /dev/null +++ b/test/AElf.Cryptography.Tests/EdDsaHelperTest.cs @@ -0,0 +1,25 @@ +using AElf.Cryptography.EdDSA; +using Shouldly; +using Xunit; + +namespace AElf.Cryptography.Tests; + +public class Bn254HelperTest +{ + [Fact] + public void Ed25519Verify_Test() + { + var publicKey = "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"; + var message = ""; + var signature = + "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"; + + var publicKeyBytes = ByteArrayHelper.HexStringToByteArray(publicKey); + var messageBytes = ByteArrayHelper.HexStringToByteArray(message); + var signatureBytes = ByteArrayHelper.HexStringToByteArray(signature); + + var ed25519VerifyResult = EdDsaHelper.Ed25519Verify(signatureBytes, messageBytes, publicKeyBytes); + + ed25519VerifyResult.ShouldBe(true); + } +} \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/KeccakHelperTest.cs b/test/AElf.Cryptography.Tests/KeccakHelperTest.cs new file mode 100644 index 0000000000..d6c8faa3fa --- /dev/null +++ b/test/AElf.Cryptography.Tests/KeccakHelperTest.cs @@ -0,0 +1,22 @@ +using System.Text; +using AElf.Cryptography.Keccak; +using Nethereum.Util; +using Shouldly; +using Xunit; + +namespace AElf.Cryptography.Tests; + +public class KeccakHelperTest +{ + [Fact] + public void Keccak256_Test() + { + byte[] message = Encoding.UTF8.GetBytes("Test message"); + + var expectedHash = Sha3Keccack.Current.CalculateHash(message); + + var computedHash = KeccakHelper.Keccak256(message); + + computedHash.ShouldBe(expectedHash); + } +} \ No newline at end of file diff --git a/test/AElf.Types.Tests/BigIntegerTest.cs b/test/AElf.Types.Tests/BigIntegerTest.cs new file mode 100644 index 0000000000..056fcca2a9 --- /dev/null +++ b/test/AElf.Types.Tests/BigIntegerTest.cs @@ -0,0 +1,176 @@ +using System; +using System.Numerics; +using Xunit; + +namespace AElf.Types.Tests; + +public class BigIntegerTest +{ + [Fact] + public void Zero_Should_Be_Zero() + { + var zero = BigIntValue.Zero; + Assert.Equal("0", zero.Value); + } + + [Fact] + public void One_Should_Be_One() + { + var one = BigIntValue.One; + Assert.Equal("1", one.Value); + } + + [Fact] + public void BigIntValue_FromBigEndianBytes_Should_Work() + { + var bytes = new byte[] { 0x01, 0x00 }; // 256 in big endian + var bigIntValue = BigIntValue.FromBigEndianBytes(bytes); + Assert.Equal("256", bigIntValue.Value); + } + + [Fact] + public void ToBigEndianBytes_Should_Work() + { + var bigIntValue = new BigIntValue { Value = "256" }; + var bytes = bigIntValue.ToBigEndianBytes(); + Assert.Equal(new byte[] { 0x01, 0x00 }, bytes); + } + + [Theory] + [InlineData("123", "123", 0)] + [InlineData("123", "456", -1)] + [InlineData("456", "123", 1)] + public void CompareTo_Should_Correctly_Compare(string a, string b, int expected) + { + var bigIntValueA = new BigIntValue { Value = a }; + var bigIntValueB = new BigIntValue { Value = b }; + + Assert.Equal(expected, bigIntValueA.CompareTo(bigIntValueB)); + } + + [Fact] + public void Implicit_Conversion_From_String_Should_Work() + { + BigIntValue bigIntValue = "123"; + Assert.Equal("123", bigIntValue.Value); + } + + [Fact] + public void Implicit_Conversion_From_Long_Should_Work() + { + BigIntValue bigIntValue = 456L; + Assert.Equal("456", bigIntValue.Value); + } + + [Fact] + public void Addition_Operator_Should_Work() + { + BigIntValue a = "123"; + BigIntValue b = "456"; + BigIntValue result = a + b; + Assert.Equal("579", result.Value); + } + + [Fact] + public void Subtraction_Operator_Should_Work() + { + BigIntValue a = "123"; + BigIntValue b = "23"; + BigIntValue result = a - b; + Assert.Equal("100", result.Value); + } + + [Fact] + public void Multiplication_Operator_Should_Work() + { + BigIntValue a = "10"; + BigIntValue b = "20"; + BigIntValue result = a * b; + Assert.Equal("200", result.Value); + } + + [Fact] + public void Modulus_Operator_Should_Work() + { + BigIntValue a = "10"; + BigIntValue b = "3"; + BigIntValue result = a % b; + Assert.Equal("1", result.Value); + } + + [Fact] + public void Equality_Operator_Should_Work() + { + BigIntValue a = "123"; + BigIntValue b = "123"; + Assert.True(a == b); + + BigIntValue c = "456"; + Assert.False(a == c); + } + + [Fact] + public void Inequality_Operator_Should_Work() + { + BigIntValue a = "123"; + BigIntValue b = "456"; + Assert.True(a != b); + + BigIntValue c = "123"; + Assert.False(a != c); + } + + [Fact] + public void LessThanOperator_Should_Work() + { + BigIntValue a = "123"; + BigIntValue b = "456"; + Assert.True(a < b); + Assert.False(b < a); + } + + [Fact] + public void GreaterThanOperator_Should_Work() + { + BigIntValue a = "456"; + BigIntValue b = "123"; + Assert.True(a > b); + Assert.False(b > a); + } + + [Fact] + public void LessThanOrEqualOperator_Should_Work() + { + BigIntValue a = "123"; + BigIntValue b = "123"; + BigIntValue c = "456"; + Assert.True(a <= b); + Assert.True(a <= c); + Assert.False(c <= a); + } + + [Fact] + public void GreaterThanOrEqualOperator_Should_Work() + { + BigIntValue a = "123"; + BigIntValue b = "123"; + BigIntValue c = "456"; + Assert.True(a >= b); + Assert.True(c >= a); + Assert.False(a >= c); + } + + [Theory] + [InlineData("0", 0)] + [InlineData("123456789", 123456789)] + [InlineData("-987654321", -987654321)] + [InlineData("1_000_000_000", 1000000000)] + [InlineData("-1_234_567", -1234567)] + public void ConvertStringToBigInteger_ValidStrings_Should_ParseCorrectly(string input, long expected) + { + BigIntValue bigIntValue = input; + BigInteger result = bigIntValue; // Implicit conversion to BigInteger + Assert.Equal(new BigInteger(expected), result); + } + +} \ No newline at end of file diff --git a/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs b/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs index 67e9db0b83..d72f7d6d4d 100644 --- a/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs +++ b/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs @@ -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_TransactionResultWithBVP_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 }); + + // Check transaction status + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResultWithBVP?transactionId={transactionHex}"); + response.StatusWithBVP.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()